ptp-pack.c revision 3d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1
1a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij/* ptp-pack.c
2a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij *
3a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
43d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * Copyright (C) 2003-2014 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
219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij * Boston, MA  02110-1301  USA
23a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij */
24a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij
25b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/* currently this file is included into ptp.c */
26eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#ifdef HAVE_LIMITS_H
289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#include <limits.h>
299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#endif
309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#ifndef UINT_MAX
319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij# define UINT_MAX 0xFFFFFFFF
329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#endif
333d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
34a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij#include <iconv.h>
356db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
36a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
37b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
38eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16p (PTPParams *params, uint16_t var)
39eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
40eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole16(var):htobe16(var));
41eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
42eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
43b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
44eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32p (PTPParams *params, uint32_t var)
45eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
46eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?htole32(var):htobe32(var));
47eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
48eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
49b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
50eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod16ap (PTPParams *params, unsigned char *a, uint16_t val)
51eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
52eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
53b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole16a(a,val);
54e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
55eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe16a(a,val);
56eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
57eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
58b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
59eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijhtod32ap (PTPParams *params, unsigned char *a, uint32_t val)
60eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
61eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (params->byteorder==PTP_DL_LE)
62b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htole32a(a,val);
63e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
64eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		htobe32a(a,val);
65eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
66eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
67abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline void
68abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijhtod64ap (PTPParams *params, unsigned char *a, uint64_t val)
69abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
70abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	if (params->byteorder==PTP_DL_LE)
71abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htole64a(a,val);
72e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	else
73abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htobe64a(a,val);
74abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
75abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
76b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
77eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh16p (PTPParams *params, uint16_t var)
78eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
79eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16toh(var):be16toh(var));
80eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
81eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
82b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
83eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleijdtoh32p (PTPParams *params, uint32_t var)
84eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
85eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32toh(var):be32toh(var));
86eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
87eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
88abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijstatic inline uint64_t
89abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleijdtoh64p (PTPParams *params, uint64_t var)
90abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij{
91abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64toh(var):be64toh(var));
92abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij}
93abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
94b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint16_t
951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh16ap (PTPParams *params, const unsigned char *a)
96eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
97eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le16atoh(a):be16atoh(a));
98eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
99eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
100b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh32ap (PTPParams *params, const unsigned char *a)
102eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
103eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return ((params->byteorder==PTP_DL_LE)?le32atoh(a):be32atoh(a));
104eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
105eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
106b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint64_t
1071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijdtoh64ap (PTPParams *params, const unsigned char *a)
108eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
109abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	return ((params->byteorder==PTP_DL_LE)?le64atoh(a):be64atoh(a));
110eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
111eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
112b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod8a(a,x)	*(uint8_t*)(a) = x
113b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16a(a,x)	htod16ap(params,a,x)
114b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32a(a,x)	htod32ap(params,a,x)
115abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64a(a,x)	htod64ap(params,a,x)
116b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod16(x)	htod16p(params,x)
117b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define htod32(x)	htod32p(params,x)
118abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define htod64(x)	htod64p(params,x)
119b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
120b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh8a(x)	(*(uint8_t*)(x))
121b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16a(a)	dtoh16ap(params,a)
122b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32a(a)	dtoh32ap(params,a)
123b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh64a(a)	dtoh64ap(params,a)
124b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh16(x)	dtoh16p(params,x)
125b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define dtoh32(x)	dtoh32p(params,x)
126abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij#define dtoh64(x)	dtoh64p(params,x)
127b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
128b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
129b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline char*
130b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint8_t *len)
131eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
132a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint8_t length;
133a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	uint16_t string[PTP_MAXSTRLEN+1];
134a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* allow for UTF-8: max of 3 bytes per UCS-2 char, plus final null */
135e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	char loclstr[PTP_MAXSTRLEN*3+1];
136a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	size_t nconv, srclen, destlen;
137a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	char *src, *dest;
138a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
139a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
140a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*len = length;
141a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (length == 0)		/* nothing to do? */
142a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		return(NULL);
143a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
144a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* copy to string[] to ensure correct alignment for iconv(3) */
145a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(string, &data[offset+1], length * sizeof(string[0]));
146a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
147a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[0] = '\0';
148e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij
149a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* convert from camera UCS-2 to our locale */
150a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	src = (char *)string;
151a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	srclen = length * sizeof(string[0]);
152a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	dest = loclstr;
153a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	destlen = sizeof(loclstr)-1;
1546db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	nconv = (size_t)-1;
1553d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
156d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	if (params->cd_ucs2_to_locale != (iconv_t)-1)
157d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij		nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
1586db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
159a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (nconv == (size_t) -1) { /* do it the hard way */
160a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		int i;
161a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		/* try the old way, in case iconv is broken */
162a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		for (i=0;i<length;i++) {
163a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			if (dtoh16a(&data[offset+1+2*i])>127)
164a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = '?';
165a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			else
166a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
167eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
168a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		dest = loclstr+length;
169eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
170a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*dest = '\0';
171a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
172a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	return(strdup(loclstr));
173a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
174a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
175a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline int
176a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijucs2strlen(uint16_t const * const unicstr)
177a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
17896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int length = 0;
179a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
180a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Unicode strings are terminated with 2 * 0x00 */
181a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for(length = 0; unicstr[length] != 0x0000U; length ++);
182a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return length;
183eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
184eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
185a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
186b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
187b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
188eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
18996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int packedlen = 0;
190a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint16_t ucs2str[PTP_MAXSTRLEN+1];
191a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *ucs2strp = (char *) ucs2str;
192a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convlen = strlen(string);
193a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
194a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
195a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
1963d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
197d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij	if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
1986db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t nconv;
1996db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
2006db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		char *stringp = string;
2016db174f4d18af574fab991309e11010aa0eb4543Linus Walleij
2026db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
2036db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			&ucs2strp, &convmax);
2046db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		if (nconv == (size_t) -1)
2056db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[0] = 0x0000U;
206d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	} else
207d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij#endif
2086db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	{
2092ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int i;
2102ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij
2116db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		for (i=0;i<convlen;i++) {
2126db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[i] = string[i];
2136db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		}
2146db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		ucs2str[convlen] = 0;
2156db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	}
216a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/*
217a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
218a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 *      why do we need ucs2strlen()?
219a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 */
220a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
221a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
222a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
223a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
224a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
225958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
2267f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
227a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
228a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
229a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
230958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
231958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
232048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
233eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
234eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
235a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
236735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
237a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
2388b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
239a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
240a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
241d47b9218023a6b943a93faa743712ae072cba85cRichard Low
242d47b9218023a6b943a93faa743712ae072cba85cRichard Low	if (string == NULL)
243d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
244d47b9218023a6b943a93faa743712ae072cba85cRichard Low	else
245d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
246d47b9218023a6b943a93faa743712ae072cba85cRichard Low
247958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
248958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
249048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
250a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
251735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
252735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
253a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
254735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
255a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
256735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
257a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
258a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
259a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
260b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
2613d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint32_t **array)
262eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
263eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2653d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset >= datalen)
2663d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
2673d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
2683d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t) > datalen)
2693d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
2703d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
2719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*array = NULL;
272eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
2739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (n >= UINT_MAX/sizeof(uint32_t))
2749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
2759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!n)
2769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
2773d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
2783d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t)*(n+1) > datalen) {
2793d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)*(n+1) , datalen);
2803d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
2813d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
2823d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
283eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
2849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	for (i=0;i<n;i++)
285eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
286eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
287eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
288eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
289b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
290f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
291f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
292f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
293f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
294f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
295f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
296f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
297f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
298f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
299f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
300f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
301f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
3023d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint16_t **array)
303eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
304eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
305eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
3069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*array = NULL;
307eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
3089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (n >= UINT_MAX/sizeof(uint16_t))
3099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
3109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!n)
3119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
3123d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t) > datalen)
3133d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
3143d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t)+sizeof(uint16_t)*n > datalen) {
3153d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)+n*sizeof(uint16_t) , datalen);
3163d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
3173d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
3199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	for (i=0;i<n;i++)
320eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
321eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
323eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
324eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
325eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
326eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
327eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
328eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
329eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
330eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
333b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
334b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
335eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
336eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
337eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
3387e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
339d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (!data) return;
340d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij	if (datalen < 12) return;
3417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
343eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
344eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
345eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
346eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionDesc =
347eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
348eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_VendorExtensionDesc, &len);
349eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
350eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->FunctionalMode =
351eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
352eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
353eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
355eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
356eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
357eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
358eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3593d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
360eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
361eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
362eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
363eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
364eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3653d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
366eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
367eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
368eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
369eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3703d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
371eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
372eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
373eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
374eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3753d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
376eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
377eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
378eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
379eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
380eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
381eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
382eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
383eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
384eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
390eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
391eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
393eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
394a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
3952ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleijinline static void
396a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijptp_free_DI (PTPDeviceInfo *di) {
3973d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->SerialNumber);
3983d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->DeviceVersion);
3993d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->Model);
4003d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->Manufacturer);
4013d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->ImageFormats);
4023d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->CaptureFormats);
4033d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->VendorExtensionDesc);
4043d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->OperationsSupported);
4053d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->EventsSupported);
4063d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->DevicePropertiesSupported);
407a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij}
4087e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4097e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij/* EOS Device Info unpack */
4107e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijstatic inline void
4117e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
4127e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij{
4132ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int totallen = 4;
41496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
41596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	memset (di,0, sizeof(*di));
4167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (datalen < 8) return;
4177e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4187e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	/* uint32_t struct len - ignore */
4197e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
4203d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		totallen, datalen, &di->EventsSupported);
4217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->EventsSupported) return;
4227e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
4237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
4247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4257e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
4263d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		totallen, datalen, &di->DevicePropertiesSupported);
4277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->DevicePropertiesSupported) return;
4287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
4297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (totallen >= datalen) return;
4307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->unk_len = ptp_unpack_uint32_t_array(params, data,
4323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		totallen, datalen, &di->unk);
4337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (!di->unk) return;
4347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->unk_len*sizeof(uint32_t)+4;
4357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	return;
4367e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij}
4370d762ccc39331608119dd0267021b165e22de499Linus Walleij
4380d762ccc39331608119dd0267021b165e22de499Linus Walleijstatic inline void
4390d762ccc39331608119dd0267021b165e22de499Linus Walleijptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
4400d762ccc39331608119dd0267021b165e22de499Linus Walleij{
4410d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->EventsSupported);
4420d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->DevicePropertiesSupported);
4430d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->unk);
4440d762ccc39331608119dd0267021b165e22de499Linus Walleij}
445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
450b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
451b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
453f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (len) {
4543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, len, &oh->Handler);
455f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	} else {
456f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = 0;
457f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->Handler = NULL;
458f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
464eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
465b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
466b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
467eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
4682ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	if (!data || !len) {
46996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		sids->n = 0;
47096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		sids->Storage = NULL;
47196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		return;
47296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij        }
4733d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids, len, &sids->Storage);
474eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
475eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
476eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
477eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
478eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
479eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
480eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
481eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
482eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
486b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
487b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
488eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
489eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
4913d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (len < 26) return;
492eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
493eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
494eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
495eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
496eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
4983d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
4993d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* FIXME: check more lengths here */
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription, &storagedescriptionlen);
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
503eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
504eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
506eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
507eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
508eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
509eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
510eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
511eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
512eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
521eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
522eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
523eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
524eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
525eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
526eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
527a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* the max length assuming zero length dates. We have need 3 */
528a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* bytes for these. */
529a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
530a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
531b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
532b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
533eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
534b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
535eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
536eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
537a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
5380546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	oidata=malloc(PTP_oi_MaxLen + params->ocs64*4);
5390546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	*oidataptr=oidata;
540eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
541eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
542eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
543eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
5440546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	memset (oidata, 0, PTP_oi_MaxLen + params->ocs64*4);
545eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
546eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
547eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
548eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
5490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (params->ocs64)
5500546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		oidata += 4;
551eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
552eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
553eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
554eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
555eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
556eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
557eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
558eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
559eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
560eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
561eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
562eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
563eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
564eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
565eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
566eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
567eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
568eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
569eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
570eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
571eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
572eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
573eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
574eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
575eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
576eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
577eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
578eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
579eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
580eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
581eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
582eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
583eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
584eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
585eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
586eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
587eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
588eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
589eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
590eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
5910546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
592eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
593eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
5943bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleijstatic time_t
5956db174f4d18af574fab991309e11010aa0eb4543Linus Walleijptp_unpack_PTPTIME (const char *str) {
5963bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char ptpdate[40];
5973bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char tmp[5];
598a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	size_t  ptpdatelen;
5993bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	struct tm tm;
6003bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
6013bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	if (!str)
6023bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
6033bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	ptpdatelen = strlen(str);
6047e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen >= sizeof (ptpdate)) {
6056db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
6063bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
6077e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
6087e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen<15) {
6096db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
6103bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
6117e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
612a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	strncpy (ptpdate, str, sizeof(ptpdate));
613a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	ptpdate[sizeof(ptpdate) - 1] = '\0';
6143bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
6153bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	memset(&tm,0,sizeof(tm));
6163bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate, 4);
6173bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[4] = 0;
6183bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_year=atoi (tmp) - 1900;
6193bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 4, 2);
6203bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6213bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mon = atoi (tmp) - 1;
6223bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 6, 2);
6233bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6243bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mday = atoi (tmp);
6253bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 9, 2);
6263bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6273bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_hour = atoi (tmp);
6283bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 11, 2);
6293bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6303bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_min = atoi (tmp);
6313bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 13, 2);
6323bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6333bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_sec = atoi (tmp);
634e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	tm.tm_isdst = -1;
6353bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	return mktime (&tm);
6363bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij}
6373bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
638b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
640eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
641eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
642eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
643eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
644eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6453d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (len < PTP_oi_SequenceNumber)
6463d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return;
6473d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
6483d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	oi->Filename = oi->Keywords = NULL;
6493d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
6503d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* FIXME: also handle length with all the strings at the end */
651eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
652eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
653eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
654eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
6550546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
6560546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
6570546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
6580546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		params->ocs64 = 1;
6590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		data += 4;
6600546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
661eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
662eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
663eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
664eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
665eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
666eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
667eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
668eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
669eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
670eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
671eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
6720546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
673eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, &filenamelen);
674eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
675eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
676eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2+1, &capturedatelen);
677eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
678eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
679eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
6806db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
681eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
682eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6833bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	/* now the modification date ... */
684eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
685eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
686eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		+capturedatelen*2+2,&capturedatelen);
6876db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
688eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
689eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
690eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
691eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
692b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
693b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
694b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
695b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
696b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
697eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
698eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
699b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
7009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int n,j;				\
701b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
702b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
704b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
705b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
7069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (n >= UINT_MAX/sizeof(val->a.v[0]))		\
7079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;				\
708b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
709b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
710b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
711b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
712b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
713b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
714eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
7152ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleijstatic inline unsigned int
716b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
7173d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	PTPParams *params, unsigned char* data, unsigned int *offset, unsigned int total,
718b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
719b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
720eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
721b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
722b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
723b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
724b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
725b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
726b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
727b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
728b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
729b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
730b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
731b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
732b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
733b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
734b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
739abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
740abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->i64,dtoh64a);
741abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
742abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
743abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->u64,dtoh64a);
744abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
745abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
746037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
747037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
748037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
749037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
750037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
751037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
752037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
753037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
754037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
755037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
756037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
759b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
760b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
762b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
765b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
766b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
767b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
768b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
772b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
775abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
776abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,u64,dtoh64a);
777abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
778abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
779abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,i64,dtoh64a);
780abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		value->str = ptp_unpack_string(params,data,*offset,&len);
787b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
788b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
789deddc3490b3084b802737017982285bfa58b382fLinus Walleij			return 1;
790b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
791eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
792037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
793037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
794b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
795b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
796eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
797eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
798eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
799eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
800eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
801eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
802eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
803eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
804b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
806eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
8079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int offset = 0, ret;
808eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
810eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
811eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
812eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
813deddc3490b3084b802737017982285bfa58b382fLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
815b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
818deddc3490b3084b802737017982285bfa58b382fLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
819deddc3490b3084b802737017982285bfa58b382fLinus Walleij		return 1;
820b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
822b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
823b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
824b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
825b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
826b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
827b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
828b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
829b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
830b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
831b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
832b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
833eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
834eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
835b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
836b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
837b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
838b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
839b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
840b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
841b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
842eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
843b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
844b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
845eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
846b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
847b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
848b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
849b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
850b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
851b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
852b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
853b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
854b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
855b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
856b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
857b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
858b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
859b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
860b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
861b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
862b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
863b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
864b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
865b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
866eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
867b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
868eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
869eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
870b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
871b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
872b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
873b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
874b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
875eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
876eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
8779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij/* Device Property pack/unpack */
8789783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_DevicePropertyCode	0
8799783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_DataType		2
8809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_GetSet		4
8819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_Unknown		5
8829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_FactoryDefaultValue	6
8839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
8849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijstatic inline int
8859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset)
8869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij{
8879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int ret;
8883d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if 0
8893d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unsigned int unk1, unk2;
8903d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#endif
8919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
8929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	memset (dpd, 0, sizeof(*dpd));
8939783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]);
8949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]);
8959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
8969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#if 0
8973d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* get set ? */
8983d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unk1 = dtoh8a(&data[PTP_dpd_Sony_GetSet]);
8993d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unk2 = dtoh8a(&data[PTP_dpd_Sony_Unknown]);
9003d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug (params, "prop 0x%04x, datatype 0x%04x, unk1 %d unk2 %d", dpd->DevicePropertyCode, dpd->DataType, unk1, unk2);
9019783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#endif
9029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->GetSet=1;
9039783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9049783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
9059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*poffset = PTP_dpd_Sony_FactoryDefaultValue;
9079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
9089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!ret) goto outofmemory;
9099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (*poffset == dpdlen))
9109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 1;
9119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->CurrentValue, dpd->DataType);
9129783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!ret) goto outofmemory;
9139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	/* if offset==0 then Data Type format is not supported by this
9159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	   code or the Data Type is a string (with two empty strings as
9169783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
9179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	   not present. */
9189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (*poffset==PTP_dpd_Sony_FactoryDefaultValue)
9209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 1;
9219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->FormFlag=dtoh8a(&data[*poffset]);
9239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*poffset+=sizeof(uint8_t);
9249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	switch (dpd->FormFlag) {
9269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	case PTP_DPFF_Range:
9279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
9289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!ret) goto outofmemory;
9299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
9309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!ret) goto outofmemory;
9319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
9329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!ret) goto outofmemory;
9339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		break;
9349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	case PTP_DPFF_Enumeration: {
9359783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		int i;
9369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
9379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		N = dtoh16a(&data[*poffset]);
9389783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		*poffset+=sizeof(uint16_t);
9399783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
9409783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
9419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			goto outofmemory;
9429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
9449783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		for (i=0;i<N;i++) {
9459783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
9469783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
9489783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 * specifies an enumeration with N in wrong endian
9499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
9509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 * the end of the packet.
9519783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 */
9529783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (!ret) {
9539783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				if (!i)
9549783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					goto outofmemory;
9559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
9569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				break;
9579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
9589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
9599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
9609783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	}
9619783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#undef N
9629783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	return 1;
9639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijoutofmemory:
9649783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ptp_free_devicepropdesc(dpd);
9659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	return 0;
9669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij}
9679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
968d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijstatic inline void
969d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijduplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
9709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (type == PTP_DTC_STR) {
9719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (src->str)
9729783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			dst->str = strdup(src->str);
9739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		else
9749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			dst->str = NULL;
9759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return;
9769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	}
9779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
978d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	if (type & PTP_DTC_ARRAY_MASK) {
9792ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int i;
980d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
981d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->a.count = src->a.count;
9829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		dst->a.v = malloc (sizeof(src->a.v[0])*src->a.count);
983d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		for (i=0;i<src->a.count;i++)
984d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij			duplicate_PropertyValue (&src->a.v[i], &dst->a.v[i], type & ~PTP_DTC_ARRAY_MASK);
985d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		return;
986d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
987d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	switch (type & ~PTP_DTC_ARRAY_MASK) {
988d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT8:	dst->i8 = src->i8; break;
989d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT8:	dst->u8 = src->u8; break;
990d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT16:	dst->i16 = src->i16; break;
991d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT16:	dst->u16 = src->u16; break;
992d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT32:	dst->i32 = src->i32; break;
993d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT32:	dst->u32 = src->u32; break;
994d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT64:	dst->u64 = src->u64; break;
995d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT64:	dst->i64 = src->i64; break;
996d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij#if 0
997d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT128:	dst->i128 = src->i128; break;
998d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT128:	dst->u128 = src->u128; break;
999d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij#endif
1000d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	default:		break;
1001d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
1002d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	return;
1003d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij}
1004d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1005d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijstatic inline void
1006d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijduplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
1007d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	int i;
1008d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1009d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->DevicePropertyCode	= src->DevicePropertyCode;
1010d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->DataType		= src->DataType;
1011d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->GetSet		= src->GetSet;
1012d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
10139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, src->DataType);
10149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, src->DataType);
1015d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1016d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->FormFlag		= src->FormFlag;
1017d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	switch (src->FormFlag) {
1018d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_Range:
1019d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.MinimumValue, &dst->FORM.Range.MinimumValue, src->DataType);
1020d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.MaximumValue, &dst->FORM.Range.MaximumValue, src->DataType);
1021d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.StepSize,     &dst->FORM.Range.StepSize,     src->DataType);
1022d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
1023d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_Enumeration:
1024d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->FORM.Enum.NumberOfValues = src->FORM.Enum.NumberOfValues;
1025d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->FORM.Enum.SupportedValue = malloc (sizeof(dst->FORM.Enum.SupportedValue[0])*src->FORM.Enum.NumberOfValues);
1026d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		for (i = 0; i<src->FORM.Enum.NumberOfValues ; i++)
1027d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij			duplicate_PropertyValue (&src->FORM.Enum.SupportedValue[i], &dst->FORM.Enum.SupportedValue[i], src->DataType);
1028d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
1029d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_None:
1030d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
1031d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
1032d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij}
1033d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1034b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
1035b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
1036b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
1037b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
1038eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1039b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
1040b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
1041eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
10422ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int offset=0, ret;
1043b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1044b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
1045b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
1046b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
1047b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
1048b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1049b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
1050b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
1051b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
1052b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1053b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
1054b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
1055b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1056b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
1057b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
1058b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1059b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
1060b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
1061b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
1062b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
1063b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
1064b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
1065b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
1066b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
1067b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1068b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
10692ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int i;
1070b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
1071b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
1072b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
1073b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1074b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
1075b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
1076b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1077b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1078b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
1079b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
1080b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1081b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
1082b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
1083b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
1084b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
1085b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
1086b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
1087b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
1088b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
1089b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
1090b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
1091b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
1092b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
1093b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
1094b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
1095eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
1096b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
1097b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
1098b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
1099b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
1100eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1101eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1102eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1103b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1104b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
1105eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1106b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
1107eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
11082ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int i;
1109eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1110eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
1111b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
1112b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
1113b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1114b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
1115b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1116b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
1117b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
1118b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1119b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
1120b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1121b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
1122b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
1123b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1124b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
1125b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1126b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
1127b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
1128b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1129b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
1130b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1131b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
1132b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
1133b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1134b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
1135b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1136b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
1137b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
1138b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1139b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
1140b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1141abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
1142abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(int64_t);
1143abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1144abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->i64);
1145abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1146abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
1147abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint64_t);
1148abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1149abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->u64);
1150abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1151b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
1152b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
1153b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1154b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1155b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1156cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
1157b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1158b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
1159b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
1160b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1161b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1162b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1163cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
1164b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1165b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
1166b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
1167b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1168b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1169b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1170cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
1171b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1172b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
1173b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
1174b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1175b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1176b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1177cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
1178b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1179b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
1180b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
1181b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1182b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1183b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1184cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
1185b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1186b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
1187b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
1188b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1189b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1190b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1191cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
1192b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1193abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
1194abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
1195abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1196abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
1197abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
1198cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
1199abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1200abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
1201abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
1202abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1203abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
1204abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
1205cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
1206abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1207b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
1208b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
1209735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
1210eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
1211b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1212eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
1213eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
1214eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
121599310d4445697da39f22dff35457c75e35e97171Linus Walleij}
121699310d4445697da39f22dff35457c75e35e97171Linus Walleij
121799310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
121899310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
12191e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
122099310d4445697da39f22dff35457c75e35e97171Linus Walleij{
122199310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
12221e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *propitr;
122399310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
122499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
122539b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
122699310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
122799310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
122899310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
122999310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
123099310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
123199310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
123299310d4445697da39f22dff35457c75e35e97171Linus Walleij
123399310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
12341e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	propitr = props;
12351e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
12366c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
123739b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
123899310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
123999310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
124099310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
124199310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
124299310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
124399310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
124499310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
124599310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
124699310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
124799310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
124899310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
12491e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		propitr ++;
125099310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
125199310d4445697da39f22dff35457c75e35e97171Linus Walleij
125299310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
125399310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
125499310d4445697da39f22dff35457c75e35e97171Linus Walleij
125599310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
125699310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
125799310d4445697da39f22dff35457c75e35e97171Linus Walleij
125899310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
125999310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
126099310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
12616c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
126299310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
126399310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
126499310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
126599310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
126699310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
126799310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
126899310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
126999310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
127099310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
127199310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
127299310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
127399310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
1274eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1275eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
12761e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijstatic int
12771e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij_compare_func(const void* x, const void *y) {
12781e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *px = x;
12791e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *py = y;
12801e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
12811e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	return px->ObjectHandle - py->ObjectHandle;
12821e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij}
12831e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
12848d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
12851e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
12868d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
1287277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
12881e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *props = NULL;
12892ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int offset = 0, i;
1290277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1291277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	if (prop_count == 0) {
12921e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		*pprops = NULL;
1293277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
1294277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1295d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1296277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
12973bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	len -= sizeof(uint32_t);
12981e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	props = malloc(prop_count * sizeof(MTPProperties));
12991e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	if (!props) return 0;
1300277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
13013bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		if (len <= 0) {
1302d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
13033bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL", i);
13043bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1305d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			qsort (props, i, sizeof(MTPProperties),_compare_func);
1306d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			*pprops = props;
13073bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			return i;
13083bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		}
13091e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].ObjectHandle = dtoh32a(data);
1310277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
1311277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
1312277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
13131e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].property = dtoh16a(data);
1314277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1315277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1316277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
13171e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].datatype = dtoh16a(data);
1318277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1319277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1320277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1321277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
13221e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype);
1323277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
1324277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
1325277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
13261e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
13271e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	*pprops = props;
1328277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
13298d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
13308d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
1331eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1332eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
1333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1334eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1335eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1336eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
1337eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
1338eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
1339eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
1340eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
1341eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
1342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
1343eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1344b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
13457e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1346eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
13479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int	length;
13487e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	type;
13497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
1350eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1351eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
13527e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	memset(ec,0,sizeof(*ec));
13539783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
13547e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	length=dtoh32a(&data[PTP_ec_Length]);
13559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (length > len) {
13569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ptp_debug (params, "length %d in container, but data only %d bytes?!", length, len);
13579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return;
13589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	}
13597e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	type = dtoh16a(&data[PTP_ec_Type]);
1360b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
13617e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Code=dtoh16a(&data[PTP_ec_Code]);
13627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
13637e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
13647e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (type!=PTP_USB_CONTAINER_EVENT) {
13657e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
13667e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		return;
13677e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
13687e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param1+4)) {
13697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
13707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=1;
13717e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
13727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param2+4)) {
13737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
13747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=2;
13757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
13767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param3+4)) {
13777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
13787e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=3;
13797e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
1380eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1381eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1382eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1383eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
1384eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1388eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1390eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1391eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1393b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1394b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1395eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1396eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1397eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1402b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1405b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1406b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1407b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
140896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij/*
140996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij    PTP Canon EOS Folder Entry unpack
141096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0: 00 00 08 a0     objectid
141196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij4: 01 00 02 00     storageid
141296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij8: 01 30 00 00     ofc
141396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij12: 01 00
141496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij14: 00 00
141596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij16: 11 00 00 00
141696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij20: 00 00 00 00
141796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij24: 00 00 00 80
141896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij28: 00 00 08 a0
141996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij32: 4d 49 53 43-00 00 00 00 00 00 00 00     name
142096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij00 00 00 00
142196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij84 bc 74 46     objectime
142296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
142396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
142496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij(normal PTP GetObjectInfo)
142596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus WalleijObjectInfo for 'IMG_0199.JPG':
142696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  Object ID: 0x92740c72
142796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  StorageID: 0x00020001
142896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectFormat: 0x3801
142996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ProtectionStatus: 0x0000
143096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectCompressedSize: 2217241
143196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbFormat: 0x3808
143296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbCompressedSize: 5122
143396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixWidth: 160
143496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixHeight: 120
143596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixWidth: 4000
143696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixHeight: 3000
143796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImageBitDepth: 24
143896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ParentObject: 0x92740000
143996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationType: 0x0000
144096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationDesc: 0x00000000
144196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  SequenceNumber: 0x00000000
144296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ModificationDate: 0x4d985ff0
144396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  CaptureDate: 0x4d985ff0
144496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
144596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0010  38 00 00 00  Size of this entry
144696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0014  72 0c 74 92  OID
144796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0018  01 00 02 00  StorageID
144896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij001c  01 38 00 00  OFC
14493d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner0020  00 00 00 00 ??
14503d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner0024  21 00 00 00  flags (4 bytes? 1 byte?)
145196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0028  19 d5 21 00  Size
145296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij002c  00 00 74 92  ?
145396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0030  70 0c 74 92  OID
145496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0034  49 4d 47 5f-30 31 39 39 2e 4a 50 47  IMG_0199.JPG
145596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0040  00 00 00 00
145696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0044  10 7c 98 4d Time
145796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
145896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
145996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij*/
146096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectHandle		0
146196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_StorageID		4
146296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectFormatCode	8
14633d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#define PTP_cefe_Flags			16
146496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectSize		20
146596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Filename		32
146696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Time			48
146796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
146896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijstatic inline void
146996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
147096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij{
147196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int i;
147296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
147396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cefe_ObjectHandle]);
147496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cefe_ObjectFormatCode]);
147596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Flags=dtoh8a(&data[PTP_cefe_Flags]);
147696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cefe_ObjectSize]);
147796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cefe_Time]);
147896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
147996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		fe->Filename[i]=(char)data[PTP_cefe_Filename+i];
148096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij}
148196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
148296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
14831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint16_t
14841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
14851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
14861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	/*
14870546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this:
14881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: number of entries / generated files (1 or 2)
14891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: size of this entry in bytes (most likely allways 0x10)
14901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image type (1 == JPG, 6 == RAW)
14910546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3)
14921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
14930546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  If the number of entries is 2 the last 4 uint32 repeat.
14941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
14951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  example:
14961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		0: 0x       1
14971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		1: 0x      10
14981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		2: 0x       6
14991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		3: 0x       1
15001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		4: 0x       4
15011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15020546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniently
15031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  use the available enumeration facilities (look-up table). The image size and compression
15041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
15051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
15061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  The above example would result in the value 0x1400.
15070546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
15080546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2
15090546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow.
15101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  */
15111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	const unsigned char* d = *data;
15131a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = dtoh32a( d );
15141a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t l, s1, c1, s2 = 0, c2 = 0;
15151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n != 1 && n !=2) {
15171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
15181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
15191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
15201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	l = dtoh32a( d+=4 );
15221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (l != 0x10) {
15231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
15241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
15251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
15261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15271a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	d+=4; /* skip type */
15281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	s1 = dtoh32a( d+=4 );
15291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	c1 = dtoh32a( d+=4 );
15301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15311a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n == 2) {
15321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		l = dtoh32a( d+=4 );
15331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		if (l != 0x10) {
15341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
15351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			return 0;
15361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		}
15371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		d+=4; /* skip type */
15381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		s2 = dtoh32a( d+=4 );
15391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		c2 = dtoh32a( d+=4 );
15401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
15411a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	*data = (unsigned char*) d+4;
15431a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15440546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* deal with S1/S2/S3 JPEG sizes, see above. */
15450546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s1 >= 0xe )
15460546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s1--;
15470546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s2 >= 0xe )
15480546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s2--;
15490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
15501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
15511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
15521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint32_t
15541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
15551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
15561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = (value & 0xFF) ? 2 : 1;
15571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t s = 4 + 0x10 * n;
15581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15591a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if( !data )
15601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return s;
15611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15620546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
15630546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
15641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=0, n);
15651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, 0x10);
15661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
15670546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF));
15681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, (value >> 8) & 0xF);
15691a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15701a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n==2) {
15711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, 0x10);
15721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
15730546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF));
15741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, (value >> 0) & 0xF);
15751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
15761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#undef PACK_5DM3_SMALL_JPEG_SIZE
15780546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
15790546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return s;
15800546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
15810546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
15823d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner/* 00: 32 bit size
15833d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 04: 16 bit subsize
15843d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 08: 16 bit version (?)
15853d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 0c: 16 bit focus_points_in_struct
15863d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 10: 16 bit focus_points_in_use
15873d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 14: variable arrays:
15883d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit sizex, 16 bit sizey
15893d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit othersizex, 16 bit othersizey
15903d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array height[focus_points_in_struct]
15913d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array width[focus_points_in_struct]
15923d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array offsetheight[focus_points_in_struct] middle is 0
15933d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array offsetwidth[focus_points_in_struct] middle is ?
15943d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * bitfield of selected focus points, starting with 0 [size focus_points_in_struct in bits]
15953d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * unknown stuff , likely which are active
15963d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 16 bit 0xffff
15973d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner *
15983d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * size=NxN,size2=NxN,points={NxNxNxN,NxNxNxN,...},selected={0,1,2}
15993d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner */
16003d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerstatic inline char*
16013d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerptp_unpack_EOS_FocusInfoEx (PTPParams* params, unsigned char** data )
16023d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner{
16033d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t size 			= dtoh32a( *data );
16043d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t halfsize		= dtoh16a( (*data) + 4);
16053d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t version		= dtoh16a( (*data) + 6);
16063d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t focus_points_in_struct	= dtoh16a( (*data) + 8);
16073d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t focus_points_in_use	= dtoh16a( (*data) + 10);
16083d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t sizeX			= dtoh16a( (*data) + 12);
16093d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t sizeY			= dtoh16a( (*data) + 14);
16103d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t size2X			= dtoh16a( (*data) + 16);
16113d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t size2Y			= dtoh16a( (*data) + 18);
16123d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t i;
16133d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t maxlen;
16143d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	char	*str, *p;
16153d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16163d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* every focuspoint gets 4 (16 bit number and a x) and a ,*/
16173d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* inital things around lets say 100 chars at most.
16183d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	 * FIXME: check selected when we decode it */
16193d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	maxlen = focus_points_in_use*6*4 + focus_points_in_use + 100;
16203d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (halfsize != size-4) {
16213d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_error(params, "halfsize %d is not expected %d", halfsize, size-4);
16223d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return "bad size";
16233d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
16243d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (20 + focus_points_in_struct*8 + (focus_points_in_struct+7)/8 > size) {
16253d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_error(params, "size %d is too large for fp in struct %d", focus_points_in_struct*8 + 20 + (focus_points_in_struct+7)/8, size);
16263d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return "bad size 2";
16273d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
16283d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if 0
16293d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug(params,"d1d3 content:");
16303d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=0;i<size;i+=2)
16313d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_debug(params,"%d: %02x %02x", i, (*data)[i], (*data)[i+1]);
16323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#endif
16333d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug(params,"d1d3 version", version);
16343d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug(params,"d1d3 focus points in struct %d, in use %d", focus_points_in_struct, focus_points_in_use);
16353d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16363d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	str = (char*)malloc( maxlen );
16373d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (!str)
16383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return NULL;
16393d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p = str;
16403d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16413d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"eosversion=%d,size=%dx%d,size2=%dx%d,points={", version, sizeX, sizeY, size2X, size2Y);
16423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=0;i<focus_points_in_use;i++) {
16433d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t x = dtoh16a((*data) + focus_points_in_struct*4 + 20 + 2*i);
16443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t y = dtoh16a((*data) + focus_points_in_struct*6 + 20 + 2*i);
16453d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t w = dtoh16a((*data) + focus_points_in_struct*2 + 20 + 2*i);
16463d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t h = dtoh16a((*data) + focus_points_in_struct*0 + 20 + 2*i);
16473d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16483d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		p += sprintf(p,"{%d,%d,%d,%d}",x,y,w,h);
16493d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16503d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		if (i<focus_points_in_use-1)
16513d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			p += sprintf(p,",");
16523d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
16533d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"},select={");
16543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=0;i<focus_points_in_use;i++) {
16553d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		if ((1<<(i%7)) & ((*data)[focus_points_in_struct*8+20+i/8]))
16563d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			p+=sprintf(p,"%d,", i);
16573d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
16583d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16593d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"},unknown={");
16603d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=focus_points_in_struct*8+(focus_points_in_struct+7)/8+20;i<size;i++) {
16613d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		p+=sprintf(p,"%02x", (*data)[i]);
16623d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
16633d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"}");
16643d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	return str;
16653d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner}
16663d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16673d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
16680546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline char*
16690546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
16700546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
16710546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = dtoh32a( *data );
16720546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i;
16732ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	char* str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/
16740546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!str)
16750546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return str;
16760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	char* p = str;
16770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16780546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i < n; ++i)
16790546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
16800546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16810546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return str;
16820546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
16830546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16840546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline uint32_t
16850546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
16860546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
16870546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = strtoul(str, NULL, 16);
16880546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i, v;
16890546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16900546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!data)
16910546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return s;
16920546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16930546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i<n; i++)
16940546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	{
16950546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		v = strtoul(str, &str, 16);
1696a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij		str++; /* skip the ',' delimiter */
16970546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data + i*4, v);
16980546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
16990546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
17001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return s;
17011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
17021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1703b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1704f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij    PTP EOS Changes Entry unpack
1705f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij*/
1706f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Size		0
1707f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Type		4
1708f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1709f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Subtype	8	/* only for properties */
1710f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1711f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1712f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1713f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1714f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1715d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1716d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_ObjectID	8
1717d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_OFC		0x0c
1718d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Size		0x14
1719d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Name		0x1c
1720d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij
1721d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_ObjectAddedEx */
1722d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_ObjectID	8
1723d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_StorageID	0x0c
1724d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_OFC		0x10
1725d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Size		0x1c
1726d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Parent	0x20
1727d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Name		0x28
1728f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
17293d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerstatic PTPDevicePropDesc*
17303d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner_lookup_or_allocate_canon_prop(PTPParams *params, uint16_t proptype)
17313d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner{
17323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unsigned int j;
17333d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17343d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (j=0;j<params->nrofcanon_props;j++)
17353d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		if (params->canon_props[j].proptype == proptype)
17363d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			break;
17373d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (j<params->nrofcanon_props)
17383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return &params->canon_props[j].dpd;
17393d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17403d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (j)
17413d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
17423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	else
17433d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		params->canon_props = malloc(sizeof(params->canon_props[0]));
17443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].proptype = proptype;
17453d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].size = 0;
17463d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].data = NULL;
17473d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
17483d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].dpd.GetSet = 1;
17493d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
17503d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->nrofcanon_props = j+1;
17513d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	return &params->canon_props[j].dpd;
17523d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner}
17533d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
1755f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijstatic inline int
17569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **pce)
1757f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij{
1758f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	int	i = 0, entries = 0;
1759f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	unsigned char	*curdata = data;
17609783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	PTPCanon_changes_entry *ce;
1761f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1762f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (data==NULL)
1763f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		return 0;
1764f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1765f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1766f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1767f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1768f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		if ((size == 8) && (type == 0))
1769f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
17709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (type == PTP_EC_CANON_EOS_OLCInfoChanged) {
17719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			unsigned int j;
17729783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
17739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			for (j=0;j<31;j++)
17749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				if (dtoh32a(curdata+12) & (1<<j))
17759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					entries++;
17769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
17779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		curdata += size;
1778f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		entries++;
1779f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
17809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
17819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!ce) return 0;
1782f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1783f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	curdata = data;
1784f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	while (curdata - data < datasize) {
1785f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1786f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1787f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
17889783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
17899783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ce[i].u.info = NULL;
1790f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		switch (type) {
1791d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_ObjectAddedEx:
17929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
17939783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
17949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.StorageID 		= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
17959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
17969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
17979783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
17989783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OA_Name]));
17999783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus 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);
1800d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			break;
1801d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij		case  PTP_EC_CANON_EOS_RequestObjectTransfer:
18029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
18039783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
18049783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.StorageID 		= 0; /* use as marker */
18059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
18069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
18079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
18089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.Filename 		= strdup(((char*)&curdata[PTP_ece_OI_Name]));
18099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
18109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ptp_debug (params, "event %d: request object transfer oid %08lx, ofc %04x, size %d, filename %p", i, ce[i].u.object.oid, ce[i].u.object.oi.ObjectFormat, ce[i].u.object.oi.ObjectCompressedSize, ce[i].u.object.oi.Filename);
1811f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
18127e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case  PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
1813f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1814f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1815f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1816e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij			unsigned char	*xdata = &curdata[PTP_ece_Prop_Desc_Data];
18172ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij			unsigned int	j;
1818f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			PTPDevicePropDesc	*dpd;
1819f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
18207e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1821f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			for (j=0;j<params->nrofcanon_props;j++)
1822f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (params->canon_props[j].proptype == proptype)
1823f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1824f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (j==params->nrofcanon_props) {
18253bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1826f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1827f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1828f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			dpd = &params->canon_props[j].dpd;
18297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			/* 1 - uint16 ?
18307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 3 - uint16
18317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 7 - string?
18327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 */
1833f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxtype != 3) {
18343bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled.", i, propxtype, proptype);
18353bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1836e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params, "    %d: %02x", j, xdata[j]);
1837f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1838f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
18391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			if (! propxcnt)
18401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
18419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (propxcnt >= 2<<16) /* buggy or exploit */
18429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				break;
18431a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
18441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
18451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				   i, propxtype, proptype, dpd->DataType, propxcnt);
18461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FormFlag = PTP_DPFF_Enumeration;
18471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.NumberOfValues = propxcnt;
18483d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			free (dpd->FORM.Enum.SupportedValue);
18491a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
18501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
18511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			switch (proptype) {
18521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormat:
18531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatCF:
18541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatSD:
18551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
18561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* special handling of ImageFormat properties */
1857f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<propxcnt;j++) {
18581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->FORM.Enum.SupportedValue[j].u16 =
18599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij							ptp_unpack_EOS_ImageFormat( params, &xdata );
18601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
18611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
18621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
18631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			default:
18641a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* 'normal' enumerated types */
18651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (dpd->DataType) {
18661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX( TYPE, CONV )\
18671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<propxcnt;j++) { \
1868e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); \
1869e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
1870e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						xdata += 4; /* might only be for propxtype 3 */ \
18711a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					} \
18721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
18731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
18741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_INT16:	XX( i16, dtoh16a );
18751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
18761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
18771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
18781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
18791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				default:
1880e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata));
1881e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
1882e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
18831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
1884f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1885f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1886f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1887f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
18887e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case PTP_EC_CANON_EOS_PropValueChanged:
1889f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (size >= 0xc) {	/* property info */
18902ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				unsigned int j;
1891f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1892e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij				unsigned char	*xdata = &curdata[PTP_ece_Prop_Val_Data];
1893f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				PTPDevicePropDesc	*dpd;
1894f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
18951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
1896f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<params->nrofcanon_props;j++)
1897f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (params->canon_props[j].proptype == proptype)
1898f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
1899f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (j<params->nrofcanon_props) {
1900f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (	(params->canon_props[j].size != size) ||
1901e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						(memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
1902f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
1903e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
1904f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
1905f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				} else {
1906f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (j)
1907f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
1908f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					else
1909f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = malloc(sizeof(params->canon_props[0]));
1910f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].proptype = proptype;
1911f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].size = size;
1912f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
1913e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
1914f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
1915f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.GetSet = 1;
1916f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
1917f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->nrofcanon_props = j+1;
1918f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
1919f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd = &params->canon_props[j].dpd;
19201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
19219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
19229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
1923d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
19241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* fix GetSet value */
19251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (proptype) {
19261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX(x) case PTP_DPC_CANON_##x:
19271a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusMode)
19281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryPower)
19291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatterySelect)
19301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ModelID)
19311a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_PTPExtensionVersion)
19321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DPOFVersion)
19331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AvailableShots)
19341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentStorage)
19351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentFolder)
19361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenu)
19371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenuList)
19381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_HDDirectoryStructure)
19391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryInfo)
19401a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AdapterInfo)
19411a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensStatus)
19421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CardExtension)
19431a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_TempStatus)
19441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ShutterCounter)
19451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_SerialNumber)
19461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfFieldPreview)
19471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EVFRecordStatus)
19481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LvAfSystem)
19491a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusInfoEx)
19501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfField)
19511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_Brightness)
19521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EFComp)
19531a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensName)
19541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensID)
19551a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
19561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						dpd->GetSet = PTP_DPGS_Get;
19571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						break;
19581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
19591a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
19601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* set DataType */
1961f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (proptype) {
1962ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DPC_CANON_EOS_CameraTime:
19639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				case PTP_DPC_CANON_EOS_UTCTime:
19649783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				case PTP_DPC_CANON_EOS_Summertime: /* basical the DST flag */
1965d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_AvailableShots:
1966d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CaptureDestination:
1967d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
1968d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
1969d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentStorage:
1970d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentFolder:
1971d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ShutterCounter:
1972d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ModelID:
1973d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LensID:
1974d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_StroboFiring:
19753d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_AFSelectFocusArea:
19763d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_ContinousAFMode:
1977ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
1978ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
19790d762ccc39331608119dd0267021b165e22de499Linus Walleij				/* enumeration for AEM is never provided, but is available to set */
19800d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_AutoExposureMode:
19810d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
19820d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FormFlag = PTP_DPFF_Enumeration;
19830d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FORM.Enum.NumberOfValues = 0;
19840d762ccc39331608119dd0267021b165e22de499Linus Walleij					break;
1985f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Aperture:
1986f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ShutterSpeed:
1987f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ISOSpeed:
19887e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_FocusMode:
19897e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorSpace:
19907e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_BatteryPower:
1991e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BatterySelect:
1992d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
19931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_DriveMode:
19941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_AEB:
1995e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BracketMode:
1996e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_QuickReviewTime:
19970d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFMode:
19980d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFOutputDevice:
1999a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij				case PTP_DPC_CANON_EOS_AutoPowerOff:
20003d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_EVFRecordStatus:
2001f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
2002f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2003f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_PictureStyle:
2004f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalance:
2005f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_MeteringMode:
20063d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_ExpCompensation:
2007f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT8;
2008f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2009f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Owner:
20101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Artist:
20111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Copyright:
20121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_SerialNumber:
20131a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_LensName:
2014f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_STR;
2015f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
20167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
20177e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
20187e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					dpd->DataType = PTP_DTC_INT16;
20197e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
20207e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
20217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DPOFVersion:
20221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
20231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
20241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
2025e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
20261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
20277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc1:
20287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc2:
20297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc3:
20307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc4:
20317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc5:
20327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc6:
20337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc7:
20347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc8:
20357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc9:
20367e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc10:
20377e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc11:
20381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT8;
20391a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
20407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
2041e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
20421a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
2043e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					xdata += 4;
20447e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
20457e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* yet unknown 32bit props */
20467e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorTemperature:
20477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WftStatus:
20487e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_LensStatus:
20497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CardExtension:
20507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_TempStatus:
20517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_PhotoStudioMode:
20527e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
20537e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFSharpness:
20547e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFWBMode:
20557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
20567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFColorTemp:
2057d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ExposureSimMode:
2058d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvAfSystem:
2059d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_MovSize:
2060d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfField:
2061d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
20622ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				case PTP_DPC_CANON_EOS_AloMode:
20639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				case PTP_DPC_CANON_EOS_Brightness:
20640d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
20657e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
20661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
20671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
20681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
20693d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner						ptp_debug (params, "    %d: 0x%8x", j, dtoh32a(xdata+j*4));
20707e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
2071d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				/* ImageFormat properties have to be ignored here, see special handling below */
2072d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
2073d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
2074d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
2075d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
20760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
20773d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_FocusInfoEx:
2078d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
2079f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
20803bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
20813bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
2082e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
2083f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2084f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
2085f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (dpd->DataType) {
2086ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DTC_UINT32:
2087e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u32	= dtoh32a(xdata);
2088e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u32		= dtoh32a(xdata);
20893bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
2090ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
20912ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				case PTP_DTC_INT16:
20922ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					dpd->FactoryDefaultValue.i16	= dtoh16a(xdata);
20932ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					dpd->CurrentValue.i16		= dtoh16a(xdata);
20942ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %d", i, proptype, dpd->CurrentValue.i16);
20952ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					break;
2096f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT16:
2097e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= dtoh16a(xdata);
2098e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u16		= dtoh16a(xdata);
20993bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
2100f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2101f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT8:
2102e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u8	= dtoh8a(xdata);
2103e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u8		= dtoh8a(xdata);
21043bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
2105f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
21063d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DTC_INT8:
21073d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->FactoryDefaultValue.i8	= dtoh8a(xdata);
21083d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->CurrentValue.i8		= dtoh8a(xdata);
21093d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.i8);
21103d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					break;
2111f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_STR: {
21121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
2113f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					uint8_t len = 0;
2114f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
2115f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
21161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#else
21173d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->FactoryDefaultValue.str);
2118e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.str	= strdup( (char*)xdata );
21190d762ccc39331608119dd0267021b165e22de499Linus Walleij
21203d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->CurrentValue.str);
2121e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.str		= strdup( (char*)xdata );
21221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#endif
21237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
2124f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2125f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
2126f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
2127f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/* debug is printed in switch above this one */
2128f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2129f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
21301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
21310546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				/* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
2132d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				switch (proptype) {
2133d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
2134d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
2135d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
2136d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
2137d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
2138e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &xdata );
2139d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
2140d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
2141d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
21420546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
21430546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->DataType = PTP_DTC_STR;
21443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->FactoryDefaultValue.str);
21453d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->CurrentValue.str);
21463d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->FactoryDefaultValue.str	= ptp_unpack_EOS_CustomFuncEx( params, &xdata );
21470546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->CurrentValue.str		= strdup( (char*)dpd->FactoryDefaultValue.str );
21480546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
21490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					break;
21503d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_FocusInfoEx:
21513d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->DataType = PTP_DTC_STR;
21523d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->FactoryDefaultValue.str);
21533d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->CurrentValue.str);
21543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->FactoryDefaultValue.str	= ptp_unpack_EOS_FocusInfoEx( params, &xdata );
21553d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->CurrentValue.str		= strdup( (char*)dpd->FactoryDefaultValue.str );
21563d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					ptp_debug (params,"event %d: decoded focus info, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
21573d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					break;
2158d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				}
2159d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
2160f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
2161f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
21629783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		/* one more information record handed to us */
21639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		case PTP_EC_CANON_EOS_OLCInfoChanged: {
21649783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			uint32_t		len, curoff;
21659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			uint16_t		mask,proptype;
21669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			PTPDevicePropDesc	*dpd;
21679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
21689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			/* unclear what OLC stands for */
21699783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ptp_debug (params, "event %d: EOS event OLCInfoChanged (size %d)", i, size);
21709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (size >= 0x8) {	/* event info */
21713d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				unsigned int k;
21723d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				for (k=8;k<size;k++)
21733d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					ptp_debug (params, "    %d: %02x", k-8, curdata[k]);
21749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
21759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			len = dtoh32a(curdata+8);
21769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (len != size-8) {
21779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
21789783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ptp_debug (params, "event %d: size %d, len %d", i, size, len);
21799783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				break;
21809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
21819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			mask = dtoh16a(curdata+8+4);
21829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			curoff = 8+4+4;
21839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_BUTTON) {
21849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
21859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("Button 1234567"));
21869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info, "Button %d",  dtoh16a(curdata+curoff));
21879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
21889783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 2;
21899783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
21909783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
21919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_SHUTTERSPEED) {
21929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* 6 bytes: 01 01 98 10 00 60 */
21939783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* this seesm to be the shutter speed record */
21949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				proptype = PTP_DPC_CANON_EOS_ShutterSpeed;
21953d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				dpd = _lookup_or_allocate_canon_prop(params, proptype);
21969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */
21979783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
21989783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
21999783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
22009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 6;
22019783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22039783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_APERTURE) {
22049783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* 5 bytes: 01 01 5b 30 30 */
22059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* this seesm to be the aperture record */
22069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				proptype = PTP_DPC_CANON_EOS_Aperture;
22073d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				dpd = _lookup_or_allocate_canon_prop(params, proptype);
22089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */
22099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
22109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
22119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
22129783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 5;
22139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_ISO) {
22169783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* 5 bytes: 01 01 00 78 */
22179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* this seesm to be the aperture record */
22189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				proptype = PTP_DPC_CANON_EOS_ISOSpeed;
22193d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				dpd = _lookup_or_allocate_canon_prop(params, proptype);
22209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */
22219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
22229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
22239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
22249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 4;
22259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0010) {
22289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0010: 4 bytes, 04 00 00 00 observed */
22299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
22309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0010 content 01234567")+1);
22319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0010 content %02x%02x%02x%02x",
22329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
22339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
22349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
22359783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3]
22369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
22379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 4;
22389783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22399783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22409783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0020) {
22419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0020: 6 bytes, 00 00 00 00 00 00 observed */
22429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
22439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0020 content 0123456789ab")+1);
22449783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0020 content %02x%02x%02x%02x%02x%02x",
22459783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
22469783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
22479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
22489783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
22499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
22509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5]
22519783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
22529783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 6;
22539783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22549783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0040) {
22563d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				int	value = (signed char)curdata[curoff+2];
22579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0040: 7 bytes, 01 01 00 00 00 00 00 observed */
22583d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				/* exposure indicator */
22599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
22603d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].u.info = malloc(strlen("OLCInfo exposure indicator 012345678901234567890123456789abcd")+1);
22613d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				sprintf(ce[i].u.info,"OLCInfo exposure indicator %d,%d,%d.%d (%02x%02x%02x%02x)",
22629783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
22639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
22643d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					value/10,abs(value)%10,
22659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
22669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
22679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
22689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6]
22699783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
22709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 7;
22719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22729783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0080) {
22749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0080: 4 bytes, 00 00 00 00 observed */
22759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
22769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0080 content 01234567")+1);
22779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0080 content %02x%02x%02x%02x",
22789783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
22799783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
22809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
22819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3]
22829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
22839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 4;
22849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
22859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
22869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0100) {
22879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0100: 6 bytes, 00 00 00 00 00 00 (before focus) and 00 00 00 00 01 00 (on focus) observed */
22883d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSINFO;
22893d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].u.info = malloc(strlen("0123456789ab")+1);
22903d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x",
22919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
22929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
22939783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
22949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
22959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
22969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5]
22979783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
22989783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 6;
22999783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23019783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0200) {
23029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0200: 7 bytes, 00 00 00 00 00 00 00 observed */
23033d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSMASK;
23043d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].u.info = malloc(strlen("0123456789abcd0123456789abcdef")+1);
23053d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x%02x",
23069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
23079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
23089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
23099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
23109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
23119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
23129783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6]
23139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
23149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 7;
23159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23169783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0400) {
23189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0400: 7 bytes, 00 00 00 00 00 00 00 observed */
23199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
23209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0400 content 0123456789abcd")+1);
23219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0400 content %02x%02x%02x%02x%02x%02x%02x",
23229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
23239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
23249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
23259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
23269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
23279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
23289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6]
23299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
23309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 7;
23319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0800) {
23349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0800: 8 bytes, 00 00 00 00 00 00 00 00 and 19 01 00 00 00 00 00 00 and others observed */
23359783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/*   might be mask of focus points selected */
23369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
23379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0800 content 0123456789abcdef")+1);
23389783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0800 content %02x%02x%02x%02x%02x%02x%02x%02x",
23399783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
23409783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
23419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
23429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
23439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
23449783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
23459783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6],
23469783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+7]
23479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
23489783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 8;
23499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23519783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x1000) {
23529783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x1000: 1 byte, 00 observed */
23539783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
23549783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x1000 content 01")+1);
23559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x1000 content %02x",
23569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff]
23579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
23589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 1;
23599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23609783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23619783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			/* handle more masks */
23629783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
23639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.info = malloc(strlen("OLCInfo event mask 0123456789")+1);
23649783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			sprintf(ce[i].u.info, "OLCInfo event mask=%x",  mask);
23659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			break;
23669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
2367d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		case PTP_EC_CANON_EOS_CameraStatusChanged:
23689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
23699783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.status =  dtoh32a(curdata+8);
23709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d) = %d", i, size, dtoh32a(curdata+8));
23719e09ad0e32cbdac88637d4ee2cc02ca3b771ca40Linus Walleij			params->eos_camerastatus = dtoh32a(curdata+8);
2372d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			break;
23737e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case 0: /* end marker */
23747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size == 8) /* no output */
23757e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				break;
23767e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
23777e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			break;
237896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		case PTP_EC_CANON_EOS_BulbExposureTime:
23799783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
23809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.info = malloc(strlen("BulbExposureTime 123456789"));
23819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			sprintf (ce[i].u.info, "BulbExposureTime %d",  dtoh32a(curdata+8));
238296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			break;
23833d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		case PTP_EC_CANON_EOS_ObjectRemoved:
23843d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED;
23853d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			ce[i].u.object.oid = dtoh32a(curdata+8);
23863d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			break;
2387f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		default:
2388d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			switch (type) {
2389d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij#define XX(x)		case PTP_EC_CANON_EOS_##x: 								\
2390d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size); 	\
23919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)"));	\
23929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf (ce[i].u.info, "unhandled EOS event "#x" (size %d)",  size);		\
2393d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				break;
2394d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetEvent)
2395d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetObjectInfoEx)
2396d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageStatusChanged)
2397d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageInfoChanged)
2398d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectInfoChangedEx)
2399d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectContentChanged)
2400d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(WillSoonShutdown)
2401d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ShutdownTimerUpdated)
2402d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransfer)
2403d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferDT)
2404d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransferDT)
2405d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreAdded)
2406d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreRemoved)
2407d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(BulbExposureTime)
2408d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RecordingTime)
2409d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferTS)
2410d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(AfResult)
2411d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#undef XX
2412d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			default:
2413d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
2414d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				break;
2415d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			}
24167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size >= 0x8) {	/* event info */
24172ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				unsigned int j;
2418d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				for (j=8;j<size;j++)
2419d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij					ptp_debug (params, "    %d: %02x", j, curdata[j]);
24207e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			}
24219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2422f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
2423f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
2424f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
24259d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij		if ((size == 8) && (type == 0))
24269d22ce0e3214f38d30435fb9ec8ff2c8c6c4191eLinus Walleij			break;
24279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		i++;
2428f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
24299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!i) {
24309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		free (ce);
24319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ce = NULL;
24320d762ccc39331608119dd0267021b165e22de499Linus Walleij	}
24339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*pce = ce;
24349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	return i;
2435f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij}
2436f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
2437f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij/*
2438b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
2439b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
2440b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
2441b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
2442b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
2443b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
2444b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
24452ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
2446b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
24472ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int i;
2448b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2449b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
2450b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
2451b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
2452b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
2453b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
2454b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
2455b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) /* broken cnt? */
2456b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
24570d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!*cnt)
24580d762ccc39331608119dd0267021b165e22de499Linus Walleij		return;
24590d762ccc39331608119dd0267021b165e22de499Linus Walleij
24607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	*ec = malloc(sizeof(PTPContainer)*(*cnt));
2461b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2462b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
24637e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		memset(&(*ec)[i],0,sizeof(PTPContainer));
24647e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
24657e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
24667e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Nparam	= 1;
2467b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
2468eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
2469eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2470eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2471b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
2472b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
2473b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
2474b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
2475b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
2476b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2477b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
2478b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
2479b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
2480b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
2481b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
2482b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
2483b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
2484b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
2485b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
2486b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2487b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
2488b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
2489b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
2490b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
2491b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
2492b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2493b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
2494b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
2495b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2496b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
2497b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
2498b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2499b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
2500b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
2501b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2502b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
2503b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
2504b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
2505b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
2506b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
2507b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
2508b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
2509b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
2510b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
25117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
25137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
25147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
25157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
25167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
25177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
25187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
25197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
25207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
25217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
25227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
25237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
25247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
25257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
25267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
25277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
25287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
25297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
25307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
25317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
25327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
25337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
25347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
25357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
25377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
25387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
25397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
25407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
25417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
25427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
25437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
25447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
25457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
25467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
25487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
25497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
25507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
25513d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	handles->Handler = calloc(nrofobs,sizeof(handles->Handler[0]));
25527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
25533d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	*oinfos = calloc(nrofobs,sizeof((*oinfos)[0]));
25547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
25553d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	*flags  = calloc(nrofobs,sizeof((*flags)[0]));
25567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
25577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
25597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
25607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
25617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
25627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
25637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
25647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
25657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
25677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
25687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
25707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
25717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
25727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
25737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
25747347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
25757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
25767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
25777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
25787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
25797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
25807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
25817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
25827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
25837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
25847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
25857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
25867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
25877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
25887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
25897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
25907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
25917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
25927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
25937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
25947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
25957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
25962ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int changed = 0;
25977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
25987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
25997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
26007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
26017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
26027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
26037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
26047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
26057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
26067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
26077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
26087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
26097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
26107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
26117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
26127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
26137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
26147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
26157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
26167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
26177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
26187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
26197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
26207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
26217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
26227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
26237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
26247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
26257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
26267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
26277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
26287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
26297347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
26307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
26317347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
26327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
26337347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
26347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
26357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
26367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
26377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
26387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
26397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
26407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
26417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
26427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
26437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
26447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
26457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
26467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
2647