1a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij/* ptp-pack.c
2a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij *
3a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij * Copyright (C) 2001-2004 Mariusz Woloszyn <emsi@ipartners.pl>
4aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner * Copyright (C) 2003-2016 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*
130aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissnerptp_unpack_string(PTPParams *params, unsigned char* data, uint16_t offset, uint32_t total, 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
139aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (offset + 1 >= total)
140aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return NULL;
141aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
142a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	length = dtoh8a(&data[offset]);	/* PTP_MAXSTRLEN == 255, 8 bit len */
143a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*len = length;
144a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (length == 0)		/* nothing to do? */
145aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return NULL;
146aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
147aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (offset + 1 + length*sizeof(string[0]) > total)
148aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return NULL;
149a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
150a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* copy to string[] to ensure correct alignment for iconv(3) */
151a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(string, &data[offset+1], length * sizeof(string[0]));
152a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	string[length] = 0x0000U;   /* be paranoid!  add a terminator. */
153a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[0] = '\0';
154e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij
155a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/* convert from camera UCS-2 to our locale */
156a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	src = (char *)string;
157a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	srclen = length * sizeof(string[0]);
158a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	dest = loclstr;
159a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	destlen = sizeof(loclstr)-1;
1606db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	nconv = (size_t)-1;
1613d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
162d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	if (params->cd_ucs2_to_locale != (iconv_t)-1)
163d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij		nconv = iconv(params->cd_ucs2_to_locale, &src, &srclen, &dest, &destlen);
1646db174f4d18af574fab991309e11010aa0eb4543Linus Walleij#endif
165a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	if (nconv == (size_t) -1) { /* do it the hard way */
166a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		int i;
167a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		/* try the old way, in case iconv is broken */
168a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		for (i=0;i<length;i++) {
169a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			if (dtoh16a(&data[offset+1+2*i])>127)
170a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = '?';
171a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij			else
172a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij				loclstr[i] = dtoh16a(&data[offset+1+2*i]);
173eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
174a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij		dest = loclstr+length;
175eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
176a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	*dest = '\0';
177a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	loclstr[sizeof(loclstr)-1] = '\0';   /* be safe? */
178a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	return(strdup(loclstr));
179a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
180a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
181a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline int
182a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijucs2strlen(uint16_t const * const unicstr)
183a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
18496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int length = 0;
185a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
186a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Unicode strings are terminated with 2 * 0x00 */
187a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	for(length = 0; unicstr[length] != 0x0000U; length ++);
188a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return length;
189eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
190eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
191a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
192b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
193b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_string(PTPParams *params, char *string, unsigned char* data, uint16_t offset, uint8_t *len)
194eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
19596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int packedlen = 0;
196a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	uint16_t ucs2str[PTP_MAXSTRLEN+1];
197a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	char *ucs2strp = (char *) ucs2str;
198a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t convlen = strlen(string);
199a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
200a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	/* Cannot exceed 255 (PTP_MAXSTRLEN) since it is a single byte, duh ... */
201a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memset(ucs2strp, 0, sizeof(ucs2str));  /* XXX: necessary? */
2023d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
203d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij	if (params->cd_locale_to_ucs2 != (iconv_t)-1) {
2046db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t nconv;
2056db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		size_t convmax = PTP_MAXSTRLEN * 2; /* Includes the terminator */
2066db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		char *stringp = string;
2076db174f4d18af574fab991309e11010aa0eb4543Linus Walleij
2086db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen,
2096db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			&ucs2strp, &convmax);
2106db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		if (nconv == (size_t) -1)
2116db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[0] = 0x0000U;
212d6f25baf36fba05e3d8b2fa6d3cd4c026e2e6d33Linus Walleij	} else
213d000c371601fafcf75d2de2d1060ee11be2007d6Linus Walleij#endif
2146db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	{
2152ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int i;
2162ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij
2176db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		for (i=0;i<convlen;i++) {
2186db174f4d18af574fab991309e11010aa0eb4543Linus Walleij			ucs2str[i] = string[i];
2196db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		}
2206db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		ucs2str[convlen] = 0;
2216db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	}
222a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	/*
223a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 * XXX: isn't packedlen just ( (uint16_t *)ucs2strp - ucs2str )?
224a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 *      why do we need ucs2strlen()?
225a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	 */
226a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	packedlen = ucs2strlen(ucs2str);
227a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	if (packedlen > PTP_MAXSTRLEN-1) {
228a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		*len=0;
229a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return;
230a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	}
231958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
2327f2343824550452974d78f5dbd94e64844355c33Linus Walleij	/* number of characters including terminating 0 (PTP standard confirmed) */
233a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	htod8a(&data[offset],packedlen+1);
234a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	memcpy(&data[offset+1], &ucs2str[0], packedlen * sizeof(ucs2str[0]));
235a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij	htod16a(&data[offset+packedlen*2+1], 0x0000);  /* terminate 0 */
236958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij
237958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* The returned length is in number of characters */
238048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij	*len = (uint8_t) packedlen+1;
239eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
240eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
241a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleijstatic inline unsigned char *
242735f41692934a716158cf051d76e988febeca7eeLinus Walleijptp_get_packed_stringcopy(PTPParams *params, char *string, uint32_t *packed_size)
243a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij{
2448b42ca3d3baeb7c8f3e5eca88c613adb612e4ec0Richard Low	uint8_t packed[PTP_MAXSTRLEN*2+3], len;
245a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	size_t plen;
246a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	unsigned char *retcopy = NULL;
247d47b9218023a6b943a93faa743712ae072cba85cRichard Low
248d47b9218023a6b943a93faa743712ae072cba85cRichard Low	if (string == NULL)
249d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, "", (unsigned char*) packed, 0, &len);
250d47b9218023a6b943a93faa743712ae072cba85cRichard Low	else
251d47b9218023a6b943a93faa743712ae072cba85cRichard Low	  ptp_pack_string(params, string, (unsigned char*) packed, 0, &len);
252d47b9218023a6b943a93faa743712ae072cba85cRichard Low
253958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	/* returned length is in characters, then one byte for string length */
254958441f8ed3e704cf07c9f600730f90a80a0d424Linus Walleij	plen = len*2 + 1;
255048d938dc4889b74b258a786d5f53142b059fc32Linus Walleij
256a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	retcopy = malloc(plen);
257735f41692934a716158cf051d76e988febeca7eeLinus Walleij	if (!retcopy) {
258735f41692934a716158cf051d76e988febeca7eeLinus Walleij		*packed_size = 0;
259a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij		return NULL;
260735f41692934a716158cf051d76e988febeca7eeLinus Walleij	}
261a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	memcpy(retcopy, packed, plen);
262735f41692934a716158cf051d76e988febeca7eeLinus Walleij	*packed_size = plen;
263a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij	return (retcopy);
264a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij}
265a823a70e892d5eb1f4528679429cb3d9539abbe4Linus Walleij
266b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
2673d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerptp_unpack_uint32_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint32_t **array)
268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
269eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
270eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
271aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!data)
272aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
273aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
2743d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset >= datalen)
2753d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
2763d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
2773d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t) > datalen)
2783d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
2793d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
2809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*array = NULL;
281eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
2829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (n >= UINT_MAX/sizeof(uint32_t))
2839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
2849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!n)
2859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
2863d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
2873d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t)*(n+1) > datalen) {
2883d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)*(n+1) , datalen);
2893d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
2903d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
2913d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
292eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint32_t));
293aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!*array)
294aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
2959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	for (i=0;i<n;i++)
296eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh32a(&data[offset+(sizeof(uint32_t)*(i+1))]);
297eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
298eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
299eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
300b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
301f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijptp_pack_uint32_t_array(PTPParams *params, uint32_t *array, uint32_t arraylen, unsigned char **data )
302f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij{
303f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	uint32_t i=0;
304f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
305f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	*data = malloc ((arraylen+1)*sizeof(uint32_t));
306aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!*data)
307aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
308f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	htod32a(&(*data)[0],arraylen);
309f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	for (i=0;i<arraylen;i++)
310f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij		htod32a(&(*data)[sizeof(uint32_t)*(i+1)], array[i]);
311f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij	return (arraylen+1)*sizeof(uint32_t);
312f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij}
313f67bca9bde733f456ad341c0d852147124ab388aLinus Walleij
314f67bca9bde733f456ad341c0d852147124ab388aLinus Walleijstatic inline uint32_t
3153d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerptp_unpack_uint16_t_array(PTPParams *params, unsigned char* data, unsigned int offset, unsigned int datalen, uint16_t **array)
316eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
317eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t n, i=0;
318eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
319aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!data)
320aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
3219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*array = NULL;
322eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	n=dtoh32a(&data[offset]);
3239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (n >= UINT_MAX/sizeof(uint16_t))
3249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
3259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!n)
3269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;
3273d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t) > datalen)
3283d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
3293d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (offset + sizeof(uint32_t)+sizeof(uint16_t)*n > datalen) {
3303d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_debug (params ,"array runs over datalen bufferend (%d vs %d)", offset + sizeof(uint32_t)+n*sizeof(uint16_t) , datalen);
3313d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return 0;
3323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
333eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*array = malloc (n*sizeof(uint16_t));
334aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!*array)
335aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
3369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	for (i=0;i<n;i++)
337eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		(*array)[i]=dtoh16a(&data[offset+(sizeof(uint16_t)*(i+2))]);
338eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return n;
339eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
340eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
341eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* DeviceInfo pack/unpack */
342eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
343eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_StandardVersion		 0
344eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionID	 2
345eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionVersion	 6
346eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_VendorExtensionDesc	 8
347eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_FunctionalMode		 8
348eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_di_OperationsSupported	10
349eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
350aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissnerstatic inline int
351b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DI (PTPParams *params, unsigned char* data, PTPDeviceInfo *di, unsigned int datalen)
352eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
353eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t len;
354eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	unsigned int totallen;
3557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
356aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!data) return 0;
357aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen < 12) return 0;
358aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	memset (di, 0, sizeof(*di));
3597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	di->StandardVersion = dtoh16a(&data[PTP_di_StandardVersion]);
360eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionID =
361eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh32a(&data[PTP_di_VendorExtensionID]);
362eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->VendorExtensionVersion =
363eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_VendorExtensionVersion]);
364aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	di->VendorExtensionDesc =
365eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_string(params, data,
366aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		PTP_di_VendorExtensionDesc,
367aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		datalen,
368aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		&len);
369eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=len*2+1;
370aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen) return 0;
371aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	di->FunctionalMode =
372eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		dtoh16a(&data[PTP_di_FunctionalMode+totallen]);
373eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->OperationsSupported_len = ptp_unpack_uint16_t_array(params, data,
374eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3753d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
376eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->OperationsSupported);
377eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->OperationsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
378aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 0;
379eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->EventsSupported_len = ptp_unpack_uint16_t_array(params, data,
380eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3813d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
382eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->EventsSupported);
383eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->EventsSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
384aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 0;
385eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DevicePropertiesSupported_len =
386eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		ptp_unpack_uint16_t_array(params, data,
387eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3883d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
389eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->DevicePropertiesSupported);
390eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->DevicePropertiesSupported_len*sizeof(uint16_t)+sizeof(uint32_t);
391aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 0;
392eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->CaptureFormats_len = ptp_unpack_uint16_t_array(params, data,
393eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
3943d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
395eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->CaptureFormats);
396eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->CaptureFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
397aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 0;
398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->ImageFormats_len = ptp_unpack_uint16_t_array(params, data,
399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
4003d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		datalen,
401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&di->ImageFormats);
402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen=totallen+di->ImageFormats_len*sizeof(uint16_t)+sizeof(uint32_t);
403aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 0;
404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Manufacturer = ptp_unpack_string(params, data,
405eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
406aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		datalen,
407eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
408eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
409aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	/* be more relaxed ... as these are optional its ok if they are not here */
410aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 1;
411eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->Model = ptp_unpack_string(params, data,
412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
413aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		datalen,
414eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
415eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
416aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	/* be more relaxed ... as these are optional its ok if they are not here */
417aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 1;
418eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->DeviceVersion = ptp_unpack_string(params, data,
419eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
420aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		datalen,
421eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
422eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	totallen+=len*2+1;
423aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	/* be more relaxed ... as these are optional its ok if they are not here */
424aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen <= totallen+PTP_di_OperationsSupported) return 1;
425eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	di->SerialNumber = ptp_unpack_string(params, data,
426eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_di_OperationsSupported+totallen,
427aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		datalen,
428eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&len);
429aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	return 1;
430eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
431a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij
4322ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleijinline static void
433a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleijptp_free_DI (PTPDeviceInfo *di) {
4343d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->SerialNumber);
4353d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->DeviceVersion);
4363d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->Model);
4373d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->Manufacturer);
4383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->ImageFormats);
4393d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->CaptureFormats);
4403d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->VendorExtensionDesc);
4413d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->OperationsSupported);
4423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->EventsSupported);
4433d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	free (di->DevicePropertiesSupported);
444aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	memset(di, 0, sizeof(*di));
445a8a19cc8f7d6913e13f3e87709c687baddf2e596Linus Walleij}
4467e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij/* EOS Device Info unpack */
448aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissnerstatic inline int
4497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EOS_DI (PTPParams *params, unsigned char* data, PTPCanonEOSDeviceInfo *di, unsigned int datalen)
4507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij{
4512ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int totallen = 4;
45296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
45396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	memset (di,0, sizeof(*di));
454aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (datalen < 8) return 0;
4557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	/* uint32_t struct len - ignore */
4577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->EventsSupported_len = ptp_unpack_uint32_t_array(params, data,
4583d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		totallen, datalen, &di->EventsSupported);
459aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!di->EventsSupported) return 0;
4607e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->EventsSupported_len*sizeof(uint32_t)+4;
461aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (totallen >= datalen) return 0;
4627e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4637e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->DevicePropertiesSupported_len = ptp_unpack_uint32_t_array(params, data,
4643d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		totallen, datalen, &di->DevicePropertiesSupported);
465aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!di->DevicePropertiesSupported) return 0;
4667e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->DevicePropertiesSupported_len*sizeof(uint32_t)+4;
467aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (totallen >= datalen) return 0;
4687e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
4697e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	di->unk_len = ptp_unpack_uint32_t_array(params, data,
4703d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		totallen, datalen, &di->unk);
471aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!di->unk) return 0;
4727e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	totallen += di->unk_len*sizeof(uint32_t)+4;
473aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	return 1;
4747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij}
4750d762ccc39331608119dd0267021b165e22de499Linus Walleij
4760d762ccc39331608119dd0267021b165e22de499Linus Walleijstatic inline void
4770d762ccc39331608119dd0267021b165e22de499Linus Walleijptp_free_EOS_DI (PTPCanonEOSDeviceInfo *di)
4780d762ccc39331608119dd0267021b165e22de499Linus Walleij{
4790d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->EventsSupported);
4800d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->DevicePropertiesSupported);
4810d762ccc39331608119dd0267021b165e22de499Linus Walleij	free (di->unk);
4820d762ccc39331608119dd0267021b165e22de499Linus Walleij}
483eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
484eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectHandles array pack/unpack */
485eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
486eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oh				 0
487eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
488b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
489b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OH (PTPParams *params, unsigned char* data, PTPObjectHandles *oh, unsigned int len)
490eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
491f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (len) {
4923d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		oh->n = ptp_unpack_uint32_t_array(params, data, PTP_oh, len, &oh->Handler);
493f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	} else {
494f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->n = 0;
495f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		oh->Handler = NULL;
496f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
497eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
498eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
499eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StoreIDs array pack/unpack */
500eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
501eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_sids			 0
502eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
503b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
504b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SIDs (PTPParams *params, unsigned char* data, PTPStorageIDs *sids, unsigned int len)
505eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
506aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	sids->n = 0;
507aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	sids->Storage = NULL;
508aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
509aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (!data || !len)
51096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		return;
511aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
5123d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	sids->n = ptp_unpack_uint32_t_array(params, data, PTP_sids, len, &sids->Storage);
513eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
514eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
515eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* StorageInfo pack/unpack */
516eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
517eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageType		 0
518eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FilesystemType		 2
519eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_AccessCapability		 4
520eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_MaxCapability		 6
521eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInBytes		14
522eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_FreeSpaceInImages	22
523eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_si_StorageDescription	26
524eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
525aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissnerstatic inline int
526b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_SI (PTPParams *params, unsigned char* data, PTPStorageInfo *si, unsigned int len)
527eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
528eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t storagedescriptionlen;
529eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
530aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (len < 26) return 0;
531eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageType=dtoh16a(&data[PTP_si_StorageType]);
532eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FilesystemType=dtoh16a(&data[PTP_si_FilesystemType]);
533eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->AccessCapability=dtoh16a(&data[PTP_si_AccessCapability]);
534eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->MaxCapability=dtoh64a(&data[PTP_si_MaxCapability]);
535eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInBytes=dtoh64a(&data[PTP_si_FreeSpaceInBytes]);
536eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->FreeSpaceInImages=dtoh32a(&data[PTP_si_FreeSpaceInImages]);
5373d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
5383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* FIXME: check more lengths here */
539eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->StorageDescription=ptp_unpack_string(params, data,
540aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		PTP_si_StorageDescription,
541aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		len,
542aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		&storagedescriptionlen);
543eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	si->VolumeLabel=ptp_unpack_string(params, data,
544eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_si_StorageDescription+storagedescriptionlen*2+1,
545aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		len,
546eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		&storagedescriptionlen);
547aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	return 1;
548eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
549eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
550eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* ObjectInfo pack/unpack */
551eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
552eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_StorageID		 0
553eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectFormat		 4
554eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ProtectionStatus		 6
555eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ObjectCompressedSize	 8
556eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbFormat		12
557eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbCompressedSize	14
558eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixWidth		18
559eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ThumbPixHeight		22
560eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixWidth		26
561eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImagePixHeight		30
562eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ImageBitDepth		34
563eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_ParentObject		38
564eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationType		42
565eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_AssociationDesc		44
566eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_SequenceNumber		48
567eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_filenamelen		52
568eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_oi_Filename			53
569eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
570a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* the max length assuming zero length dates. We have need 3 */
571a032327c7485548c42f8162f87469dc0e0dd2126Linus Walleij/* bytes for these. */
572a679b1c4d273f210abb6befc5d9954a25427c329Richard Low#define PTP_oi_MaxLen PTP_oi_Filename+(PTP_MAXSTRLEN+1)*2+3
573a679b1c4d273f210abb6befc5d9954a25427c329Richard Low
574b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
575b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_OI (PTPParams *params, PTPObjectInfo *oi, unsigned char** oidataptr)
576eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
577b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* oidata;
578eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
579eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen=0;
580a679b1c4d273f210abb6befc5d9954a25427c329Richard Low	/* let's allocate some memory first; correct assuming zero length dates */
5810546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	oidata=malloc(PTP_oi_MaxLen + params->ocs64*4);
5820546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	*oidataptr=oidata;
583eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* the caller should free it after use! */
584eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0
585eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date="20020101T010101"; /* XXX Fake date */
586eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
5870546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	memset (oidata, 0, PTP_oi_MaxLen + params->ocs64*4);
588eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_StorageID],oi->StorageID);
589eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ObjectFormat],oi->ObjectFormat);
590eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ProtectionStatus],oi->ProtectionStatus);
591eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ObjectCompressedSize],oi->ObjectCompressedSize);
5920546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (params->ocs64)
5930546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		oidata += 4;
594eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_ThumbFormat],oi->ThumbFormat);
595eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbCompressedSize],oi->ThumbCompressedSize);
596eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixWidth],oi->ThumbPixWidth);
597eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ThumbPixHeight],oi->ThumbPixHeight);
598eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixWidth],oi->ImagePixWidth);
599eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImagePixHeight],oi->ImagePixHeight);
600eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ImageBitDepth],oi->ImageBitDepth);
601eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_ParentObject],oi->ParentObject);
602eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod16a(&oidata[PTP_oi_AssociationType],oi->AssociationType);
603eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_AssociationDesc],oi->AssociationDesc);
604eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod32a(&oidata[PTP_oi_SequenceNumber],oi->SequenceNumber);
605eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
606eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	ptp_pack_string(params, oi->Filename, oidata, PTP_oi_filenamelen, &filenamelen);
607eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
608eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	filenamelen=(uint8_t)strlen(oi->Filename);
609eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&req->data[PTP_oi_filenamelen],filenamelen+1);
610eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<filenamelen && i< PTP_MAXSTRLEN; i++) {
611eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		req->data[PTP_oi_Filename+i*2]=oi->Filename[i];
612eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
613eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
614eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/*
615eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 *XXX Fake date.
616eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * for example Kodak sets Capture date on the basis of EXIF data.
617eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * Spec says that this field is from perspective of Initiator.
618eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
619eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#if 0	/* seems now we don't need any data packed in OI dataset... for now ;)*/
620eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capturedatelen=strlen(capture_date);
621eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+1)*2],
622eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
623eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
624eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+1)*2+1]=capture_date[i];
625eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
626eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	htod8a(&data[PTP_oi_Filename+(filenamelen+capturedatelen+2)*2+1],
627eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		capturedatelen+1);
628eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0;i<capturedatelen && i< PTP_MAXSTRLEN; i++) {
629eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		data[PTP_oi_Filename+(i+filenamelen+capturedatelen+2)*2+2]=
630eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		  capture_date[i];
631eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
632eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#endif
633eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* XXX this function should return dataset length */
6340546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return (PTP_oi_Filename+filenamelen*2+(capturedatelen+1)*3)+params->ocs64*4;
635eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
636eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6373bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleijstatic time_t
6386db174f4d18af574fab991309e11010aa0eb4543Linus Walleijptp_unpack_PTPTIME (const char *str) {
6393bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char ptpdate[40];
6403bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	char tmp[5];
641a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	size_t  ptpdatelen;
6423bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	struct tm tm;
6433bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
6443bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	if (!str)
6453bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
6463bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	ptpdatelen = strlen(str);
6477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen >= sizeof (ptpdate)) {
6486db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is larger then size of buffer", ptpdatelen, (int)sizeof(ptpdate));*/
6493bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
6507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
6517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (ptpdatelen<15) {
6526db174f4d18af574fab991309e11010aa0eb4543Linus Walleij		/*ptp_debug (params ,"datelen is less than 15 (%d)", ptpdatelen);*/
6533bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		return 0;
6547e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
655a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	strncpy (ptpdate, str, sizeof(ptpdate));
656a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij	ptpdate[sizeof(ptpdate) - 1] = '\0';
6573bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
6583bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	memset(&tm,0,sizeof(tm));
6593bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate, 4);
6603bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[4] = 0;
6613bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_year=atoi (tmp) - 1900;
6623bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 4, 2);
6633bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mon = atoi (tmp) - 1;
6653bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 6, 2);
6663bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6673bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_mday = atoi (tmp);
6683bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 9, 2);
6693bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6703bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_hour = atoi (tmp);
6713bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 11, 2);
6723bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6733bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_min = atoi (tmp);
6743bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	strncpy (tmp, ptpdate + 13, 2);
6753bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tmp[2] = 0;
6763bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	tm.tm_sec = atoi (tmp);
677e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij	tm.tm_isdst = -1;
6783bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	return mktime (&tm);
6793bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij}
6803bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij
681b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OI (PTPParams *params, unsigned char* data, PTPObjectInfo *oi, unsigned int len)
683eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
684eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t filenamelen;
685eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint8_t capturedatelen;
686eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	char *capture_date;
687eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
6883d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (len < PTP_oi_SequenceNumber)
6893d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return;
6903d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
6913d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	oi->Filename = oi->Keywords = NULL;
6923d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
6933d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* FIXME: also handle length with all the strings at the end */
694eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->StorageID=dtoh32a(&data[PTP_oi_StorageID]);
695eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectFormat=dtoh16a(&data[PTP_oi_ObjectFormat]);
696eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ProtectionStatus=dtoh16a(&data[PTP_oi_ProtectionStatus]);
697eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ObjectCompressedSize=dtoh32a(&data[PTP_oi_ObjectCompressedSize]);
6980546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
6990546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* Stupid Samsung Galaxy developers emit a 64bit objectcompressedsize */
7000546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if ((data[PTP_oi_filenamelen] == 0) && (data[PTP_oi_filenamelen+4] != 0)) {
7010546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		params->ocs64 = 1;
7020546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		data += 4;
7030546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
704eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbFormat=dtoh16a(&data[PTP_oi_ThumbFormat]);
705eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbCompressedSize=dtoh32a(&data[PTP_oi_ThumbCompressedSize]);
706eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixWidth=dtoh32a(&data[PTP_oi_ThumbPixWidth]);
707eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ThumbPixHeight=dtoh32a(&data[PTP_oi_ThumbPixHeight]);
708eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixWidth=dtoh32a(&data[PTP_oi_ImagePixWidth]);
709eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImagePixHeight=dtoh32a(&data[PTP_oi_ImagePixHeight]);
710eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ImageBitDepth=dtoh32a(&data[PTP_oi_ImageBitDepth]);
711eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->ParentObject=dtoh32a(&data[PTP_oi_ParentObject]);
712eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationType=dtoh16a(&data[PTP_oi_AssociationType]);
713eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->AssociationDesc=dtoh32a(&data[PTP_oi_AssociationDesc]);
714eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	oi->SequenceNumber=dtoh32a(&data[PTP_oi_SequenceNumber]);
7150546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
716aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	oi->Filename= ptp_unpack_string(params, data, PTP_oi_filenamelen, len, &filenamelen);
717eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
718eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
719aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		PTP_oi_filenamelen+filenamelen*2+1, len, &capturedatelen);
720eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	/* subset of ISO 8601, without '.s' tenths of second and
721eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 * time zone
722eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	 */
7236db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->CaptureDate = ptp_unpack_PTPTIME(capture_date);
724eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
725eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
7263bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	/* now the modification date ... */
727eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	capture_date = ptp_unpack_string(params, data,
728eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		PTP_oi_filenamelen+filenamelen*2
729aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		+capturedatelen*2+2, len, &capturedatelen);
7306db174f4d18af574fab991309e11010aa0eb4543Linus Walleij	oi->ModificationDate = ptp_unpack_PTPTIME(capture_date);
731eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	free(capture_date);
732eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
733eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
734eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Custom Type Value Assignement (without Length) macro frequently used below */
735b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define CTVAL(target,func) {			\
736b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(target))	\
737b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;			\
738b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	target = func(&data[*offset]);		\
739b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(target);		\
740eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
741eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
742b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define RARR(val,member,func)	{			\
7439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int n,j;				\
744b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (total - *offset < sizeof(uint32_t))		\
745b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 0;				\
746b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	n = dtoh32a (&data[*offset]);			\
747b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*offset += sizeof(uint32_t);			\
748b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij							\
7499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (n >= UINT_MAX/sizeof(val->a.v[0]))		\
7509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 0;				\
751aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (n > (total - (*offset))/sizeof(val->a.v[0]))\
752aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;				\
753b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.count = n;				\
754b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	val->a.v = malloc(sizeof(val->a.v[0])*n);	\
755b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!val->a.v) return 0;			\
756b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (j=0;j<n;j++)				\
757b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(val->a.v[j].member, func);	\
758b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
759eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
7602ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleijstatic inline unsigned int
761b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPV (
7623d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	PTPParams *params, unsigned char* data, unsigned int *offset, unsigned int total,
763b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	PTPPropertyValue* value, uint16_t datatype
764b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij) {
765aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (*offset >= total)	/* we are at the end or over the end of the buffer */
766aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
767aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
768eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
769b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
770b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i8,dtoh8a);
771b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
772b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
773b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u8,dtoh8a);
774b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
775b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
776b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i16,dtoh16a);
777b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
778b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
779b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u16,dtoh16a);
780b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
781b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
782b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->i32,dtoh32a);
783b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
784b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		CTVAL(value->u32,dtoh32a);
786b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
787abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
788abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->i64,dtoh64a);
789abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
790abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
791abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		CTVAL(value->u64,dtoh64a);
792abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
793abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij
794037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_UINT128:
795037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
796037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of uint128n");*/
797037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
798037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	case PTP_DTC_INT128:
799037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		*offset += 16;
800037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		/*fprintf(stderr,"unhandled unpack of int128n");*/
801037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		break;
802037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
803037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
804037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij
805b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
806b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i8,dtoh8a);
807b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
808b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
809b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u8,dtoh8a);
810b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
811b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
812b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u16,dtoh16a);
813b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
814b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
815b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i16,dtoh16a);
816b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
817b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
818b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,u32,dtoh32a);
819b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
820b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
821b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		RARR(value,i32,dtoh32a);
822b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
823abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
824abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,u64,dtoh64a);
825abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
826abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
827abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		RARR(value,i64,dtoh64a);
828abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
829b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
830b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int arrays are unimplemented also */
831b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
832b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		uint8_t len;
833b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		/* XXX: max size */
834aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
835aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (*offset >= total+1)
836aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			return 0;
837aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
838aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		value->str = ptp_unpack_string(params,data,*offset,total,&len);
839b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		*offset += len*2+1;
840b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!value->str)
841deddc3490b3084b802737017982285bfa58b382fLinus Walleij			return 1;
842b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
843eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
844037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij	default:
845037a12589156bbcdb5e772b6bab49dee79107f9fLinus Walleij		return 0;
846b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
847b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
848eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
849eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
850eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/* Device Property pack/unpack */
851eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DevicePropertyCode	0
852eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_DataType		2
853eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_GetSet			4
854eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_dpd_FactoryDefaultValue	5
855eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
856b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
857b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen)
858eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
8599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int offset = 0, ret;
860eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
861b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (dpd, 0, sizeof(*dpd));
862aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (dpdlen <= 5)
863aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
864eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_DevicePropertyCode]);
865eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_DataType]);
866eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	dpd->GetSet=dtoh8a(&data[PTP_dpd_GetSet]);
867deddc3490b3084b802737017982285bfa58b382fLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
868b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
869b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_dpd_FactoryDefaultValue;
870b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
871b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
872deddc3490b3084b802737017982285bfa58b382fLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (offset == dpdlen))
873deddc3490b3084b802737017982285bfa58b382fLinus Walleij		return 1;
874b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->CurrentValue, dpd->DataType);
875b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
876b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
877b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* if offset==0 then Data Type format is not supported by this
878b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   code or the Data Type is a string (with two empty strings as
879b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
880b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	   not present. */
881b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
882b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (offset==PTP_dpd_FactoryDefaultValue)
883b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return 1;
884b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
885b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	dpd->FormFlag=dtoh8a(&data[offset]);
886b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
887eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
888eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (dpd->FormFlag) {
889b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Range:
890b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
891b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
892b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
893b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
894b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
895b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
896eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
897b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DPFF_Enumeration: {
898b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		int i;
899eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
900b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
901b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
902b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
903b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
904b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
905b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
906b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
907b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
908b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
909b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
910b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
911b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
912b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
913b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
914b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
915b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
916b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
917b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
918b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
919b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
920eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij			}
921b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
922eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		}
923eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
924b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
925b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
926b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
927b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_devicepropdesc(dpd);
928b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
929eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
930eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
9319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij/* Device Property pack/unpack */
9329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_DevicePropertyCode	0
9339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_DataType		2
9349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_GetSet		4
9359783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_Unknown		5
9369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define PTP_dpd_Sony_FactoryDefaultValue	6
9379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9389783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijstatic inline int
9399783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijptp_unpack_Sony_DPD (PTPParams *params, unsigned char* data, PTPDevicePropDesc *dpd, unsigned int dpdlen, unsigned int *poffset)
9409783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij{
9419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int ret;
9423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if 0
9433d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unsigned int unk1, unk2;
9443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#endif
9459783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9469783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	memset (dpd, 0, sizeof(*dpd));
9479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->DevicePropertyCode=dtoh16a(&data[PTP_dpd_Sony_DevicePropertyCode]);
9489783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->DataType=dtoh16a(&data[PTP_dpd_Sony_DataType]);
9499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#if 0
9513d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* get set ? */
9523d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unk1 = dtoh8a(&data[PTP_dpd_Sony_GetSet]);
9533d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unk2 = dtoh8a(&data[PTP_dpd_Sony_Unknown]);
9543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug (params, "prop 0x%04x, datatype 0x%04x, unk1 %d unk2 %d", dpd->DevicePropertyCode, dpd->DataType, unk1, unk2);
9559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#endif
9569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->GetSet=1;
9579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->FormFlag=PTP_DPFF_None;
9599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9609783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*poffset = PTP_dpd_Sony_FactoryDefaultValue;
9619783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FactoryDefaultValue, dpd->DataType);
9629783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!ret) goto outofmemory;
9639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if ((dpd->DataType == PTP_DTC_STR) && (*poffset == dpdlen))
9649783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 1;
9659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->CurrentValue, dpd->DataType);
9669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!ret) goto outofmemory;
9679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	/* if offset==0 then Data Type format is not supported by this
9699783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	   code or the Data Type is a string (with two empty strings as
9709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	   values). In both cases Form Flag should be set to 0x00 and FORM is
9719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	   not present. */
9729783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (*poffset==PTP_dpd_Sony_FactoryDefaultValue)
9749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return 1;
9759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	dpd->FormFlag=dtoh8a(&data[*poffset]);
9779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*poffset+=sizeof(uint8_t);
9789783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9799783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	switch (dpd->FormFlag) {
9809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	case PTP_DPFF_Range:
9819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MinimumValue, dpd->DataType);
9829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!ret) goto outofmemory;
9839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.MaximumValue, dpd->DataType);
9849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!ret) goto outofmemory;
9859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Range.StepSize, dpd->DataType);
9869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!ret) goto outofmemory;
9879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		break;
9889783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	case PTP_DPFF_Enumeration: {
9899783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		int i;
9909783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#define N	dpd->FORM.Enum.NumberOfValues
9919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		N = dtoh16a(&data[*poffset]);
9929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		*poffset+=sizeof(uint16_t);
9939783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		dpd->FORM.Enum.SupportedValue = malloc(N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
9949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (!dpd->FORM.Enum.SupportedValue)
9959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			goto outofmemory;
9969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
9979783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		memset (dpd->FORM.Enum.SupportedValue,0 , N*sizeof(dpd->FORM.Enum.SupportedValue[0]));
9989783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		for (i=0;i<N;i++) {
9999783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ret = ptp_unpack_DPV (params, data, poffset, dpdlen, &dpd->FORM.Enum.SupportedValue[i], dpd->DataType);
10009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
10019783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
10029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 * specifies an enumeration with N in wrong endian
10039783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
10049783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 * the end of the packet.
10059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			 */
10069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (!ret) {
10079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				if (!i)
10089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					goto outofmemory;
10099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->FORM.Enum.NumberOfValues = i;
10109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				break;
10119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
10129783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
10139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
10149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	}
10159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij#undef N
10169783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	return 1;
10179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijoutofmemory:
10189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ptp_free_devicepropdesc(dpd);
10199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	return 0;
10209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij}
10219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
1022d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijstatic inline void
1023d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijduplicate_PropertyValue (const PTPPropertyValue *src, PTPPropertyValue *dst, uint16_t type) {
10249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (type == PTP_DTC_STR) {
10259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (src->str)
10269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			dst->str = strdup(src->str);
10279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		else
10289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			dst->str = NULL;
10299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return;
10309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	}
10319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
1032d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	if (type & PTP_DTC_ARRAY_MASK) {
10332ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int i;
1034d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1035d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->a.count = src->a.count;
10369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		dst->a.v = malloc (sizeof(src->a.v[0])*src->a.count);
1037d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		for (i=0;i<src->a.count;i++)
1038d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij			duplicate_PropertyValue (&src->a.v[i], &dst->a.v[i], type & ~PTP_DTC_ARRAY_MASK);
1039d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		return;
1040d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
1041d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	switch (type & ~PTP_DTC_ARRAY_MASK) {
1042d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT8:	dst->i8 = src->i8; break;
1043d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT8:	dst->u8 = src->u8; break;
1044d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT16:	dst->i16 = src->i16; break;
1045d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT16:	dst->u16 = src->u16; break;
1046d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT32:	dst->i32 = src->i32; break;
1047d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT32:	dst->u32 = src->u32; break;
1048d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT64:	dst->u64 = src->u64; break;
1049d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT64:	dst->i64 = src->i64; break;
1050d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij#if 0
1051d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_INT128:	dst->i128 = src->i128; break;
1052d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DTC_UINT128:	dst->u128 = src->u128; break;
1053d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij#endif
1054d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	default:		break;
1055d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
1056d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	return;
1057d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij}
1058d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1059d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijstatic inline void
1060d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleijduplicate_DevicePropDesc(const PTPDevicePropDesc *src, PTPDevicePropDesc *dst) {
1061d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	int i;
1062d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1063d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->DevicePropertyCode	= src->DevicePropertyCode;
1064d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->DataType		= src->DataType;
1065d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->GetSet		= src->GetSet;
1066d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
10679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	duplicate_PropertyValue (&src->FactoryDefaultValue, &dst->FactoryDefaultValue, src->DataType);
10689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	duplicate_PropertyValue (&src->CurrentValue, &dst->CurrentValue, src->DataType);
1069d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1070d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	dst->FormFlag		= src->FormFlag;
1071d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	switch (src->FormFlag) {
1072d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_Range:
1073d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.MinimumValue, &dst->FORM.Range.MinimumValue, src->DataType);
1074d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.MaximumValue, &dst->FORM.Range.MaximumValue, src->DataType);
1075d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		duplicate_PropertyValue (&src->FORM.Range.StepSize,     &dst->FORM.Range.StepSize,     src->DataType);
1076d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
1077d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_Enumeration:
1078d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->FORM.Enum.NumberOfValues = src->FORM.Enum.NumberOfValues;
1079d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		dst->FORM.Enum.SupportedValue = malloc (sizeof(dst->FORM.Enum.SupportedValue[0])*src->FORM.Enum.NumberOfValues);
1080d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		for (i = 0; i<src->FORM.Enum.NumberOfValues ; i++)
1081d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij			duplicate_PropertyValue (&src->FORM.Enum.SupportedValue[i], &dst->FORM.Enum.SupportedValue[i], src->DataType);
1082d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
1083d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	case PTP_DPFF_None:
1084d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij		break;
1085d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij	}
1086d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij}
1087d9ee8cd37f0704a501b62a185c3305d236c7c8dfLinus Walleij
1088b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_ObjectPropertyCode	0
1089b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_DataType		2
1090b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_GetSet			4
1091b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_opd_FactoryDefaultValue	5
1092eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1093b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline int
1094b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_OPD (PTPParams *params, unsigned char* data, PTPObjectPropDesc *opd, unsigned int opdlen)
1095eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
10962ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int offset=0, ret;
1097b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1098b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	memset (opd, 0, sizeof(*opd));
1099b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->ObjectPropertyCode=dtoh16a(&data[PTP_opd_ObjectPropertyCode]);
1100b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->DataType=dtoh16a(&data[PTP_opd_DataType]);
1101b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GetSet=dtoh8a(&data[PTP_opd_GetSet]);
1102b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1103b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset = PTP_opd_FactoryDefaultValue;
1104b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FactoryDefaultValue, opd->DataType);
1105b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!ret) goto outofmemory;
1106b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1107b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->GroupCode=dtoh32a(&data[offset]);
1108b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint32_t);
1109b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1110b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	opd->FormFlag=dtoh8a(&data[offset]);
1111b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	offset+=sizeof(uint8_t);
1112b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1113b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	switch (opd->FormFlag) {
1114b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Range:
1115b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MinimumValue, opd->DataType);
1116b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
1117b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.MaximumValue, opd->DataType);
1118b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
1119b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Range.StepSize, opd->DataType);
1120b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!ret) goto outofmemory;
1121b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1122b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_OPFF_Enumeration: {
11232ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int i;
1124b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define N	opd->FORM.Enum.NumberOfValues
1125b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		N = dtoh16a(&data[offset]);
1126b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		offset+=sizeof(uint16_t);
1127b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		opd->FORM.Enum.SupportedValue = malloc(N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1128b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		if (!opd->FORM.Enum.SupportedValue)
1129b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			goto outofmemory;
1130b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1131b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		memset (opd->FORM.Enum.SupportedValue,0 , N*sizeof(opd->FORM.Enum.SupportedValue[0]));
1132b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<N;i++) {
1133b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			ret = ptp_unpack_DPV (params, data, &offset, opdlen, &opd->FORM.Enum.SupportedValue[i], opd->DataType);
1134b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
1135b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			/* Slightly different handling here. The HP PhotoSmart 120
1136b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * specifies an enumeration with N in wrong endian
1137b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * 00 01 instead of 01 00, so we count the enum just until the
1138b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 * the end of the packet.
1139b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			 */
1140b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			if (!ret) {
1141b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				if (!i)
1142b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij					goto outofmemory;
1143b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				opd->FORM.Enum.NumberOfValues = i;
1144b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij				break;
1145b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij			}
1146b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
1147b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#undef N
1148b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		}
1149eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
1150b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 1;
1151b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijoutofmemory:
1152b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_free_objectpropdesc(opd);
1153b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return 0;
1154eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1155eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1156eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1157b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
1158b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_DPV (PTPParams *params, PTPPropertyValue* value, unsigned char** dpvptr, uint16_t datatype)
1159eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1160b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char* dpv=NULL;
1161eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	uint32_t size=0;
11622ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int i;
1163eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1164eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	switch (datatype) {
1165b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT8:
1166b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int8_t);
1167b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1168b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->i8);
1169b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1170b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT8:
1171b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint8_t);
1172b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1173b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod8a(dpv,value->u8);
1174b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1175b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT16:
1176b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int16_t);
1177b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1178b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->i16);
1179b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1180b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT16:
1181b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint16_t);
1182b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1183b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(dpv,value->u16);
1184b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1185b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_INT32:
1186b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(int32_t);
1187b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1188b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->i32);
1189b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1190b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_UINT32:
1191b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t);
1192b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1193b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->u32);
1194b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1195abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_INT64:
1196abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(int64_t);
1197abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1198abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->i64);
1199abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1200abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_UINT64:
1201abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint64_t);
1202abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1203abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod64a(dpv,value->u64);
1204abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1205b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT8:
1206b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint8_t);
1207b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1208b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1209b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1210cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(uint8_t)],value->a.v[i].u8);
1211b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1212b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT8:
1213b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int8_t);
1214b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1215b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1216b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1217cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod8a(&dpv[sizeof(uint32_t)+i*sizeof(int8_t)],value->a.v[i].i8);
1218b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1219b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT16:
1220b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint16_t);
1221b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1222b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1223b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1224cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(uint16_t)],value->a.v[i].u16);
1225b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1226b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT16:
1227b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int16_t);
1228b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1229b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1230b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1231cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod16a(&dpv[sizeof(uint32_t)+i*sizeof(int16_t)],value->a.v[i].i16);
1232b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1233b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AUINT32:
1234b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint32_t);
1235b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1236b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1237b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1238cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(uint32_t)],value->a.v[i].u32);
1239b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1240b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_AINT32:
1241b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int32_t);
1242b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		dpv=malloc(size);
1243b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod32a(dpv,value->a.count);
1244b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		for (i=0;i<value->a.count;i++)
1245cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod32a(&dpv[sizeof(uint32_t)+i*sizeof(int32_t)],value->a.v[i].i32);
1246b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		break;
1247abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AUINT64:
1248abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(uint64_t);
1249abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1250abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
1251abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
1252cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(uint64_t)],value->a.v[i].u64);
1253abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1254abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij	case PTP_DTC_AINT64:
1255abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		size=sizeof(uint32_t)+value->a.count*sizeof(int64_t);
1256abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		dpv=malloc(size);
1257abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		htod32a(dpv,value->a.count);
1258abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		for (i=0;i<value->a.count;i++)
1259cc2659036a503fce161cb77d9b0af17a52d7437bRichard Low			htod64a(&dpv[sizeof(uint32_t)+i*sizeof(int64_t)],value->a.v[i].i64);
1260abf5475a00d858a282595b7fe8c8ec8c5d629569Linus Walleij		break;
1261b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	/* XXX: other int types are unimplemented */
1262b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	case PTP_DTC_STR: {
1263735f41692934a716158cf051d76e988febeca7eeLinus Walleij		dpv=ptp_get_packed_stringcopy(params, value->str, &size);
1264eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		break;
1265b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
1266eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	}
1267eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	*dpvptr=dpv;
1268eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	return size;
126999310d4445697da39f22dff35457c75e35e97171Linus Walleij}
127099310d4445697da39f22dff35457c75e35e97171Linus Walleij
127199310d4445697da39f22dff35457c75e35e97171Linus Walleij#define MAX_MTP_PROPS 127
127299310d4445697da39f22dff35457c75e35e97171Linus Walleijstatic inline uint32_t
12731e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_pack_OPL (PTPParams *params, MTPProperties *props, int nrofprops, unsigned char** opldataptr)
127499310d4445697da39f22dff35457c75e35e97171Linus Walleij{
127599310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char* opldata;
12761e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *propitr;
127799310d4445697da39f22dff35457c75e35e97171Linus Walleij	unsigned char *packedprops[MAX_MTP_PROPS];
127899310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t packedpropslens[MAX_MTP_PROPS];
127939b9374f23451201dece736db13f0f648584dc32Linus Walleij	uint32_t packedobjecthandles[MAX_MTP_PROPS];
128099310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropsids[MAX_MTP_PROPS];
128199310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint16_t packedpropstypes[MAX_MTP_PROPS];
128299310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t totalsize = 0;
128399310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t bufp = 0;
128499310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t noitems = 0;
128599310d4445697da39f22dff35457c75e35e97171Linus Walleij	uint32_t i;
128699310d4445697da39f22dff35457c75e35e97171Linus Walleij
128799310d4445697da39f22dff35457c75e35e97171Linus Walleij	totalsize = sizeof(uint32_t); /* 4 bytes to store the number of elements */
12881e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	propitr = props;
12891e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	while (nrofprops-- && noitems < MAX_MTP_PROPS) {
12906c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		/* Object Handle */
129139b9374f23451201dece736db13f0f648584dc32Linus Walleij		packedobjecthandles[noitems]=propitr->ObjectHandle;
129299310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint32_t); /* Object ID */
129399310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Metadata type */
129499310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropsids[noitems]=propitr->property;
129599310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
129699310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Data type */
129799310d4445697da39f22dff35457c75e35e97171Linus Walleij		packedpropstypes[noitems]= propitr->datatype;
129899310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += sizeof(uint16_t);
129999310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Add each property to be sent. */
130099310d4445697da39f22dff35457c75e35e97171Linus Walleij	        packedpropslens[noitems] = ptp_pack_DPV (params, &propitr->propval, &packedprops[noitems], propitr->datatype);
130199310d4445697da39f22dff35457c75e35e97171Linus Walleij		totalsize += packedpropslens[noitems];
130299310d4445697da39f22dff35457c75e35e97171Linus Walleij		noitems ++;
13031e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		propitr ++;
130499310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
130599310d4445697da39f22dff35457c75e35e97171Linus Walleij
130699310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Allocate memory for the packed property list */
130799310d4445697da39f22dff35457c75e35e97171Linus Walleij	opldata = malloc(totalsize);
130899310d4445697da39f22dff35457c75e35e97171Linus Walleij
130999310d4445697da39f22dff35457c75e35e97171Linus Walleij	htod32a(&opldata[bufp],noitems);
131099310d4445697da39f22dff35457c75e35e97171Linus Walleij	bufp += 4;
131199310d4445697da39f22dff35457c75e35e97171Linus Walleij
131299310d4445697da39f22dff35457c75e35e97171Linus Walleij	/* Copy into a nice packed list */
131399310d4445697da39f22dff35457c75e35e97171Linus Walleij	for (i = 0; i < noitems; i++) {
131499310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* Object ID */
13156c0a6ce803cf79802b1c48339adf0964db30ec83Richard Low		htod32a(&opldata[bufp],packedobjecthandles[i]);
131699310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint32_t);
131799310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropsids[i]);
131899310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
131999310d4445697da39f22dff35457c75e35e97171Linus Walleij		htod16a(&opldata[bufp],packedpropstypes[i]);
132099310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += sizeof(uint16_t);
132199310d4445697da39f22dff35457c75e35e97171Linus Walleij		/* The copy the actual property */
132299310d4445697da39f22dff35457c75e35e97171Linus Walleij		memcpy(&opldata[bufp], packedprops[i], packedpropslens[i]);
132399310d4445697da39f22dff35457c75e35e97171Linus Walleij		bufp += packedpropslens[i];
132499310d4445697da39f22dff35457c75e35e97171Linus Walleij		free(packedprops[i]);
132599310d4445697da39f22dff35457c75e35e97171Linus Walleij	}
132699310d4445697da39f22dff35457c75e35e97171Linus Walleij	*opldataptr = opldata;
132799310d4445697da39f22dff35457c75e35e97171Linus Walleij	return totalsize;
1328eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1329eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
13301e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijstatic int
13311e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij_compare_func(const void* x, const void *y) {
13321e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *px = x;
13331e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	const MTPProperties *py = y;
13341e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
13351e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	return px->ObjectHandle - py->ObjectHandle;
13361e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij}
13371e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij
13388d82d2f4b0794e41ec26289045867eebb3496b8cRichard Lowstatic inline int
13391e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleijptp_unpack_OPL (PTPParams *params, unsigned char* data, MTPProperties **pprops, unsigned int len)
13408d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low{
1341277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	uint32_t prop_count = dtoh32a(data);
13421e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	MTPProperties *props = NULL;
13432ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int offset = 0, i;
1344277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1345aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	*pprops = NULL;
1346aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (prop_count == 0)
1347aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return 0;
1348aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (prop_count >= INT_MAX/sizeof(MTPProperties)) {
1349aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		ptp_debug (params ,"prop_count %d is too large", prop_count);
1350277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		return 0;
1351277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
1352d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij	ptp_debug (params ,"Unpacking MTP OPL, size %d (prop_count %d)", len, prop_count);
1353277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	data += sizeof(uint32_t);
13543bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij	len -= sizeof(uint32_t);
13551e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	props = malloc(prop_count * sizeof(MTPProperties));
13561e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	if (!props) return 0;
1357277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	for (i = 0; i < prop_count; i++) {
13583bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		if (len <= 0) {
1359d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			ptp_debug (params ,"short MTP Object Property List at property %d (of %d)", i, prop_count);
1360aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params ,"device probably needs DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST_ALL");
13613bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			ptp_debug (params ,"or even DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST", i);
1362d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			qsort (props, i, sizeof(MTPProperties),_compare_func);
1363d49955b02710fd4bb1eda73b8bd6abb3f17f7c15Linus Walleij			*pprops = props;
13643bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij			return i;
13653bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij		}
13661e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].ObjectHandle = dtoh32a(data);
1367277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint32_t);
1368277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint32_t);
1369277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
13701e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].property = dtoh16a(data);
1371277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1372277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1373277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
13741e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij		props[i].datatype = dtoh16a(data);
1375277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += sizeof(uint16_t);
1376277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= sizeof(uint16_t);
1377277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij
1378277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		offset = 0;
1379aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (!ptp_unpack_DPV(params, data, &offset, len, &props[i].propval, props[i].datatype)) {
1380aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params ,"unpacking DPV of property %d encountered insufficient buffer. attack?", i);
1381aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			qsort (props, i, sizeof(MTPProperties),_compare_func);
1382aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			*pprops = props;
1383aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			return i;
1384aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
1385277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		data += offset;
1386277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij		len -= offset;
1387277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	}
13881e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	qsort (props, prop_count, sizeof(MTPProperties),_compare_func);
13891e9a033f4d2d485a34954eab0858d368c0b30fceLinus Walleij	*pprops = props;
1390277cd539ff4c4fdf591d92c1d0cd9c2e26eaaee0Linus Walleij	return prop_count;
13918d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low}
13928d82d2f4b0794e41ec26289045867eebb3496b8cRichard Low
1393eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1394eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP USB Event container unpack
1395eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1396eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1397eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1398eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Length		0
1399eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Type		4
1400eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Code		6
1401eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_TransId		8
1402eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param1		12
1403eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param2		16
1404eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_ec_Param3		20
1405eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1406b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
14077e75653e64021908ca66b155eeb950d8304c87d8Linus Walleijptp_unpack_EC (PTPParams *params, unsigned char* data, PTPContainer *ec, unsigned int len)
1408eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
14099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	unsigned int	length;
14107e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	int	type;
14117e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
1412eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1413eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
14147e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	memset(ec,0,sizeof(*ec));
14159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
14167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	length=dtoh32a(&data[PTP_ec_Length]);
14179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (length > len) {
14189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ptp_debug (params, "length %d in container, but data only %d bytes?!", length, len);
14199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		return;
14209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	}
14217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	type = dtoh16a(&data[PTP_ec_Type]);
1422b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
14237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Code=dtoh16a(&data[PTP_ec_Code]);
14247e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	ec->Transaction_ID=dtoh32a(&data[PTP_ec_TransId]);
14257e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij
14267e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (type!=PTP_USB_CONTAINER_EVENT) {
14277e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ptp_debug (params, "Unknown canon event type %d (code=%x,tid=%x), please report!",type,ec->Code,ec->Transaction_ID);
14287e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		return;
14297e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
14307e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param1+4)) {
14317e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param1=dtoh32a(&data[PTP_ec_Param1]);
14327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=1;
14337e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
14347e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param2+4)) {
14357e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param2=dtoh32a(&data[PTP_ec_Param2]);
14367e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=2;
14377e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
14387e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	if (length>=(PTP_ec_Param3+4)) {
14397e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Param3=dtoh32a(&data[PTP_ec_Param3]);
14407e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		ec->Nparam=3;
14417e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	}
1442eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
1443eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1444eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij/*
1445eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    PTP Canon Folder Entry unpack
1446eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij    Copyright (c) 2003 Nikolai Kopanygin
1447eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij*/
1448eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectHandle		0
1449eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectFormatCode	4
1450eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Flags			6
1451eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_ObjectSize		7
1452eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Time			11
1453eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij#define PTP_cfe_Filename		15
1454eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
1455b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
1456b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_unpack_Canon_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
1457eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij{
1458eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	int i;
1459eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	if (data==NULL)
1460eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij		return;
1461eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cfe_ObjectHandle]);
1462eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cfe_ObjectFormatCode]);
1463eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Flags=dtoh8a(&data[PTP_cfe_Flags]);
1464b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cfe_ObjectSize]);
1465eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cfe_Time]);
1466eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
1467b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		fe->Filename[i]=(char)dtoh8a(&data[PTP_cfe_Filename+i]);
1468b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
1469b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
147096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij/*
147196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij    PTP Canon EOS Folder Entry unpack
147296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0: 00 00 08 a0     objectid
147396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij4: 01 00 02 00     storageid
147496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij8: 01 30 00 00     ofc
147596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij12: 01 00
147696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij14: 00 00
147796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij16: 11 00 00 00
147896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij20: 00 00 00 00
147996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij24: 00 00 00 80
148096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij28: 00 00 08 a0
148196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij32: 4d 49 53 43-00 00 00 00 00 00 00 00     name
148296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij00 00 00 00
148396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij84 bc 74 46     objectime
148496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
148596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
148696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij(normal PTP GetObjectInfo)
148796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus WalleijObjectInfo for 'IMG_0199.JPG':
148896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  Object ID: 0x92740c72
148996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  StorageID: 0x00020001
149096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectFormat: 0x3801
149196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ProtectionStatus: 0x0000
149296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ObjectCompressedSize: 2217241
149396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbFormat: 0x3808
149496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbCompressedSize: 5122
149596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixWidth: 160
149696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ThumbPixHeight: 120
149796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixWidth: 4000
149896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImagePixHeight: 3000
149996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ImageBitDepth: 24
150096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ParentObject: 0x92740000
150196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationType: 0x0000
150296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  AssociationDesc: 0x00000000
150396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  SequenceNumber: 0x00000000
150496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  ModificationDate: 0x4d985ff0
150596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij  CaptureDate: 0x4d985ff0
150696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
150796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0010  38 00 00 00  Size of this entry
150896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0014  72 0c 74 92  OID
150996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0018  01 00 02 00  StorageID
151096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij001c  01 38 00 00  OFC
15113d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner0020  00 00 00 00 ??
15123d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner0024  21 00 00 00  flags (4 bytes? 1 byte?)
151396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0028  19 d5 21 00  Size
151496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij002c  00 00 74 92  ?
151596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0030  70 0c 74 92  OID
151696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0034  49 4d 47 5f-30 31 39 39 2e 4a 50 47  IMG_0199.JPG
151796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0040  00 00 00 00
151896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij0044  10 7c 98 4d Time
151996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
152096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
152196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij*/
152296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectHandle		0
152396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_StorageID		4
152496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectFormatCode	8
15253d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#define PTP_cefe_Flags			16
152696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_ObjectSize		20
152796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Filename		32
152896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij#define PTP_cefe_Time			48
152996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
153096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijstatic inline void
153196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleijptp_unpack_Canon_EOS_FE (PTPParams *params, unsigned char* data, PTPCANONFolderEntry *fe)
153296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij{
153396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	int i;
153496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
153596aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectHandle=dtoh32a(&data[PTP_cefe_ObjectHandle]);
153696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectFormatCode=dtoh16a(&data[PTP_cefe_ObjectFormatCode]);
153796aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Flags=dtoh8a(&data[PTP_cefe_Flags]);
153896aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->ObjectSize=dtoh32a((unsigned char*)&data[PTP_cefe_ObjectSize]);
153996aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	fe->Time=(time_t)dtoh32a(&data[PTP_cefe_Time]);
154096aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij	for (i=0; i<PTP_CANON_FilenameBufferLen; i++)
154196aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		fe->Filename[i]=(char)data[PTP_cefe_Filename+i];
154296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij}
154396aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
154496aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij
15451a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint16_t
15461a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_unpack_EOS_ImageFormat (PTPParams* params, unsigned char** data )
15471a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
15481a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	/*
15490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  EOS ImageFormat entries (of at least the 5DM2 and the 400D) look like this:
15501a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: number of entries / generated files (1 or 2)
15511a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: size of this entry in bytes (most likely allways 0x10)
15521a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image type (1 == JPG, 6 == RAW)
15530546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		uint32: image size (0 == Large, 1 == Medium, 2 == Small, 0xe == S1, 0xf == S2, 0x10 == S3)
15541a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		uint32: image compression (2 == Standard/JPG, 3 == Fine/JPG, 4 == Lossles/RAW)
15550546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  If the number of entries is 2 the last 4 uint32 repeat.
15561a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15571a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  example:
15581a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		0: 0x       1
15591a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		1: 0x      10
15601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		2: 0x       6
15611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		3: 0x       1
15621a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		4: 0x       4
15631a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15640546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The idea is to simply 'condense' these values to just one uint16 to be able to conveniently
15651a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  use the available enumeration facilities (look-up table). The image size and compression
15661a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  values fully describe the image format. Hence we generate a uint16 with the four nibles set
15671a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  as follows: entry 1 size | entry 1 compression | entry 2 size | entry 2 compression.
15681a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  The above example would result in the value 0x1400.
15690546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
15700546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  The EOS 5D Mark III (and possibly other high-end EOS as well) added the extra fancy S1, S2
15710546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	  and S3 JPEG options. S1 replaces the old Small. -1 the S1/S2/S3 to prevent the 0x10 overflow.
15721a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	  */
15731a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15741a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	const unsigned char* d = *data;
15751a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = dtoh32a( d );
15761a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t l, s1, c1, s2 = 0, c2 = 0;
15771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n != 1 && n !=2) {
15791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (n != 1 && n != 2: %d)", n);
15801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
15811a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
15821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	l = dtoh32a( d+=4 );
15841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (l != 0x10) {
15851a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
15861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return 0;
15871a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
15881a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	d+=4; /* skip type */
15901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	s1 = dtoh32a( d+=4 );
15911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	c1 = dtoh32a( d+=4 );
15921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
15931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n == 2) {
15941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		l = dtoh32a( d+=4 );
15951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		if (l != 0x10) {
15961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "parsing EOS ImageFormat property failed (l != 0x10: 0x%x)", l);
15971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			return 0;
15981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		}
15991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		d+=4; /* skip type */
16001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		s2 = dtoh32a( d+=4 );
16011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		c2 = dtoh32a( d+=4 );
16021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
16031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	*data = (unsigned char*) d+4;
16051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16060546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	/* deal with S1/S2/S3 JPEG sizes, see above. */
16070546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s1 >= 0xe )
16080546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s1--;
16090546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if( s2 >= 0xe )
16100546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		s2--;
16110546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return ((s1 & 0xF) << 12) | ((c1 & 0xF) << 8) | ((s2 & 0xF) << 4) | ((c2 & 0xF) << 0);
16131a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
16141a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijstatic inline uint32_t
16161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleijptp_pack_EOS_ImageFormat (PTPParams* params, unsigned char* data, uint16_t value)
16171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij{
16181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t n = (value & 0xFF) ? 2 : 1;
16191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	uint32_t s = 4 + 0x10 * n;
16201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if( !data )
16221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		return s;
16231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16240546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#define PACK_5DM3_SMALL_JPEG_SIZE( X ) (X) >= 0xd ? (X)+1 : (X)
16250546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=0, n);
16271a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, 0x10);
16281a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, ((value >> 8) & 0xF) == 4 ? 6 : 1);
16290546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 12) & 0xF));
16301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	htod32a(data+=4, (value >> 8) & 0xF);
16311a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	if (n==2) {
16331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, 0x10);
16341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, ((value >> 0) & 0xF) == 4 ? 6 : 1);
16350546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data+=4, PACK_5DM3_SMALL_JPEG_SIZE((value >> 4) & 0xF));
16361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij		htod32a(data+=4, (value >> 0) & 0xF);
16371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	}
16381a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
16390546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner#undef PACK_5DM3_SMALL_JPEG_SIZE
16400546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16410546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return s;
16420546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
16430546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
16443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner/* 00: 32 bit size
16453d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 04: 16 bit subsize
16463d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 08: 16 bit version (?)
16473d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 0c: 16 bit focus_points_in_struct
16483d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 10: 16 bit focus_points_in_use
16493d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 14: variable arrays:
16503d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit sizex, 16 bit sizey
16513d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit othersizex, 16 bit othersizey
16523d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array height[focus_points_in_struct]
16533d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array width[focus_points_in_struct]
16543d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array offsetheight[focus_points_in_struct] middle is 0
16553d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 	16 bit array offsetwidth[focus_points_in_struct] middle is ?
16563d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * bitfield of selected focus points, starting with 0 [size focus_points_in_struct in bits]
16573d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * unknown stuff , likely which are active
16583d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * 16 bit 0xffff
16593d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner *
16603d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner * size=NxN,size2=NxN,points={NxNxNxN,NxNxNxN,...},selected={0,1,2}
16613d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner */
16623d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerstatic inline char*
1663aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissnerptp_unpack_EOS_FocusInfoEx (PTPParams* params, unsigned char** data, uint32_t datasize )
16643d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner{
16653d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t size 			= dtoh32a( *data );
16663d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t halfsize		= dtoh16a( (*data) + 4);
16673d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t version		= dtoh16a( (*data) + 6);
16683d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t focus_points_in_struct	= dtoh16a( (*data) + 8);
16693d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t focus_points_in_use	= dtoh16a( (*data) + 10);
16703d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t sizeX			= dtoh16a( (*data) + 12);
16713d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t sizeY			= dtoh16a( (*data) + 14);
16723d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t size2X			= dtoh16a( (*data) + 16);
16733d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t size2Y			= dtoh16a( (*data) + 18);
16743d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t i;
16753d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	uint32_t maxlen;
16763d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	char	*str, *p;
16773d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
1678aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if ((size >= datasize) || (size < 20))
1679aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("bad size 1");
1680aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	/* every focuspoint gets 4 (16 bit number possible "-" sign and a x) and a ,*/
16813d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	/* inital things around lets say 100 chars at most.
1682aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	 * FIXME: check selected when we decode it
1683aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	 */
1684aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (size < focus_points_in_struct*8) {
1685aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		ptp_error(params, "focus_points_in_struct %d is too large vs size %d", focus_points_in_struct, size);
1686aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("bad size 2");
1687aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	}
1688aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (focus_points_in_use > focus_points_in_struct) {
1689aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		ptp_error(params, "focus_points_in_use %d is larger than focus_points_in_struct %d", focus_points_in_use, focus_points_in_struct);
1690aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("bad size 3");
1691aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	}
1692aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
1693aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	maxlen = focus_points_in_use*32 + 100 + (size - focus_points_in_struct*8)*2;
16943d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (halfsize != size-4) {
16953d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_error(params, "halfsize %d is not expected %d", halfsize, size-4);
1696aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("bad size 4");
16973d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
16983d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (20 + focus_points_in_struct*8 + (focus_points_in_struct+7)/8 > size) {
16993d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus 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);
1700aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("bad size 5");
17013d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
17023d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#if 0
17033d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug(params,"d1d3 content:");
17043d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=0;i<size;i+=2)
17053d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		ptp_debug(params,"%d: %02x %02x", i, (*data)[i], (*data)[i+1]);
17063d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner#endif
1707aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	ptp_debug(params,"d1d3 version %d", version);
1708aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	ptp_debug(params,"d1d3 size %d", size);
17093d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	ptp_debug(params,"d1d3 focus points in struct %d, in use %d", focus_points_in_struct, focus_points_in_use);
17103d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17113d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	str = (char*)malloc( maxlen );
17123d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (!str)
17133d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return NULL;
17143d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p = str;
17153d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17163d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"eosversion=%d,size=%dx%d,size2=%dx%d,points={", version, sizeX, sizeY, size2X, size2Y);
17173d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=0;i<focus_points_in_use;i++) {
17183d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t x = dtoh16a((*data) + focus_points_in_struct*4 + 20 + 2*i);
17193d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t y = dtoh16a((*data) + focus_points_in_struct*6 + 20 + 2*i);
17203d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t w = dtoh16a((*data) + focus_points_in_struct*2 + 20 + 2*i);
17213d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		int16_t h = dtoh16a((*data) + focus_points_in_struct*0 + 20 + 2*i);
17223d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17233d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		p += sprintf(p,"{%d,%d,%d,%d}",x,y,w,h);
17243d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17253d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		if (i<focus_points_in_use-1)
17263d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			p += sprintf(p,",");
17273d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
17283d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"},select={");
17293d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=0;i<focus_points_in_use;i++) {
1730aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if ((1<<(i%8)) & ((*data)[focus_points_in_struct*8+20+i/8]))
17313d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			p+=sprintf(p,"%d,", i);
17323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
17333d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17343d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"},unknown={");
17353d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (i=focus_points_in_struct*8+(focus_points_in_struct+7)/8+20;i<size;i++) {
1736aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if ((p-str) > maxlen - 4)
1737aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
17383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		p+=sprintf(p,"%02x", (*data)[i]);
17393d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	}
17403d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	p += sprintf(p,"}");
17413d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	return str;
17423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner}
17433d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
17450546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline char*
17460546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_unpack_EOS_CustomFuncEx (PTPParams* params, unsigned char** data )
17470546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
17480546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = dtoh32a( *data );
17490546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i;
1750aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	char	*str, *p;
1751aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
1752aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (s > 1024) {
1753aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		ptp_debug (params, "customfuncex data is larger than 1k / %d... unexpected?", s);
1754aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("bad length");
1755aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	}
1756aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	str = (char*)malloc( s*2+s/4+1 ); /* n is size in uint32, maximum %x len is 8 chars and \0*/
17570546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!str)
1758aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		return strdup("malloc failed");
17590546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
1760aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	p = str;
17610546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i < n; ++i)
17620546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		p += sprintf(p, "%x,", dtoh32a( *data + 4*i ));
17630546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	return str;
17640546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner}
17650546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
17660546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerstatic inline uint32_t
17670546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissnerptp_pack_EOS_CustomFuncEx (PTPParams* params, unsigned char* data, char* str)
17680546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner{
17690546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t s = strtoul(str, NULL, 16);
17700546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	uint32_t n = s/4, i, v;
17710546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
17720546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	if (!data)
17730546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		return s;
17740546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
17750546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	for (i=0; i<n; i++)
17760546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	{
17770546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		v = strtoul(str, &str, 16);
1778a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij		str++; /* skip the ',' delimiter */
17790546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner		htod32a(data + i*4, v);
17800546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner	}
17810546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner
17821a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij	return s;
17831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij}
17841a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
1785b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij/*
1786f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij    PTP EOS Changes Entry unpack
1787f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij*/
1788f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Size		0
1789f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Type		4
1790f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1791f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Subtype	8	/* only for properties */
1792f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Val_Data	0xc	/* only for properties */
1793f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Type	0xc	/* only for property descs */
1794f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Count	0x10	/* only for property descs */
1795f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij#define PTP_ece_Prop_Desc_Data	0x14	/* only for property descs */
1796f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1797d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_RequestObjectTransfer */
1798d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_ObjectID	8
1799d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_OFC		0x0c
1800d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Size		0x14
1801d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OI_Name		0x1c
1802d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij
1803d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij/* for PTP_EC_CANON_EOS_ObjectAddedEx */
1804d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_ObjectID	8
1805d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_StorageID	0x0c
1806d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_OFC		0x10
1807d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Size		0x1c
1808d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Parent	0x20
1809d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#define PTP_ece_OA_Name		0x28
1810f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1811aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_ObjectID	8	/* OK */
1812aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_StorageID	0x0c	/* OK */
1813aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_OFC		0x10	/* OK */
1814aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_Size	0x1c	/* OK, might be 64 bit now? */
1815aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_Parent	0x24
1816aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_2ndOID	0x28
1817aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece2_OA_Name	0x2c	/* OK */
1818aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
1819aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner/* for PTP_EC_CANON_EOS_ObjectAddedNew */
1820aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece_OAN_OFC		0x0c
1821aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner#define PTP_ece_OAN_Size	0x14
1822aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
18233d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissnerstatic PTPDevicePropDesc*
18243d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner_lookup_or_allocate_canon_prop(PTPParams *params, uint16_t proptype)
18253d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner{
18263d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	unsigned int j;
18273d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
18283d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	for (j=0;j<params->nrofcanon_props;j++)
18293d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		if (params->canon_props[j].proptype == proptype)
18303d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			break;
18313d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (j<params->nrofcanon_props)
18323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		return &params->canon_props[j].dpd;
18333d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
18343d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	if (j)
18353d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
18363d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	else
18373d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		params->canon_props = malloc(sizeof(params->canon_props[0]));
18383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].proptype = proptype;
18393d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].size = 0;
18403d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].data = NULL;
18413d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
18423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].dpd.GetSet = 1;
18433d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
18443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	params->nrofcanon_props = j+1;
18453d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	return &params->canon_props[j].dpd;
18463d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner}
18473d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
18483d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner
1849f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleijstatic inline int
18509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleijptp_unpack_CANON_changes (PTPParams *params, unsigned char* data, int datasize, PTPCanon_changes_entry **pce)
1851f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij{
1852f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	int	i = 0, entries = 0;
1853f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	unsigned char	*curdata = data;
18549783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	PTPCanon_changes_entry *ce;
1855f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1856f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	if (data==NULL)
1857f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		return 0;
1858aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	while (curdata - data + 8 < datasize) {
1859f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1860f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1861f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1862aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (size > datasize) {
1863aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "size %d is larger than datasize %d", size, datasize);
1864aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1865aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
1866aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (size < 8) {
1867aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "size %d is smaller than 8.", size);
1868aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1869aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
1870f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		if ((size == 8) && (type == 0))
1871f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1872aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if ((curdata - data) + size >= datasize) {
1873aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "canon eos event decoder ran over supplied data, skipping entries");
1874aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1875aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
18769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		if (type == PTP_EC_CANON_EOS_OLCInfoChanged) {
18779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			unsigned int j;
18789783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
1879aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			entries++;
1880aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if (size >= 12+2) {
1881aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				for (j=0;j<31;j++)
1882aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					if (dtoh16a(curdata+12) & (1<<j))
1883aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner						entries++;
1884aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			}
18859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
18869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		curdata += size;
1887f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		entries++;
1888f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
18899783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	ce = malloc (sizeof(PTPCanon_changes_entry)*(entries+1));
18909783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!ce) return 0;
1891f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1892f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	curdata = data;
1893aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	while (curdata - data  + 8 < datasize) {
1894f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	size = dtoh32a(&curdata[PTP_ece_Size]);
1895f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		uint32_t	type = dtoh32a(&curdata[PTP_ece_Type]);
1896f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1897aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (size > datasize) {
1898aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "size %d is larger than datasize %d", size, datasize);
1899aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1900aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
1901aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (size < 8) {
1902aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "size %d is smaller than 8", size);
1903aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1904aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
1905aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
1906aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if ((size == 8) && (type == 0))
1907aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1908aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
1909aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if ((curdata - data) + size >= datasize) {
1910aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "canon eos event decoder ran over supplied data, skipping entries");
1911aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1912aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
1913aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
19149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
19159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ce[i].u.info = NULL;
1916f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		switch (type) {
1917aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		case PTP_EC_CANON_EOS_ObjectAddedEx:
1918aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if (size < PTP_ece_OA_Name+1) {
1919aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OA_Name+1);
1920aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				break;
1921aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			}
19229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
19239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OA_ObjectID]);
1924aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.StorageID	= dtoh32a(&curdata[PTP_ece_OA_StorageID]);
19259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece_OA_Parent]);
19269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OA_OFC]);
19279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece_OA_Size]);
1928aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.Filename 	= strdup(((char*)&curdata[PTP_ece_OA_Name]));
1929aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			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);
1930aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			break;
1931aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner                case PTP_EC_CANON_EOS_ObjectAddedUnknown:	/* FIXME: review if the data used is correct */
1932aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if (size < PTP_ece2_OA_Name+1) {
1933aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "size %d is smaller than %d", size, PTP_ece2_OA_Name+1);
1934aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				break;
1935aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			}
1936aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTINFO;
1937aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece2_OA_ObjectID]);
1938aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.StorageID	= dtoh32a(&curdata[PTP_ece2_OA_StorageID]);
1939aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.ParentObject	= dtoh32a(&curdata[PTP_ece2_OA_Parent]);
1940aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece2_OA_OFC]);
1941aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.ObjectCompressedSize= dtoh32a(&curdata[PTP_ece2_OA_Size]);	/* FIXME: might be 64bit now */
1942aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.Filename 	= strdup(((char*)&curdata[PTP_ece2_OA_Name]));
19439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus 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);
1944d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			break;
1945aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		case PTP_EC_CANON_EOS_RequestObjectTransfer:
1946aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		case PTP_EC_CANON_EOS_RequestObjectTransferNew: /* FIXME: confirm */
1947aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if (size < PTP_ece_OI_Name+1) {
1948aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_OI_Name+1);
1949aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				break;
1950aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			}
19519783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTTRANSFER;
19529783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oid    		= dtoh32a(&curdata[PTP_ece_OI_ObjectID]);
1953aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.StorageID 	= 0; /* use as marker */
19549783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectFormat 	= dtoh16a(&curdata[PTP_ece_OI_OFC]);
19559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ParentObject	= 0; /* check, but use as marker */
19569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.object.oi.ObjectCompressedSize = dtoh32a(&curdata[PTP_ece_OI_Size]);
1957aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.object.oi.Filename 	= strdup(((char*)&curdata[PTP_ece_OI_Name]));
19589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
19599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus 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);
1960f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
1961aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		case PTP_EC_CANON_EOS_AvailListChanged: {	/* property desc */
1962f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
1963f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxtype = dtoh32a(&curdata[PTP_ece_Prop_Desc_Type]);
1964f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			uint32_t	propxcnt = dtoh32a(&curdata[PTP_ece_Prop_Desc_Count]);
1965e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij			unsigned char	*xdata = &curdata[PTP_ece_Prop_Desc_Data];
19662ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij			unsigned int	j;
1967f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			PTPDevicePropDesc	*dpd;
1968f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
1969aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if (size < PTP_ece_Prop_Desc_Data) {
1970aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Desc_Data);
1971aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				break;
1972aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			}
1973aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner
19747e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS prop %04x desc record, datasize %d, propxtype %d", i, proptype, size-PTP_ece_Prop_Desc_Data, propxtype);
1975f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			for (j=0;j<params->nrofcanon_props;j++)
1976f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (params->canon_props[j].proptype == proptype)
1977f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
1978f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (j==params->nrofcanon_props) {
19793bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				ptp_debug (params, "event %d: propdesc %x, default value not found.", i, proptype);
1980f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1981f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
1982f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			dpd = &params->canon_props[j].dpd;
19837e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			/* 1 - uint16 ?
19847e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 3 - uint16
19857e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 * 7 - string?
19867e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			 */
1987f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (propxtype != 3) {
1988aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "event %d: propxtype is %x for %04x, unhandled, size %d", i, propxtype, proptype, size);
19893bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij				for (j=0;j<size-PTP_ece_Prop_Desc_Data;j++)
1990e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					ptp_debug (params, "    %d: %02x", j, xdata[j]);
1991f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
1992f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
19931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			if (! propxcnt)
19941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
19959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (propxcnt >= 2<<16) /* buggy or exploit */
19969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				break;
19971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
19981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			ptp_debug (params, "event %d: propxtype is %x, prop is 0x%04x, data type is 0x%04x, propxcnt is %d.",
19991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				   i, propxtype, proptype, dpd->DataType, propxcnt);
20001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FormFlag = PTP_DPFF_Enumeration;
20011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.NumberOfValues = propxcnt;
20023d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			free (dpd->FORM.Enum.SupportedValue);
20031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			dpd->FORM.Enum.SupportedValue = malloc (sizeof (PTPPropertyValue)*propxcnt);
20041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
20051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			switch (proptype) {
20061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormat:
20071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatCF:
20081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatSD:
20091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			case PTP_DPC_CANON_EOS_ImageFormatExtHD:
20101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* special handling of ImageFormat properties */
2011f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<propxcnt;j++) {
20121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->FORM.Enum.SupportedValue[j].u16 =
20139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij							ptp_unpack_EOS_ImageFormat( params, &xdata );
20141a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, dpd->FORM.Enum.SupportedValue[j].u16);
20151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
20161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				break;
20171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij			default:
20181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* 'normal' enumerated types */
20191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (dpd->DataType) {
20201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX( TYPE, CONV )\
2021aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					if (sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt + PTP_ece_Prop_Desc_Data > size) {	\
2022aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner						ptp_debug (params, "size %d does not match needed %d", sizeof(dpd->FORM.Enum.SupportedValue[j].TYPE)*propxcnt + PTP_ece_Prop_Desc_Data, size);	\
2023aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner						break;							\
2024aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					}								\
2025aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					for (j=0;j<propxcnt;j++) { 					\
2026aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner						dpd->FORM.Enum.SupportedValue[j].TYPE = CONV(xdata); 	\
2027e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "event %d: suppval[%d] of %x is 0x%x.", i, j, proptype, CONV(xdata)); \
2028e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						xdata += 4; /* might only be for propxtype 3 */ \
20291a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					} \
20301a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
20311a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
20321a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_INT16:	XX( i16, dtoh16a );
20331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT32:	XX( u32, dtoh32a );
20341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT16:	XX( u16, dtoh16a );
20351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DTC_UINT8:	XX( u8,  dtoh8a );
20361a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
20371a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				default:
2038aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					free (dpd->FORM.Enum.SupportedValue);
2039aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					dpd->FORM.Enum.SupportedValue = NULL;
2040aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					dpd->FORM.Enum.NumberOfValues = 0;
2041aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					ptp_debug (params ,"event %d: data type 0x%04x of %x unhandled, size %d, raw values:", i, dpd->DataType, proptype, dtoh32a(xdata), size);
2042e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					for (j=0;j<(size-PTP_ece_Prop_Desc_Data)/4;j++, xdata+=4) /* 4 is good for propxtype 3 */
2043e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %3d: 0x%8x", j, dtoh32a(xdata));
20441a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
2045f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
2046f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			}
2047f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
2048f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
20497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case PTP_EC_CANON_EOS_PropValueChanged:
2050f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			if (size >= 0xc) {	/* property info */
20512ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				unsigned int j;
2052f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				uint32_t	proptype = dtoh32a(&curdata[PTP_ece_Prop_Subtype]);
2053e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij				unsigned char	*xdata = &curdata[PTP_ece_Prop_Val_Data];
2054f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				PTPDevicePropDesc	*dpd;
2055f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
2056aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				if (size < PTP_ece_Prop_Val_Data) {
2057aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					ptp_debug (params, "size %d is smaller than %d", size, PTP_ece_Prop_Val_Data);
2058aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					break;
2059aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				}
20601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				ptp_debug (params, "event %d: EOS prop %04x info record, datasize is %d", i, proptype, size-PTP_ece_Prop_Val_Data);
2061f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				for (j=0;j<params->nrofcanon_props;j++)
2062f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (params->canon_props[j].proptype == proptype)
2063f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						break;
2064f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				if (j<params->nrofcanon_props) {
2065f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (	(params->canon_props[j].size != size) ||
2066e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						(memcmp(params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data))) {
2067f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props[j].data = realloc(params->canon_props[j].data,size-PTP_ece_Prop_Val_Data);
2068aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner						params->canon_props[j].size = size;
2069e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						memcpy (params->canon_props[j].data,xdata,size-PTP_ece_Prop_Val_Data);
2070f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					}
2071f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				} else {
2072f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					if (j)
2073f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = realloc(params->canon_props, sizeof(params->canon_props[0])*(j+1));
2074f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					else
2075f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij						params->canon_props = malloc(sizeof(params->canon_props[0]));
2076f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].proptype = proptype;
2077f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].size = size;
2078f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].data = malloc(size-PTP_ece_Prop_Val_Data);
2079e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					memcpy(params->canon_props[j].data, xdata, size-PTP_ece_Prop_Val_Data);
2080f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					memset (&params->canon_props[j].dpd,0,sizeof(params->canon_props[j].dpd));
2081f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.GetSet = 1;
2082f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->canon_props[j].dpd.FormFlag = PTP_DPFF_None;
2083f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					params->nrofcanon_props = j+1;
2084f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
2085f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				dpd = &params->canon_props[j].dpd;
20861a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
20879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
20889783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
2089d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
20901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* fix GetSet value */
20911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				switch (proptype) {
20921a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#define XX(x) case PTP_DPC_CANON_##x:
20931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusMode)
20941a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryPower)
20951a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatterySelect)
20961a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ModelID)
20971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_PTPExtensionVersion)
20981a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DPOFVersion)
20991a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AvailableShots)
21001a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentStorage)
21011a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CurrentFolder)
21021a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenu)
21031a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_MyMenuList)
21041a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_HDDirectoryStructure)
21051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_BatteryInfo)
21061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_AdapterInfo)
21071a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensStatus)
21081a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_CardExtension)
21091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_TempStatus)
21101a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_ShutterCounter)
21111a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_SerialNumber)
21121a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfFieldPreview)
21131a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EVFRecordStatus)
21141a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LvAfSystem)
21151a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_FocusInfoEx)
21161a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_DepthOfField)
21171a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_Brightness)
21181a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_EFComp)
21191a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensName)
21201a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					XX(EOS_LensID)
21211a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#undef XX
21221a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						dpd->GetSet = PTP_DPGS_Get;
21231a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						break;
21241a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				}
21251a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
21261a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				/* set DataType */
2127f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (proptype) {
2128ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DPC_CANON_EOS_CameraTime:
21299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				case PTP_DPC_CANON_EOS_UTCTime:
21309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				case PTP_DPC_CANON_EOS_Summertime: /* basical the DST flag */
2131d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_AvailableShots:
2132d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CaptureDestination:
2133d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXA:
2134d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceXB:
2135d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentStorage:
2136d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_CurrentFolder:
2137d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ShutterCounter:
2138d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ModelID:
2139d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LensID:
2140d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_StroboFiring:
21413d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_AFSelectFocusArea:
21423d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_ContinousAFMode:
2143aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				case PTP_DPC_CANON_EOS_MirrorUpSetting:
2144ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
2145ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
21460d762ccc39331608119dd0267021b165e22de499Linus Walleij				/* enumeration for AEM is never provided, but is available to set */
21470d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_AutoExposureMode:
21480d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
21490d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FormFlag = PTP_DPFF_Enumeration;
21500d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->FORM.Enum.NumberOfValues = 0;
21510d762ccc39331608119dd0267021b165e22de499Linus Walleij					break;
2152f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Aperture:
2153f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ShutterSpeed:
2154f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_ISOSpeed:
21557e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_FocusMode:
21567e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorSpace:
21577e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_BatteryPower:
2158e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BatterySelect:
2159d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_PTPExtensionVersion:
21601a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_DriveMode:
21611a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_AEB:
2162e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_BracketMode:
2163e29ca68e54b8dd04e54499d6b5fa8668770a20cfLinus Walleij				case PTP_DPC_CANON_EOS_QuickReviewTime:
21640d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFMode:
21650d762ccc39331608119dd0267021b165e22de499Linus Walleij				case PTP_DPC_CANON_EOS_EVFOutputDevice:
2166a381e8a353dfd64d25169cfb950b4dc7d4a3032aLinus Walleij				case PTP_DPC_CANON_EOS_AutoPowerOff:
21673d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_EVFRecordStatus:
2168f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT16;
2169f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2170f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_PictureStyle:
2171f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalance:
2172f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_MeteringMode:
21733d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_ExpCompensation:
2174f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_UINT8;
2175f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2176f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DPC_CANON_EOS_Owner:
21771a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Artist:
21781a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_Copyright:
21791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_SerialNumber:
21801a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij				case PTP_DPC_CANON_EOS_LensName:
2181f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->DataType = PTP_DTC_STR;
2182f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
21837e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustA:
21847e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WhiteBalanceAdjustB:
21857e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					dpd->DataType = PTP_DTC_INT16;
21867e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
21877e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* unknown props, listed from dump.... all 16 bit, but vals might be smaller */
21887e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DPOFVersion:
21891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
21901a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint16", i ,proptype, size-PTP_ece_Prop_Val_Data);
21911a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
2192e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
21931a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					break;
21947e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc1:
21957e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc2:
21967e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc3:
21977e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc4:
21987e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc5:
21997e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc6:
22007e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc7:
22017e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc8:
22027e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc9:
22037e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc10:
22047e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CustomFunc11:
22051a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					dpd->DataType = PTP_DTC_UINT8;
22061a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint8", i ,proptype, size-PTP_ece_Prop_Val_Data);
22077e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
2208e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
22091a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					/* custom func entries look like this on the 400D: '5 0 0 0 ?' = 4 bytes size + 1 byte data */
2210e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					xdata += 4;
22117e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
22127e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				/* yet unknown 32bit props */
22137e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_ColorTemperature:
22147e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_WftStatus:
22157e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_LensStatus:
22167e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_CardExtension:
22177e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_TempStatus:
22187e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_PhotoStudioMode:
22197e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfFieldPreview:
22207e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFSharpness:
22217e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFWBMode:
22227e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFClickWBCoeffs:
22237e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				case PTP_DPC_CANON_EOS_EVFColorTemp:
2224d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_ExposureSimMode:
2225d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvAfSystem:
2226d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_MovSize:
2227d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_DepthOfField:
2228d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				case PTP_DPC_CANON_EOS_LvViewTypeSelect:
22292ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				case PTP_DPC_CANON_EOS_AloMode:
22309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				case PTP_DPC_CANON_EOS_Brightness:
22310d762ccc39331608119dd0267021b165e22de499Linus Walleij					dpd->DataType = PTP_DTC_UINT32;
22327e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d, using uint32", i ,proptype, size-PTP_ece_Prop_Val_Data);
22331a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					if ((size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) != 0)
22341a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij						ptp_debug (params, "event %d: Warning: datasize modulo sizeof(uint32) is not 0: ", i, (size-PTP_ece_Prop_Val_Data) % sizeof(uint32_t) );
22351a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij					for (j=0;j<(size-PTP_ece_Prop_Val_Data)/sizeof(uint32_t);j++)
22363d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner						ptp_debug (params, "    %d: 0x%8x", j, dtoh32a(xdata+j*4));
22377e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					break;
2238d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				/* ImageFormat properties have to be ignored here, see special handling below */
2239d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
2240d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
2241d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
2242d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
22430546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
22443d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_FocusInfoEx:
2245d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
2246f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
22473bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params, "event %d: Unknown EOS property %04x, datasize is %d", i ,proptype, size-PTP_ece_Prop_Val_Data);
22483bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					for (j=0;j<size-PTP_ece_Prop_Val_Data;j++)
2249e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij						ptp_debug (params, "    %d: %02x", j, xdata[j]);
2250f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2251f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
2252f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				switch (dpd->DataType) {
2253ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij				case PTP_DTC_UINT32:
2254e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u32	= dtoh32a(xdata);
2255e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u32		= dtoh32a(xdata);
22563bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params ,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u32);
2257ac052c1ac330b94932d2b4f774e0053e78e91216Linus Walleij					break;
22582ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				case PTP_DTC_INT16:
22592ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					dpd->FactoryDefaultValue.i16	= dtoh16a(xdata);
22602ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					dpd->CurrentValue.i16		= dtoh16a(xdata);
22612ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %d", i, proptype, dpd->CurrentValue.i16);
22622ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij					break;
2263f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT16:
2264e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= dtoh16a(xdata);
2265e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u16		= dtoh16a(xdata);
22663bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
2267f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2268f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_UINT8:
2269e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u8	= dtoh8a(xdata);
2270e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.u8		= dtoh8a(xdata);
22713bc0d7f58d56fad55449927a658951ca80a3258cLinus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u8);
2272f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
22733d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DTC_INT8:
22743d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->FactoryDefaultValue.i8	= dtoh8a(xdata);
22753d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->CurrentValue.i8		= dtoh8a(xdata);
22763d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					ptp_debug (params,"event %d: currentvalue of %x is %x", i, proptype, dpd->CurrentValue.i8);
22773d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					break;
2278f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				case PTP_DTC_STR: {
22791a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#if 0 /* 5D MII and 400D aktually store plain ASCII in their string properties */
2280f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					uint8_t len = 0;
2281f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->FactoryDefaultValue.str	= ptp_unpack_string(params, data, 0, &len);
2282f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					dpd->CurrentValue.str		= ptp_unpack_string(params, data, 0, &len);
22831a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#else
22843d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->FactoryDefaultValue.str);
2285e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.str	= strdup( (char*)xdata );
22860d762ccc39331608119dd0267021b165e22de499Linus Walleij
22873d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->CurrentValue.str);
2288e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->CurrentValue.str		= strdup( (char*)xdata );
22891a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij#endif
22907e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij					ptp_debug (params,"event %d: currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
2291f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2292f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
2293f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				default:
2294f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					/* debug is printed in switch above this one */
2295f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij					break;
2296f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				}
22971a0c3012b1cec61f54393ec3975c53141f698c8dLinus Walleij
22980546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				/* ImageFormat and customFuncEx special handling (WARNING: dont move this in front of the dpd->DataType switch!) */
2299d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				switch (proptype) {
2300d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormat:
2301d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatCF:
2302d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatSD:
2303d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				case PTP_DPC_CANON_EOS_ImageFormatExtHD:
2304d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->DataType = PTP_DTC_UINT16;
2305e206af608ab20ea4de89739d792ba2738377ccf8Linus Walleij					dpd->FactoryDefaultValue.u16	= ptp_unpack_EOS_ImageFormat( params, &xdata );
2306d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					dpd->CurrentValue.u16		= dpd->FactoryDefaultValue.u16;
2307d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					ptp_debug (params,"event %d: decoded imageformat, currentvalue of %x is %x", i, proptype, dpd->CurrentValue.u16);
2308d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij					break;
23090546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner				case PTP_DPC_CANON_EOS_CustomFuncEx:
23100546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->DataType = PTP_DTC_STR;
23113d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->FactoryDefaultValue.str);
23123d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->CurrentValue.str);
23133d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->FactoryDefaultValue.str	= ptp_unpack_EOS_CustomFuncEx( params, &xdata );
23140546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					dpd->CurrentValue.str		= strdup( (char*)dpd->FactoryDefaultValue.str );
23150546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					ptp_debug (params,"event %d: decoded custom function, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
23160546a76acd169daf35572ece1f58c9b3bc7f0f56Marcus Meissner					break;
23173d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				case PTP_DPC_CANON_EOS_FocusInfoEx:
23183d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->DataType = PTP_DTC_STR;
23193d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->FactoryDefaultValue.str);
23203d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					free (dpd->CurrentValue.str);
2321aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner					dpd->FactoryDefaultValue.str	= ptp_unpack_EOS_FocusInfoEx( params, &xdata, size );
23223d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					dpd->CurrentValue.str		= strdup( (char*)dpd->FactoryDefaultValue.str );
23233d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					ptp_debug (params,"event %d: decoded focus info, currentvalue of %x is %s", i, proptype, dpd->CurrentValue.str);
23243d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					break;
2325d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				}
2326d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij
2327f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij				break;
2328f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
23299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		/* one more information record handed to us */
23309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		case PTP_EC_CANON_EOS_OLCInfoChanged: {
23319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			uint32_t		len, curoff;
23329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			uint16_t		mask,proptype;
23339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			PTPDevicePropDesc	*dpd;
23349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
23359783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			/* unclear what OLC stands for */
23369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ptp_debug (params, "event %d: EOS event OLCInfoChanged (size %d)", i, size);
23379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (size >= 0x8) {	/* event info */
23383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				unsigned int k;
23393d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				for (k=8;k<size;k++)
23403d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					ptp_debug (params, "    %d: %02x", k-8, curdata[k]);
23419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			len = dtoh32a(curdata+8);
2343aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if ((len != size-8) && (len != size-4)) {
23449783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2345aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ce[i].u.info = strdup("OLC size unexpected");
2346aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "event %d: OLC unexpected size %d for blob len %d (not -4 nor -8)", i, size, len);
23479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				break;
23489783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			mask = dtoh16a(curdata+8+4);
2350aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			if (size < 14) {
2351aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2352aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ce[i].u.info = strdup("OLC size too small");
2353aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				ptp_debug (params, "event %d: OLC unexpected size %d", i, size);
2354aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				break;
2355aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			}
23569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			curoff = 8+4+4;
23579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_BUTTON) {
23589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
23599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("Button 1234567"));
23609783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info, "Button %d",  dtoh16a(curdata+curoff));
23619783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23629783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 2;
23639783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23649783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
23659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_SHUTTERSPEED) {
23669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* 6 bytes: 01 01 98 10 00 60 */
23679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* this seesm to be the shutter speed record */
23689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				proptype = PTP_DPC_CANON_EOS_ShutterSpeed;
23693d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				dpd = _lookup_or_allocate_canon_prop(params, proptype);
23709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->CurrentValue.u16 = curdata[curoff+5]; /* just use last byte */
23719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
23729783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
23739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
23749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 6;
23759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23779783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_APERTURE) {
23789783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* 5 bytes: 01 01 5b 30 30 */
23799783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* this seesm to be the aperture record */
23809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				proptype = PTP_DPC_CANON_EOS_Aperture;
23813d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				dpd = _lookup_or_allocate_canon_prop(params, proptype);
23829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->CurrentValue.u16 = curdata[curoff+4]; /* just use last byte */
23839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
23849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
23859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
23869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 5;
23879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
23889783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
23899783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & CANON_EOS_OLC_ISO) {
23909783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* 5 bytes: 01 01 00 78 */
23919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* this seesm to be the aperture record */
23929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				proptype = PTP_DPC_CANON_EOS_ISOSpeed;
23933d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				dpd = _lookup_or_allocate_canon_prop(params, proptype);
23949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				dpd->CurrentValue.u16 = curdata[curoff+3]; /* just use last byte */
23959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij
23969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_PROPERTY;
23979783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.propid = proptype;
23989783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 4;
23999783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24019783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0010) {
24029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0010: 4 bytes, 04 00 00 00 observed */
24039783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
24049783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0010 content 01234567")+1);
24059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0010 content %02x%02x%02x%02x",
24069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
24099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3]
24109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
24119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 4;
24129783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0020) {
24159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0020: 6 bytes, 00 00 00 00 00 00 observed */
24169783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
24179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0020 content 0123456789ab")+1);
24189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0020 content %02x%02x%02x%02x%02x%02x",
24199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
24229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
24239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
24249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5]
24259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
24269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 6;
24279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0040) {
24303d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				int	value = (signed char)curdata[curoff+2];
24319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0040: 7 bytes, 01 01 00 00 00 00 00 observed */
24323d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				/* exposure indicator */
24339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
24343d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].u.info = malloc(strlen("OLCInfo exposure indicator 012345678901234567890123456789abcd")+1);
24353d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				sprintf(ce[i].u.info,"OLCInfo exposure indicator %d,%d,%d.%d (%02x%02x%02x%02x)",
24369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24383d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner					value/10,abs(value)%10,
24399783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
24409783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
24419783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
24429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6]
24439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
24449783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 7;
24459783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24469783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24479783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0080) {
24489783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0080: 4 bytes, 00 00 00 00 observed */
24499783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
24509783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0080 content 01234567")+1);
24519783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0080 content %02x%02x%02x%02x",
24529783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24539783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24549783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
24559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3]
24569783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
24579783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 4;
24589783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24599783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24609783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0100) {
24619783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0100: 6 bytes, 00 00 00 00 00 00 (before focus) and 00 00 00 00 01 00 (on focus) observed */
24623d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSINFO;
24633d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].u.info = malloc(strlen("0123456789ab")+1);
24643d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x",
24659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24679783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
24689783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
24699783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
24709783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5]
24719783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
24729783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 6;
24739783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24749783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24759783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0200) {
24769783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0200: 7 bytes, 00 00 00 00 00 00 00 observed */
24773d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_FOCUSMASK;
24783d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				ce[i].u.info = malloc(strlen("0123456789abcd0123456789abcdef")+1);
24793d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner				sprintf(ce[i].u.info,"%02x%02x%02x%02x%02x%02x%02x",
24809783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24819783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24829783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
24839783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
24849783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
24859783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
24869783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6]
24879783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
24889783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 7;
24899783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
24909783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
24919783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0400) {
24929783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x0400: 7 bytes, 00 00 00 00 00 00 00 observed */
24939783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
24949783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0400 content 0123456789abcd")+1);
24959783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0400 content %02x%02x%02x%02x%02x%02x%02x",
24969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
24979783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
24989783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
24999783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
25009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
25019783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
25029783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6]
25039783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
25049783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 7;
25059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
25069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
25079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x0800) {
25089783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus 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 */
25099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/*   might be mask of focus points selected */
25109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
25119783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x0800 content 0123456789abcdef")+1);
25129783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x0800 content %02x%02x%02x%02x%02x%02x%02x%02x",
25139783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff],
25149783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+1],
25159783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+2],
25169783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+3],
25179783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+4],
25189783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+5],
25199783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+6],
25209783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff+7]
25219783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
25229783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 8;
25239783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
25249783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
25259783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			if (mask & 0x1000) {
25269783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				/* mask 0x1000: 1 byte, 00 observed */
25279783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
25289783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("OLCInfo event 0x1000 content 01")+1);
25299783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf(ce[i].u.info,"OLCInfo event 0x1000 content %02x",
25309783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij					curdata[curoff]
25319783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				);
25329783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				curoff += 1;
25339783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				i++;
25349783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			}
25359783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			/* handle more masks */
25369783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
25379783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.info = malloc(strlen("OLCInfo event mask 0123456789")+1);
25389783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			sprintf(ce[i].u.info, "OLCInfo event mask=%x",  mask);
25399783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			break;
25409783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		}
2541d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij		case PTP_EC_CANON_EOS_CameraStatusChanged:
25429783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_CAMERASTATUS;
25439783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].u.status =  dtoh32a(curdata+8);
25449783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ptp_debug (params, "event %d: EOS event CameraStatusChanged (size %d) = %d", i, size, dtoh32a(curdata+8));
25459e09ad0e32cbdac88637d4ee2cc02ca3b771ca40Linus Walleij			params->eos_camerastatus = dtoh32a(curdata+8);
2546d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij			break;
25477e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		case 0: /* end marker */
25487e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size == 8) /* no output */
25497e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij				break;
25507e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			ptp_debug (params, "event %d: EOS event 0, but size %d", i, size);
25517e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			break;
255296aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij		case PTP_EC_CANON_EOS_BulbExposureTime:
25539783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2554aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ce[i].u.info = malloc(strlen("BulbExposureTime 123456789012345678"));
25559783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			sprintf (ce[i].u.info, "BulbExposureTime %d",  dtoh32a(curdata+8));
255696aa0e34e92d98a5cf7900afbe20395f74ed3a20Linus Walleij			break;
25573d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner		case PTP_EC_CANON_EOS_ObjectRemoved:
25583d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_OBJECTREMOVED;
25593d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			ce[i].u.object.oid = dtoh32a(curdata+8);
25603d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner			break;
2561f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		default:
2562d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			switch (type) {
2563d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij#define XX(x)		case PTP_EC_CANON_EOS_##x: 								\
2564d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				ptp_debug (params, "event %d: unhandled EOS event "#x" (size %d)", i, size); 	\
25659783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				ce[i].u.info = malloc(strlen("unhandled EOS event "#x" (size 123456789)"));	\
25669783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij				sprintf (ce[i].u.info, "unhandled EOS event "#x" (size %d)",  size);		\
2567d7072c3fa6182eed4767c97d371b15860bc386afLinus Walleij				break;
2568d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetEvent)
2569d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestGetObjectInfoEx)
2570d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageStatusChanged)
2571d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StorageInfoChanged)
2572d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectInfoChangedEx)
2573d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ObjectContentChanged)
2574d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(WillSoonShutdown)
2575d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(ShutdownTimerUpdated)
2576d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransfer)
2577d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferDT)
2578d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestCancelTransferDT)
2579d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreAdded)
2580d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(StoreRemoved)
2581d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(BulbExposureTime)
2582d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RecordingTime)
2583d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(RequestObjectTransferTS)
2584d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			XX(AfResult)
2585d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij#undef XX
2586d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			default:
2587d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				ptp_debug (params, "event %d: unknown EOS event %04x", i, type);
2588d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				break;
2589d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij			}
25907e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			if (size >= 0x8) {	/* event info */
25912ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij				unsigned int j;
2592aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner				/*ptp_debug (params, "data=%p, curdata=%p, datsize=%d, size=%d", data, curdata, datasize, size);*/
2593d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij				for (j=8;j<size;j++)
2594d4637506d9551957a152cab2cfb80fdfed029424Linus Walleij					ptp_debug (params, "    %d: %02x", j, curdata[j]);
25957e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij			}
25969783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij			ce[i].type = PTP_CANON_EOS_CHANGES_TYPE_UNKNOWN;
2597f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij			break;
2598f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		}
2599f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij		curdata += size;
26009783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		i++;
2601aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		if (i >= entries) {
2602aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner			ptp_debug (params, "BAD: i %d, entries %d", i, entries);
2603aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		}
2604f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij	}
26059783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	if (!i) {
26069783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		free (ce);
26079783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij		ce = NULL;
26080d762ccc39331608119dd0267021b165e22de499Linus Walleij	}
26099783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	*pce = ce;
26109783ce3e1a9c2a1780be0c8a0648ba6b6ae1342aLinus Walleij	return i;
2611f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij}
2612f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij
2613f0bf437f4de75d31a9493c06d03e4db8ded84be4Linus Walleij/*
2614b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij    PTP USB Event container unpack for Nikon events.
2615b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij*/
2616b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Length		0
2617b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Code		2
2618b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Param1		4
2619b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij#define PTP_nikon_ec_Size		6
2620b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline void
26212ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleijptp_unpack_Nikon_EC (PTPParams *params, unsigned char* data, unsigned int len, PTPContainer **ec, unsigned int *cnt)
2622b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij{
26232ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij	unsigned int i;
2624b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2625b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*ec = NULL;
2626b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (data == NULL)
2627b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
2628b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (len < PTP_nikon_ec_Code)
2629b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
2630b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*cnt = dtoh16a(&data[PTP_nikon_ec_Length]);
2631aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	if (*cnt > (len-PTP_nikon_ec_Code)/PTP_nikon_ec_Size) { /* broken cnt? */
2632aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner		*cnt = 0;
2633b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		return;
2634aa7d91a789873a9d86969028e57f888a1241c085Marcus Meissner	}
26350d762ccc39331608119dd0267021b165e22de499Linus Walleij	if (!*cnt)
26360d762ccc39331608119dd0267021b165e22de499Linus Walleij		return;
26370d762ccc39331608119dd0267021b165e22de499Linus Walleij
26387e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij	*ec = malloc(sizeof(PTPContainer)*(*cnt));
2639b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2640b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<*cnt;i++) {
26417e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		memset(&(*ec)[i],0,sizeof(PTPContainer));
26427e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Code	= dtoh16a(&data[PTP_nikon_ec_Code+PTP_nikon_ec_Size*i]);
26437e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Param1	= dtoh32a(&data[PTP_nikon_ec_Param1+PTP_nikon_ec_Size*i]);
26447e75653e64021908ca66b155eeb950d8304c87d8Linus Walleij		(*ec)[i].Nparam	= 1;
2645b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
2646eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij}
2647eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2648eb8c6fe031f5ba155cabcbfabcc235acffbc2fbLinus Walleij
2649b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijstatic inline uint32_t
2650b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleijptp_pack_EK_text(PTPParams *params, PTPEKTextParams *text, unsigned char **data) {
2651b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	int i, len = 0;
2652b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	uint8_t	retlen;
2653b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	unsigned char *curdata;
2654b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2655b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	len =	2*(strlen(text->title)+1)+1+
2656b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[0])+1)+1+
2657b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[1])+1)+1+
2658b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[2])+1)+1+
2659b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[3])+1)+1+
2660b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		2*(strlen(text->line[4])+1)+1+
2661b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		4*2+2*4+2+4+2+5*4*2;
2662b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	*data = malloc(len);
2663b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	if (!*data) return 0;
2664b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2665b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	curdata = *data;
2666b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,100);curdata+=2;
2667b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1);curdata+=2;
2668b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0);curdata+=2;
2669b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,1000);curdata+=2;
2670b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2671b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
2672b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
2673b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2674b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,6);curdata+=2;
2675b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod32a(curdata,0);curdata+=4;
2676b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2677b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	ptp_pack_string(params, text->title, curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
2678b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	htod16a(curdata,0x10);curdata+=2;
2679b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij
2680b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	for (i=0;i<5;i++) {
2681b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		ptp_pack_string(params, text->line[i], curdata, 0, &retlen); curdata+=2*retlen+1;htod16a(curdata,0);curdata+=2;
2682b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x10);curdata+=2;
2683b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x01);curdata+=2;
2684b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x02);curdata+=2;
2685b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij		htod16a(curdata,0x06);curdata+=2;
2686b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	}
2687b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij	return len;
2688b02a066363ab3c9b4f8f48b227c9b7b71cf7705eLinus Walleij}
26897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
26907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_version	0x00
26917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_ofc	0x02
26927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk1	0x04
26937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_objectid	0x08
26947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_parentid	0x0c
26957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_previd	0x10	/* in same dir */
26967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextid	0x14	/* in same dir */
26977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_nextchild	0x18	/* down one dir */
26987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_storageid	0x1c	/* only in storage entry */
26997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_name	0x20
27007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_flags	0x2c
27017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_size	0x30
27027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unixtime	0x34
27037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_year	0x38
27047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_month	0x39
27057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_mday	0x3a
27067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_hour	0x3b
27077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_minute	0x3c
27087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_second	0x3d
27097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_unk2	0x3e
27107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_thumbsize	0x40
27117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_width	0x44
27127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ptp_canon_dir_height	0x48
27137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijstatic inline uint16_t
27157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleijptp_unpack_canon_directory (
27167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPParams		*params,
27177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned char		*dir,
27187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		cnt,
27197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectHandles	*handles,
27207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	PTPObjectInfo		**oinfos,	/* size(handles->n) */
27217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	uint32_t		**flags		/* size(handles->n) */
27227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij) {
27237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	unsigned int	i, j, nrofobs = 0, curob = 0;
27247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27257347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#define ISOBJECT(ptr) (dtoh32a((ptr)+ptp_canon_dir_storageid) == 0xffffffff)
27267347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++)
27277347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(dir+i*0x4c)) nrofobs++;
27287347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	handles->n = nrofobs;
27293d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	handles->Handler = calloc(nrofobs,sizeof(handles->Handler[0]));
27307347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!handles->Handler) return PTP_RC_GeneralError;
27313d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	*oinfos = calloc(nrofobs,sizeof((*oinfos)[0]));
27327347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*oinfos) return PTP_RC_GeneralError;
27333d692dcb45c73f58e0c0bd86f5a19b001fd8ebf1Marcus Meissner	*flags  = calloc(nrofobs,sizeof((*flags)[0]));
27347347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	if (!*flags) return PTP_RC_GeneralError;
27357347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27367347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Migrate data into objects ids, handles into
27377347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the object handler array.
27387347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 */
27397347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	curob = 0;
27407347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
27417347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
27427347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		PTPObjectInfo	*oi = (*oinfos)+curob;
27437347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27447347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!ISOBJECT(cur))
27457347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
27467347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27477347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		handles->Handler[curob] = dtoh32a(cur + ptp_canon_dir_objectid);
27487347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->StorageID		= 0xffffffff;
27497347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectFormat	= dtoh16a(cur + ptp_canon_dir_ofc);
27507347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ParentObject	= dtoh32a(cur + ptp_canon_dir_parentid);
27517347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->Filename		= strdup((char*)(cur + ptp_canon_dir_name));
27527347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ObjectCompressedSize= dtoh32a(cur + ptp_canon_dir_size);
27537347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ThumbCompressedSize	= dtoh32a(cur + ptp_canon_dir_thumbsize);
27547347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixWidth	= dtoh32a(cur + ptp_canon_dir_width);
27557347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->ImagePixHeight	= dtoh32a(cur + ptp_canon_dir_height);
27567347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		oi->CaptureDate		= oi->ModificationDate = dtoh32a(cur + ptp_canon_dir_unixtime);
27577347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*flags)[curob]		= dtoh32a(cur + ptp_canon_dir_flags);
27587347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		curob++;
27597347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
27607347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over Storage ID entries and distribute the IDs to
27617347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 * the parent objects. */
27627347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	for (i=0;i<cnt;i++) {
27637347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		unsigned char	*cur = dir+i*0x4c;
27647347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
27657347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27667347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (ISOBJECT(cur))
27677347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			continue;
27687347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
27697347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (j == handles->n) continue;
27707347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		(*oinfos)[j].StorageID = dtoh32a(cur + ptp_canon_dir_storageid);
27717347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
27727347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	/* Walk over all objects and distribute the storage ids */
27737347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	while (1) {
27742ad5b720731014737c5ab8781362e7b3faa713ecLinus Walleij		unsigned int changed = 0;
27757347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		for (i=0;i<cnt;i++) {
27767347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			unsigned char	*cur = dir+i*0x4c;
27777347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	oid = dtoh32a(cur + ptp_canon_dir_objectid);
27787347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextoid = dtoh32a(cur + ptp_canon_dir_nextid);
27797347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	nextchild = dtoh32a(cur + ptp_canon_dir_nextchild);
27807347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			uint32_t	storageid;
27817347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij
27827347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (!ISOBJECT(cur))
27837347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
27847347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			for (j=0;j<handles->n;j++) if (oid == handles->Handler[j]) break;
27857347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (j == handles->n) {
27867347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				/*fprintf(stderr,"did not find oid in lookup pass for current oid\n");*/
27877347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				continue;
27887347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
27897347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	 		storageid = (*oinfos)[j].StorageID;
27907347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (storageid == 0xffffffff) continue;
27917347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextoid != 0xffffffff) {
27927347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextoid == handles->Handler[j]) break;
27937347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
27947347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next oid\n");*/
27957347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
27967347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
27977347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
27987347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
27997347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
28007347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
28017347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
28027347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			if (nextchild != 0xffffffff) {
28037347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				for (j=0;j<handles->n;j++) if (nextchild == handles->Handler[j]) break;
28047347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if (j == handles->n) {
28057347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					/*fprintf(stderr,"did not find oid in lookup pass for next child\n");*/
28067347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					continue;
28077347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
28087347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				if ((*oinfos)[j].StorageID == 0xffffffff) {
28097347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					(*oinfos)[j].StorageID = storageid;
28107347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij					changed++;
28117347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij				}
28127347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			}
28137347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		}
28147347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		/* Check if we:
28157347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed no entry (nothing more to do)
28167347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * - changed all of them at once (usually happens)
28177347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 * break if we do.
28187347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		 */
28197347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij		if (!changed || (changed==nrofobs-1))
28207347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij			break;
28217347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	}
28227347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij#undef ISOBJECT
28237347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij	return PTP_RC_OK;
28247347d0f315ffcce2c934555e35014af8bbc2cb1cLinus Walleij}
2825