1#![allow(non_snake_case)]
2#[macro_use]
3extern crate log;
4
5use byteorder::LittleEndian;
6use std::io::Cursor;
7
8mod camera;
9mod data_type;
10mod error;
11mod read;
12
13pub use self::camera::Camera;
14pub use self::data_type::{DataType, FormData};
15pub use self::error::Error;
16pub use self::read::Read;
17
18pub type ResponseCode = u16;
19
20#[allow(non_upper_case_globals)]
21pub mod StandardResponseCode {
22 use super::ResponseCode;
23
24 pub const Undefined: ResponseCode = 0x2000;
25 pub const Ok: ResponseCode = 0x2001;
26 pub const GeneralError: ResponseCode = 0x2002;
27 pub const SessionNotOpen: ResponseCode = 0x2003;
28 pub const InvalidTransactionId: ResponseCode = 0x2004;
29 pub const OperationNotSupported: ResponseCode = 0x2005;
30 pub const ParameterNotSupported: ResponseCode = 0x2006;
31 pub const IncompleteTransfer: ResponseCode = 0x2007;
32 pub const InvalidStorageId: ResponseCode = 0x2008;
33 pub const InvalidObjectHandle: ResponseCode = 0x2009;
34 pub const DevicePropNotSupported: ResponseCode = 0x200A;
35 pub const InvalidObjectFormatCode: ResponseCode = 0x200B;
36 pub const StoreFull: ResponseCode = 0x200C;
37 pub const ObjectWriteProtected: ResponseCode = 0x200D;
38 pub const StoreReadOnly: ResponseCode = 0x200E;
39 pub const AccessDenied: ResponseCode = 0x200F;
40 pub const NoThumbnailPresent: ResponseCode = 0x2010;
41 pub const SelfTestFailed: ResponseCode = 0x2011;
42 pub const PartialDeletion: ResponseCode = 0x2012;
43 pub const StoreNotAvailable: ResponseCode = 0x2013;
44 pub const SpecificationByFormatUnsupported: ResponseCode = 0x2014;
45 pub const NoValidObjectInfo: ResponseCode = 0x2015;
46 pub const InvalidCodeFormat: ResponseCode = 0x2016;
47 pub const UnknownVendorCode: ResponseCode = 0x2017;
48 pub const CaptureAlreadyTerminated: ResponseCode = 0x2018;
49 pub const DeviceBusy: ResponseCode = 0x2019;
50 pub const InvalidParentObject: ResponseCode = 0x201A;
51 pub const InvalidDevicePropFormat: ResponseCode = 0x201B;
52 pub const InvalidDevicePropValue: ResponseCode = 0x201C;
53 pub const InvalidParameter: ResponseCode = 0x201D;
54 pub const SessionAlreadyOpen: ResponseCode = 0x201E;
55 pub const TransactionCancelled: ResponseCode = 0x201F;
56 pub const SpecificationOfDestinationUnsupported: ResponseCode = 0x2020;
57
58 pub fn name(v: ResponseCode) -> Option<&'static str> {
59 match v {
60 Undefined => Some("Undefined"),
61 Ok => Some("Ok"),
62 GeneralError => Some("GeneralError"),
63 SessionNotOpen => Some("SessionNotOpen"),
64 InvalidTransactionId => Some("InvalidTransactionId"),
65 OperationNotSupported => Some("OperationNotSupported"),
66 ParameterNotSupported => Some("ParameterNotSupported"),
67 IncompleteTransfer => Some("IncompleteTransfer"),
68 InvalidStorageId => Some("InvalidStorageId"),
69 InvalidObjectHandle => Some("InvalidObjectHandle"),
70 DevicePropNotSupported => Some("DevicePropNotSupported"),
71 InvalidObjectFormatCode => Some("InvalidObjectFormatCode"),
72 StoreFull => Some("StoreFull"),
73 ObjectWriteProtected => Some("ObjectWriteProtected"),
74 StoreReadOnly => Some("StoreReadOnly"),
75 AccessDenied => Some("AccessDenied"),
76 NoThumbnailPresent => Some("NoThumbnailPresent"),
77 SelfTestFailed => Some("SelfTestFailed"),
78 PartialDeletion => Some("PartialDeletion"),
79 StoreNotAvailable => Some("StoreNotAvailable"),
80 SpecificationByFormatUnsupported => Some("SpecificationByFormatUnsupported"),
81 NoValidObjectInfo => Some("NoValidObjectInfo"),
82 InvalidCodeFormat => Some("InvalidCodeFormat"),
83 UnknownVendorCode => Some("UnknownVendorCode"),
84 CaptureAlreadyTerminated => Some("CaptureAlreadyTerminated"),
85 DeviceBusy => Some("DeviceBusy"),
86 InvalidParentObject => Some("InvalidParentObject"),
87 InvalidDevicePropFormat => Some("InvalidDevicePropFormat"),
88 InvalidDevicePropValue => Some("InvalidDevicePropValue"),
89 InvalidParameter => Some("InvalidParameter"),
90 SessionAlreadyOpen => Some("SessionAlreadyOpen"),
91 TransactionCancelled => Some("TransactionCancelled"),
92 SpecificationOfDestinationUnsupported => Some("SpecificationOfDestinationUnsupported"),
93 _ => None,
94 }
95 }
96}
97
98pub type CommandCode = u16;
99
100#[allow(non_upper_case_globals)]
101pub mod StandardCommandCode {
102 use super::CommandCode;
103
104 pub const Undefined: CommandCode = 0x1000;
105 pub const GetDeviceInfo: CommandCode = 0x1001;
106 pub const OpenSession: CommandCode = 0x1002;
107 pub const CloseSession: CommandCode = 0x1003;
108 pub const GetStorageIDs: CommandCode = 0x1004;
109 pub const GetStorageInfo: CommandCode = 0x1005;
110 pub const GetNumObjects: CommandCode = 0x1006;
111 pub const GetObjectHandles: CommandCode = 0x1007;
112 pub const GetObjectInfo: CommandCode = 0x1008;
113 pub const GetObject: CommandCode = 0x1009;
114 pub const GetThumb: CommandCode = 0x100A;
115 pub const DeleteObject: CommandCode = 0x100B;
116 pub const SendObjectInfo: CommandCode = 0x100C;
117 pub const SendObject: CommandCode = 0x100D;
118 pub const InitiateCapture: CommandCode = 0x100E;
119 pub const FormatStore: CommandCode = 0x100F;
120 pub const ResetDevice: CommandCode = 0x1010;
121 pub const SelfTest: CommandCode = 0x1011;
122 pub const SetObjectProtection: CommandCode = 0x1012;
123 pub const PowerDown: CommandCode = 0x1013;
124 pub const GetDevicePropDesc: CommandCode = 0x1014;
125 pub const GetDevicePropValue: CommandCode = 0x1015;
126 pub const SetDevicePropValue: CommandCode = 0x1016;
127 pub const ResetDevicePropValue: CommandCode = 0x1017;
128 pub const TerminateOpenCapture: CommandCode = 0x1018;
129 pub const MoveObject: CommandCode = 0x1019;
130 pub const CopyObject: CommandCode = 0x101A;
131 pub const GetPartialObject: CommandCode = 0x101B;
132 pub const InitiateOpenCapture: CommandCode = 0x101C;
133
134 pub fn name(v: CommandCode) -> Option<&'static str> {
135 match v {
136 Undefined => Some("Undefined"),
137 GetDeviceInfo => Some("GetDeviceInfo"),
138 OpenSession => Some("OpenSession"),
139 CloseSession => Some("CloseSession"),
140 GetStorageIDs => Some("GetStorageIDs"),
141 GetStorageInfo => Some("GetStorageInfo"),
142 GetNumObjects => Some("GetNumObjects"),
143 GetObjectHandles => Some("GetObjectHandles"),
144 GetObjectInfo => Some("GetObjectInfo"),
145 GetObject => Some("GetObject"),
146 GetThumb => Some("GetThumb"),
147 DeleteObject => Some("DeleteObject"),
148 SendObjectInfo => Some("SendObjectInfo"),
149 SendObject => Some("SendObject"),
150 InitiateCapture => Some("InitiateCapture"),
151 FormatStore => Some("FormatStore"),
152 ResetDevice => Some("ResetDevice"),
153 SelfTest => Some("SelfTest"),
154 SetObjectProtection => Some("SetObjectProtection"),
155 PowerDown => Some("PowerDown"),
156 GetDevicePropDesc => Some("GetDevicePropDesc"),
157 GetDevicePropValue => Some("GetDevicePropValue"),
158 SetDevicePropValue => Some("SetDevicePropValue"),
159 ResetDevicePropValue => Some("ResetDevicePropValue"),
160 TerminateOpenCapture => Some("TerminateOpenCapture"),
161 MoveObject => Some("MoveObject"),
162 CopyObject => Some("CopyObject"),
163 GetPartialObject => Some("GetPartialObject"),
164 InitiateOpenCapture => Some("InitiateOpenCapture"),
165 _ => None,
166 }
167 }
168}
169
170#[allow(non_snake_case)]
171#[derive(Debug)]
172pub struct DeviceInfo {
173 pub Version: u16,
174 pub VendorExID: u32,
175 pub VendorExVersion: u16,
176 pub VendorExtensionDesc: String,
177 pub FunctionalMode: u16,
178 pub OperationsSupported: Vec<u16>,
179 pub EventsSupported: Vec<u16>,
180 pub DevicePropertiesSupported: Vec<u16>,
181 pub CaptureFormats: Vec<u16>,
182 pub ImageFormats: Vec<u16>,
183 pub Manufacturer: String,
184 pub Model: String,
185 pub DeviceVersion: String,
186 pub SerialNumber: String,
187}
188
189impl DeviceInfo {
190 pub fn decode(buf: &[u8]) -> Result<DeviceInfo, Error> {
191 let mut cur = Cursor::new(buf);
192
193 Ok(DeviceInfo {
194 Version: cur.read_ptp_u16()?,
195 VendorExID: cur.read_ptp_u32()?,
196 VendorExVersion: cur.read_ptp_u16()?,
197 VendorExtensionDesc: cur.read_ptp_str()?,
198 FunctionalMode: cur.read_ptp_u16()?,
199 OperationsSupported: cur.read_ptp_u16_vec()?,
200 EventsSupported: cur.read_ptp_u16_vec()?,
201 DevicePropertiesSupported: cur.read_ptp_u16_vec()?,
202 CaptureFormats: cur.read_ptp_u16_vec()?,
203 ImageFormats: cur.read_ptp_u16_vec()?,
204 Manufacturer: cur.read_ptp_str()?,
205 Model: cur.read_ptp_str()?,
206 DeviceVersion: cur.read_ptp_str()?,
207 SerialNumber: cur.read_ptp_str()?,
208 })
209 }
210}
211
212#[allow(dead_code)]
213#[derive(Debug, Clone)]
214pub struct ObjectInfo {
215 pub StorageID: u32,
216 pub ObjectFormat: u16,
217 pub ProtectionStatus: u16,
218 pub ObjectCompressedSize: u32,
219 pub ThumbFormat: u16,
220 pub ThumbCompressedSize: u32,
221 pub ThumbPixWidth: u32,
222 pub ThumbPixHeight: u32,
223 pub ImagePixWidth: u32,
224 pub ImagePixHeight: u32,
225 pub ImageBitDepth: u32,
226 pub ParentObject: u32,
227 pub AssociationType: u16,
228 pub AssociationDesc: u32,
229 pub SequenceNumber: u32,
230 pub Filename: String,
231 pub CaptureDate: String,
232 pub ModificationDate: String,
233 pub Keywords: String,
234}
235
236impl ObjectInfo {
237 pub fn decode(buf: &[u8]) -> Result<ObjectInfo, Error> {
238 let mut cur = Cursor::new(buf);
239
240 Ok(ObjectInfo {
241 StorageID: cur.read_ptp_u32()?,
242 ObjectFormat: cur.read_ptp_u16()?,
243 ProtectionStatus: cur.read_ptp_u16()?,
244 ObjectCompressedSize: cur.read_ptp_u32()?,
245 ThumbFormat: cur.read_ptp_u16()?,
246 ThumbCompressedSize: cur.read_ptp_u32()?,
247 ThumbPixWidth: cur.read_ptp_u32()?,
248 ThumbPixHeight: cur.read_ptp_u32()?,
249 ImagePixWidth: cur.read_ptp_u32()?,
250 ImagePixHeight: cur.read_ptp_u32()?,
251 ImageBitDepth: cur.read_ptp_u32()?,
252 ParentObject: cur.read_ptp_u32()?,
253 AssociationType: cur.read_ptp_u16()?,
254 AssociationDesc: cur.read_ptp_u32()?,
255 SequenceNumber: cur.read_ptp_u32()?,
256 Filename: cur.read_ptp_str()?,
257 CaptureDate: cur.read_ptp_str()?,
258 ModificationDate: cur.read_ptp_str()?,
259 Keywords: cur.read_ptp_str()?,
260 })
261 }
262}
263
264#[allow(non_snake_case)]
265#[derive(Debug)]
266pub struct StorageInfo {
267 pub StorageType: u16,
268 pub FilesystemType: u16,
269 pub AccessCapability: u16,
270 pub MaxCapacity: u64,
271 pub FreeSpaceInBytes: u64,
272 pub FreeSpaceInImages: u32,
273 pub StorageDescription: String,
274 pub VolumeLabel: String,
275}
276
277impl StorageInfo {
278 pub fn decode<T: Read>(cur: &mut T) -> Result<StorageInfo, Error> {
279 Ok(StorageInfo {
280 StorageType: cur.read_ptp_u16()?,
281 FilesystemType: cur.read_ptp_u16()?,
282 AccessCapability: cur.read_ptp_u16()?,
283 MaxCapacity: cur.read_ptp_u64()?,
284 FreeSpaceInBytes: cur.read_ptp_u64()?,
285 FreeSpaceInImages: cur.read_ptp_u32()?,
286 StorageDescription: cur.read_ptp_str()?,
287 VolumeLabel: cur.read_ptp_str()?,
288 })
289 }
290}
291
292#[derive(Debug)]
293pub struct PropInfo {
294 pub property_code: u16,
296 pub data_type: u16,
298 pub get_set: u8,
300 pub factory_default: DataType,
301 pub current: DataType,
302 pub form: FormData,
303}
304
305impl PropInfo {
306 pub fn decode<T: Read>(cur: &mut T) -> Result<PropInfo, Error> {
307 let property_code = cur.read_ptp_u16()?;
308 let data_type = cur.read_ptp_u16()?;
309 Ok(PropInfo {
310 property_code,
311 data_type,
312 get_set: cur.read_u8()?,
313 factory_default: DataType::read_type(data_type, cur)?,
314 current: DataType::read_type(data_type, cur)?,
315 form: {
316 match cur.read_u8()? {
317 0x01 => FormData::Range {
319 min_value: DataType::read_type(data_type, cur)?,
320 max_value: DataType::read_type(data_type, cur)?,
321 step: DataType::read_type(data_type, cur)?,
322 },
323 0x02 => FormData::Enumeration {
324 array: {
325 let len = cur.read_u16::<LittleEndian>()? as usize;
326 let mut arr = Vec::with_capacity(len);
327 for _ in 0..len {
328 arr.push(DataType::read_type(data_type, cur)?);
329 }
330 arr
331 },
332 },
333 _ => FormData::None,
334 }
335 },
336 })
337 }
338}
339
340#[derive(Debug)]
341pub struct PropInfoSony {
342 pub property_code: u16,
344 pub data_type: u16,
346 pub get_set: u8,
348 pub is_enable: u8,
350 pub factory_default: DataType,
351 pub current: DataType,
352 pub form: FormData,
353}
354
355impl PropInfoSony {
356 pub fn decode<T: Read>(cur: &mut T) -> Result<PropInfoSony, Error> {
357 let property_code = cur.read_ptp_u16()?;
358 let data_type = cur.read_ptp_u16()?;
359 Ok(PropInfoSony {
360 property_code,
361 data_type,
362 get_set: cur.read_u8()?,
363 is_enable: cur.read_u8()?,
364 factory_default: DataType::read_type(data_type, cur)?,
365 current: DataType::read_type(data_type, cur)?,
366 form: {
367 match cur.read_u8()? {
368 0x01 => FormData::Range {
370 min_value: DataType::read_type(data_type, cur)?,
371 max_value: DataType::read_type(data_type, cur)?,
372 step: DataType::read_type(data_type, cur)?,
373 },
374 0x02 => FormData::Enumeration {
375 array: {
376 let len = cur.read_u16::<LittleEndian>()? as usize;
377 let mut arr = Vec::with_capacity(len);
378 for _ in 0..len {
379 arr.push(DataType::read_type(data_type, cur)?);
380 }
381 arr
382 },
383 },
384 _ => FormData::None,
385 }
386 },
387 })
388 }
389}
390
391#[derive(Debug, Clone)]
392pub struct ObjectTree {
393 pub handle: u32,
394 pub info: ObjectInfo,
395 pub children: Option<Vec<ObjectTree>>,
396}
397
398impl ObjectTree {
399 pub fn walk(&self) -> Vec<(String, ObjectTree)> {
400 let mut input = vec![("".to_owned(), self.clone())];
401 let mut output = vec![];
402
403 while !input.is_empty() {
404 for (prefix, item) in input.split_off(0) {
405 let path = prefix.clone()
406 + (if prefix.is_empty() { "" } else { "/" })
407 + &item.info.Filename;
408
409 output.push((path.clone(), item.clone()));
410
411 if let Some(children) = item.children {
412 input.extend(children.into_iter().map(|x| (path.clone(), x)));
413 }
414 }
415 }
416
417 output
418 }
419}