2 * Routines for PTP/IP (Picture Transfer Protocol) packet dissection
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 * [1] CIPA DC-X005-2005 - PTP-IP
15 * [2] BS ISO 15740:2008 - Photography Electronic still picture imaging - Picture transfer protocol (PTP)
16 * for digital still photography devices
17 * [3] gPhoto's Reversed Engineered PTP/IP documentation - http://gphoto.sourceforge.net/doc/ptpip.php
18 * [4] gPhoto's ptp2 header file https://gphoto.svn.sourceforge.net/svnroot/gphoto/trunk/libgphoto2/camlibs/ptp2/ptp.h
20 * @todo: This is being written as 1 dissector when in reality there is PTP/IP and PTP.
21 * Future work should include splitting this into 2 so that the PTP layer may be used again for PTP/USB.
24 #include <epan/packet.h>
25 #include <epan/prefs.h>
26 #include "packet-ptpip.h"
29 #define PTPIP_PORT 15740 /* [1] Section 2.2.3.1 */
30 #define PTPIP_GUID_SIZE 16 /* [1] Section 2.3.1 */
31 #define PTPIP_MAX_PARAM_COUNT 5 /* [1] Section 2.3.6 */
35 static int ett_ptpIP_hdr
;
38 static int proto_ptpIP
;
39 static int hf_ptpIP_len
; /* [1] Section 2.3 */
40 static int hf_ptpIP_pktType
; /* [1] Section 2.3 */
41 static int hf_ptpIP_guid
;
42 static int hf_ptpIP_name
;
43 static int hf_ptpIP_version
;
44 static int hf_ptpIP_connectionNumber
;
45 static int hf_ptpIP_dataPhaseInfo
;
47 /* note: separating the fields to make it easier to divide this code later. */
50 /* picking hf_ptp for now. Might need to change later for namespace issues with Precision Time Protocol. */
51 static int hf_ptp_opCode
;
52 static int hf_ptp_vendor_opCode
;
53 static int hf_ptp_respCode
;
54 static int hf_ptp_eventCode
;
55 static int hf_ptp_transactionID
;
56 static int hf_ptp_totalDataLength
;
57 static int hf_ptp_opCode_param_sessionID
;
59 /* function declarations */
60 static int dissect_ptpIP (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
);
61 static void dissect_ptpIP_init_command_request (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
62 static void dissect_ptpIP_init_command_ack (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
63 static void dissect_ptpIP_init_event_request (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
64 static void dissect_ptpIP_init_event_ack ( packet_info
*pinfo
);
65 static void dissect_ptpIP_operation_request (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
66 static void dissect_ptpIP_operation_response (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
67 static void dissect_ptpIP_start_data (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
68 static void dissect_ptpIP_data (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
69 static void dissect_ptpIP_end_data (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
70 static void dissect_ptpIP_event (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
71 static void dissect_ptpIP_unicode_name (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
72 static void dissect_ptpIP_protocol_version (tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t *offset
);
73 static void dissect_ptpIP_guid (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
);
75 void proto_register_ptpip( void );
76 void proto_reg_handoff_ptpIP( void );
78 static dissector_handle_t ptpIP_handle
;
81 PTP_VENDOR_UNKNOWN
= 0,
82 PTP_VENDOR_EASTMAN_KODAK
= 1,
87 PTP_VENDOR_OLYMPUS
= 6
90 static const enum_val_t pref_hsp_role
[] = {
91 { "Unknown", "Unknown vendor", PTP_VENDOR_UNKNOWN
},
92 { "Eastman_Kodak", "Eastman Kodak", PTP_VENDOR_EASTMAN_KODAK
},
93 { "Canon", "Canon", PTP_VENDOR_CANON
},
94 { "Nikon", "Nikon", PTP_VENDOR_NIKON
},
95 { "Casio", "Casio EX-F1", PTP_VENDOR_CASIO
},
96 { "MTP", "Microsoft / MTP", PTP_VENDOR_MTP
},
97 { "Olympus", "Olympus E series", PTP_VENDOR_OLYMPUS
},
101 /* Vendor preference for deciphering opcodes */
102 static int pref_vendor
;
105 static const value_string ptp_opcode_names
[] = {
106 { PTP_OC_GetDeviceInfo
, "GetDeviceInfo" },
107 { PTP_OC_OpenSession
, "OpenSession" },
108 { PTP_OC_CloseSession
, "CloseSession" },
109 { PTP_OC_GetStorageIDs
, "GetStorageIDs" },
110 { PTP_OC_GetStorageInfo
, "GetStorageInfo" },
111 { PTP_OC_GetNumObjects
, "GetNumObjects" },
112 { PTP_OC_GetObjectHandles
, "GetObjectHandles" },
113 { PTP_OC_GetObjectInfo
, "GetObjectInfo" },
114 { PTP_OC_GetObject
, "GetObject" },
115 { PTP_OC_DeleteObject
, "DeleteObject" },
116 { PTP_OC_SendObjectInfo
, "SendObjectInfo" },
117 { PTP_OC_SendObject
, "SendObject" },
118 { PTP_OC_InitiateCapture
, "InitiateCapture" },
119 { PTP_OC_FormatStore
, "FormatStore" },
120 { PTP_OC_ResetDevice
, "ResetDevice" },
121 { PTP_OC_SelfTest
, "SelfTest" },
122 { PTP_OC_SetObjectProtection
, "SetObjectProtection" },
123 { PTP_OC_PowerDown
, "PowerDown" },
124 { PTP_OC_GetDevicePropDesc
, "GetDevicePropDesc" },
125 { PTP_OC_GetDevicePropValue
, "GetDevicePropValue" },
126 { PTP_OC_SetDevicePropValue
, "SetDevicePropValue" },
127 { PTP_OC_ResetDevicePropValue
, "ResetDevicePropValue" },
128 { PTP_OC_TerminateOpenCapture
, "TerminateOpenCapture" },
129 { PTP_OC_MoveObject
, "MoveObject" },
130 { PTP_OC_CopyObject
, "CopyObject" },
131 { PTP_OC_GetPartialObject
, "GetPartialObject" },
132 { PTP_OC_InitiateOpenCapture
, "InitiateOpenCapture" },
133 { PTP_OC_StartEnumHandles
, "StartEnumHandles" },
134 { PTP_OC_EnumHandles
, "EnumHandles" },
135 { PTP_OC_StopEnumHandles
, "StopEnumHandles" },
136 { PTP_OC_GetVendorExtensionMaps
, "GetVendorExtensionMaps" },
137 { PTP_OC_GetVendorDeviceInfo
, "GetVendorDeviceInfo" },
138 { PTP_OC_GetResizedImageObject
, "GetResizedImageObject" },
139 { PTP_OC_GetFilesystemManifest
, "GetFilesystemManifest" },
140 { PTP_OC_GetStreamInfo
, "GetStreamInfo" },
141 { PTP_OC_GetStream
, "GetStream" },
144 static value_string_ext ptp_opcode_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_names
);
146 static const value_string ptp_opcode_ek_names
[] = {
147 { PTP_OC_EK_GetSerial
, "EK_GetSerial" },
148 { PTP_OC_EK_SetSerial
, "EK_SetSerial" },
149 { PTP_OC_EK_SendFileObjectInfo
, "EK_SendFileObjectInfo" },
150 { PTP_OC_EK_SendFileObject
, "EK_SendFileObject" },
151 { PTP_OC_EK_SetText
, "EK_SetText" },
154 static value_string_ext ptp_opcode_ek_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_ek_names
);
156 static const value_string ptp_opcode_canon_names
[] = {
157 { PTP_OC_CANON_GetPartialObjectInfo
, "CANON_GetPartialObjectInfo" },
158 { PTP_OC_CANON_SetObjectArchive
, "CANON_SetObjectArchive" },
159 { PTP_OC_CANON_KeepDeviceOn
, "CANON_KeepDeviceOn" },
160 { PTP_OC_CANON_LockDeviceUI
, "CANON_LockDeviceUI" },
161 { PTP_OC_CANON_UnlockDeviceUI
, "CANON_UnlockDeviceUI" },
162 { PTP_OC_CANON_GetObjectHandleByName
, "CANON_GetObjectHandleByName" },
163 { PTP_OC_CANON_InitiateReleaseControl
, "CANON_InitiateReleaseControl" },
164 { PTP_OC_CANON_TerminateReleaseControl
, "CANON_TerminateReleaseControl" },
165 { PTP_OC_CANON_TerminatePlaybackMode
, "CANON_TerminatePlaybackMode" },
166 { PTP_OC_CANON_ViewfinderOn
, "CANON_ViewfinderOn" },
167 { PTP_OC_CANON_ViewfinderOff
, "CANON_ViewfinderOff" },
168 { PTP_OC_CANON_DoAeAfAwb
, "CANON_DoAeAfAwb" },
169 { PTP_OC_CANON_GetCustomizeSpec
, "CANON_GetCustomizeSpec" },
170 { PTP_OC_CANON_GetCustomizeItemInfo
, "CANON_GetCustomizeItemInfo" },
171 { PTP_OC_CANON_GetCustomizeData
, "CANON_GetCustomizeData" },
172 { PTP_OC_CANON_SetCustomizeData
, "CANON_SetCustomizeData" },
173 { PTP_OC_CANON_GetCaptureStatus
, "CANON_GetCaptureStatus" },
174 { PTP_OC_CANON_CheckEvent
, "CANON_CheckEvent" },
175 { PTP_OC_CANON_FocusLock
, "CANON_FocusLock" },
176 { PTP_OC_CANON_FocusUnlock
, "CANON_FocusUnlock" },
177 { PTP_OC_CANON_GetLocalReleaseParam
, "CANON_GetLocalReleaseParam" },
178 { PTP_OC_CANON_SetLocalReleaseParam
, "CANON_SetLocalReleaseParam" },
179 { PTP_OC_CANON_AskAboutPcEvf
, "CANON_AskAboutPcEvf" },
180 { PTP_OC_CANON_SendPartialObject
, "CANON_SendPartialObject" },
181 { PTP_OC_CANON_InitiateCaptureInMemory
, "CANON_InitiateCaptureInMemory" },
182 { PTP_OC_CANON_GetPartialObjectEx
, "CANON_GetPartialObjectEx" },
183 { PTP_OC_CANON_SetObjectTime
, "CANON_SetObjectTime" },
184 { PTP_OC_CANON_GetViewfinderImage
, "CANON_GetViewfinderImage" },
185 { PTP_OC_CANON_GetObjectAttributes
, "CANON_GetObjectAttributes" },
186 { PTP_OC_CANON_ChangeUSBProtocol
, "CANON_ChangeUSBProtocol" },
187 { PTP_OC_CANON_GetChanges
, "CANON_GetChanges" },
188 { PTP_OC_CANON_GetObjectInfoEx
, "CANON_GetObjectInfoEx" },
189 { PTP_OC_CANON_InitiateDirectTransfer
, "CANON_InitiateDirectTransfer" },
190 { PTP_OC_CANON_TerminateDirectTransfer
, "CANON_TerminateDirectTransfer" },
191 { PTP_OC_CANON_SendObjectInfoByPath
, "CANON_SendObjectInfoByPath" },
192 { PTP_OC_CANON_SendObjectByPath
, "CANON_SendObjectByPath" },
193 { PTP_OC_CANON_InitiateDirectTransferEx
, "CANON_InitiateDirectTransferEx" },
194 { PTP_OC_CANON_GetAncillaryObjectHandles
, "CANON_GetAncillaryObjectHandles" },
195 { PTP_OC_CANON_GetTreeInfo
, "CANON_GetTreeInfo" },
196 { PTP_OC_CANON_GetTreeSize
, "CANON_GetTreeSize" },
197 { PTP_OC_CANON_NotifyProgress
, "CANON_NotifyProgress" },
198 { PTP_OC_CANON_NotifyCancelAccepted
, "CANON_NotifyCancelAccepted" },
199 { PTP_OC_CANON_902C
, "CANON_902C" },
200 { PTP_OC_CANON_SetPairingInfo
, "CANON_SetPairingInfo" },
201 { PTP_OC_CANON_GetPairingInfo
, "CANON_GetPairingInfo" },
202 { PTP_OC_CANON_DeletePairingInfo
, "CANON_DeletePairingInfo" },
203 { PTP_OC_CANON_GetMACAddress
, "CANON_GetMACAddress" },
204 { PTP_OC_CANON_SetDisplayMonitor
, "CANON_SetDisplayMonitor" },
205 { PTP_OC_CANON_PairingComplete
, "CANON_PairingComplete" },
206 { PTP_OC_CANON_GetWirelessMAXChannel
, "CANON_GetWirelessMAXChannel" },
207 { PTP_OC_CANON_EOS_GetStorageIDs
, "CANON_EOS_GetStorageIDs" },
208 { PTP_OC_CANON_EOS_GetStorageInfo
, "CANON_EOS_GetStorageInfo" },
209 { PTP_OC_CANON_EOS_GetObjectInfo
, "CANON_EOS_GetObjectInfo" },
210 { PTP_OC_CANON_EOS_GetObject
, "CANON_EOS_GetObject" },
211 { PTP_OC_CANON_EOS_DeleteObject
, "CANON_EOS_DeleteObject" },
212 { PTP_OC_CANON_EOS_FormatStore
, "CANON_EOS_FormatStore" },
213 { PTP_OC_CANON_EOS_GetPartialObject
, "CANON_EOS_GetPartialObject" },
214 { PTP_OC_CANON_EOS_GetDeviceInfoEx
, "CANON_EOS_GetDeviceInfoEx" },
215 { PTP_OC_CANON_EOS_GetObjectInfoEx
, "CANON_EOS_GetObjectInfoEx" },
216 { PTP_OC_CANON_EOS_GetThumbEx
, "CANON_EOS_GetThumbEx" },
217 { PTP_OC_CANON_EOS_SendPartialObject
, "CANON_EOS_SendPartialObject" },
218 { PTP_OC_CANON_EOS_SetObjectAttributes
, "CANON_EOS_SetObjectAttributes" },
219 { PTP_OC_CANON_EOS_GetObjectTime
, "CANON_EOS_GetObjectTime" },
220 { PTP_OC_CANON_EOS_SetObjectTime
, "CANON_EOS_SetObjectTime" },
221 { PTP_OC_CANON_EOS_RemoteRelease
, "CANON_EOS_RemoteRelease" },
222 { PTP_OC_CANON_EOS_SetDevicePropValueEx
, "CANON_EOS_SetDevicePropValueEx" },
223 { PTP_OC_CANON_EOS_GetRemoteMode
, "CANON_EOS_GetRemoteMode" },
224 { PTP_OC_CANON_EOS_SetRemoteMode
, "CANON_EOS_SetRemoteMode" },
225 { PTP_OC_CANON_EOS_SetEventMode
, "CANON_EOS_SetEventMode" },
226 { PTP_OC_CANON_EOS_GetEvent
, "CANON_EOS_GetEvent" },
227 { PTP_OC_CANON_EOS_TransferComplete
, "CANON_EOS_TransferComplete" },
228 { PTP_OC_CANON_EOS_CancelTransfer
, "CANON_EOS_CancelTransfer" },
229 { PTP_OC_CANON_EOS_ResetTransfer
, "CANON_EOS_ResetTransfer" },
230 { PTP_OC_CANON_EOS_PCHDDCapacity
, "CANON_EOS_PCHDDCapacity" },
231 { PTP_OC_CANON_EOS_SetUILock
, "CANON_EOS_SetUILock" },
232 { PTP_OC_CANON_EOS_ResetUILock
, "CANON_EOS_ResetUILock" },
233 { PTP_OC_CANON_EOS_KeepDeviceOn
, "CANON_EOS_KeepDeviceOn" },
234 { PTP_OC_CANON_EOS_SetNullPacketMode
, "CANON_EOS_SetNullPacketMode" },
235 { PTP_OC_CANON_EOS_UpdateFirmware
, "CANON_EOS_UpdateFirmware" },
236 { PTP_OC_CANON_EOS_TransferCompleteDT
, "CANON_EOS_TransferCompleteDT" },
237 { PTP_OC_CANON_EOS_CancelTransferDT
, "CANON_EOS_CancelTransferDT" },
238 { PTP_OC_CANON_EOS_SetWftProfile
, "CANON_EOS_SetWftProfile" },
239 { PTP_OC_CANON_EOS_GetWftProfile
, "CANON_EOS_GetWftProfile" },
240 { PTP_OC_CANON_EOS_SetProfileToWft
, "CANON_EOS_SetProfileToWft" },
241 { PTP_OC_CANON_EOS_BulbStart
, "CANON_EOS_BulbStart" },
242 { PTP_OC_CANON_EOS_BulbEnd
, "CANON_EOS_BulbEnd" },
243 { PTP_OC_CANON_EOS_RequestDevicePropValue
, "CANON_EOS_RequestDevicePropValue" },
244 { PTP_OC_CANON_EOS_RemoteReleaseOn
, "CANON_EOS_RemoteReleaseOn" },
245 { PTP_OC_CANON_EOS_RemoteReleaseOff
, "CANON_EOS_RemoteReleaseOff" },
246 { PTP_OC_CANON_EOS_InitiateViewfinder
, "CANON_EOS_InitiateViewfinder" },
247 { PTP_OC_CANON_EOS_TerminateViewfinder
, "CANON_EOS_TerminateViewfinder" },
248 { PTP_OC_CANON_EOS_GetViewFinderData
, "CANON_EOS_GetViewFinderData" },
249 { PTP_OC_CANON_EOS_DoAf
, "CANON_EOS_DoAf" },
250 { PTP_OC_CANON_EOS_DriveLens
, "CANON_EOS_DriveLens" },
251 { PTP_OC_CANON_EOS_DepthOfFieldPreview
, "CANON_EOS_DepthOfFieldPreview" },
252 { PTP_OC_CANON_EOS_ClickWB
, "CANON_EOS_ClickWB" },
253 { PTP_OC_CANON_EOS_Zoom
, "CANON_EOS_Zoom" },
254 { PTP_OC_CANON_EOS_ZoomPosition
, "CANON_EOS_ZoomPosition" },
255 { PTP_OC_CANON_EOS_SetLiveAfFrame
, "CANON_EOS_SetLiveAfFrame" },
256 { PTP_OC_CANON_EOS_AfCancel
, "CANON_EOS_AfCancel" },
257 { PTP_OC_CANON_EOS_FAPIMessageTX
, "CANON_EOS_FAPIMessageTX" },
258 { PTP_OC_CANON_EOS_FAPIMessageRX
, "CANON_EOS_FAPIMessageRX" },
261 static value_string_ext ptp_opcode_canon_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_canon_names
);
263 static const value_string ptp_opcode_nikon_names
[] = {
264 { PTP_OC_NIKON_GetProfileAllData
, "NIKON_GetProfileAllData" },
265 { PTP_OC_NIKON_SendProfileData
, "NIKON_SendProfileData" },
266 { PTP_OC_NIKON_SendProfileData
, "NIKON_SendProfileData" },
267 { PTP_OC_NIKON_DeleteProfile
, "NIKON_DeleteProfile" },
268 { PTP_OC_NIKON_SetProfileData
, "NIKON_SetProfileData" },
269 { PTP_OC_NIKON_AdvancedTransfer
, "NIKON_AdvancedTransfer" },
270 { PTP_OC_NIKON_GetFileInfoInBlock
, "NIKON_GetFileInfoInBlock" },
271 { PTP_OC_NIKON_Capture
, "NIKON_Capture" },
272 { PTP_OC_NIKON_AfDrive
, "NIKON_AfDrive" },
273 { PTP_OC_NIKON_SetControlMode
, "NIKON_SetControlMode" },
274 { PTP_OC_NIKON_DelImageSDRAM
, "NIKON_DelImageSDRAM" },
275 { PTP_OC_NIKON_GetLargeThumb
, "NIKON_GetLargeThumb" },
276 { PTP_OC_NIKON_CurveDownload
, "NIKON_CurveDownload" },
277 { PTP_OC_NIKON_CurveUpload
, "NIKON_CurveUpload" },
278 { PTP_OC_NIKON_CheckEvent
, "NIKON_CheckEvent" },
279 { PTP_OC_NIKON_DeviceReady
, "NIKON_DeviceReady" },
280 { PTP_OC_NIKON_SetPreWBData
, "NIKON_SetPreWBData" },
281 { PTP_OC_NIKON_GetVendorPropCodes
, "NIKON_GetVendorPropCodes" },
282 { PTP_OC_NIKON_AfCaptureSDRAM
, "NIKON_AfCaptureSDRAM" },
283 { PTP_OC_NIKON_GetPictCtrlData
, "NIKON_GetPictCtrlData" },
284 { PTP_OC_NIKON_SetPictCtrlData
, "NIKON_SetPictCtrlData" },
285 { PTP_OC_NIKON_DelCstPicCtrl
, "NIKON_DelCstPicCtrl" },
286 { PTP_OC_NIKON_GetPicCtrlCapability
, "NIKON_GetPicCtrlCapability" },
287 { PTP_OC_NIKON_GetPreviewImg
, "NIKON_GetPreviewImg" },
288 { PTP_OC_NIKON_StartLiveView
, "NIKON_StartLiveView" },
289 { PTP_OC_NIKON_EndLiveView
, "NIKON_EndLiveView" },
290 { PTP_OC_NIKON_GetLiveViewImg
, "NIKON_GetLiveViewImg" },
291 { PTP_OC_NIKON_MfDrive
, "NIKON_MfDrive" },
292 { PTP_OC_NIKON_ChangeAfArea
, "NIKON_ChangeAfArea" },
293 { PTP_OC_NIKON_AfDriveCancel
, "NIKON_AfDriveCancel" },
294 { PTP_OC_NIKON_GetDevicePTPIPInfo
, "NIKON_GetDevicePTPIPInfo" },
297 static value_string_ext ptp_opcode_nikon_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_nikon_names
);
299 static const value_string ptp_opcode_casio_names
[] = {
300 { PTP_OC_CASIO_STILL_START
, "CASIO_STILL_START" },
301 { PTP_OC_CASIO_STILL_STOP
, "CASIO_STILL_STOP" },
302 { PTP_OC_CASIO_FOCUS
, "CASIO_FOCUS" },
303 { PTP_OC_CASIO_CF_PRESS
, "CASIO_CF_PRESS" },
304 { PTP_OC_CASIO_CF_RELEASE
, "CASIO_CF_RELEASE" },
305 { PTP_OC_CASIO_GET_OBJECT_INFO
, "CASIO_GET_OBJECT_INFO" },
306 { PTP_OC_CASIO_SHUTTER
, "CASIO_SHUTTER" },
307 { PTP_OC_CASIO_GET_STILL_HANDLES
, "CASIO_GET_STILL_HANDLES" },
308 { PTP_OC_CASIO_STILL_RESET
, "CASIO_STILL_RESET" },
309 { PTP_OC_CASIO_HALF_PRESS
, "CASIO_HALF_PRESS" },
310 { PTP_OC_CASIO_HALF_RELEASE
, "CASIO_HALF_RELEASE" },
311 { PTP_OC_CASIO_CS_PRESS
, "CASIO_CS_PRESS" },
312 { PTP_OC_CASIO_CS_RELEASE
, "CASIO_CS_RELEASE" },
313 { PTP_OC_CASIO_ZOOM
, "CASIO_ZOOM" },
314 { PTP_OC_CASIO_CZ_PRESS
, "CASIO_CZ_PRESS" },
315 { PTP_OC_CASIO_CZ_RELEASE
, "CASIO_CZ_RELEASE" },
316 { PTP_OC_CASIO_MOVIE_START
, "CASIO_MOVIE_START" },
317 { PTP_OC_CASIO_MOVIE_STOP
, "CASIO_MOVIE_STOP" },
318 { PTP_OC_CASIO_MOVIE_PRESS
, "CASIO_MOVIE_PRESS" },
319 { PTP_OC_CASIO_MOVIE_RELEASE
, "CASIO_MOVIE_RELEASE" },
320 { PTP_OC_CASIO_GET_MOVIE_HANDLES
, "CASIO_GET_MOVIE_HANDLES" },
321 { PTP_OC_CASIO_MOVIE_RESET
, "CASIO_MOVIE_RESET" },
322 { PTP_OC_CASIO_GET_OBJECT
, "CASIO_GET_OBJECT" },
323 { PTP_OC_CASIO_GET_THUMBNAIL
, "CASIO_GET_THUMBNAIL" },
326 static value_string_ext ptp_opcode_casio_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_casio_names
);
328 static const value_string ptp_opcode_mtp_names
[] = {
329 { PTP_OC_MTP_GetObjectPropsSupported
, "MTP_GetObjectPropsSupported" },
330 { PTP_OC_MTP_GetObjectPropDesc
, "MTP_GetObjectPropDesc" },
331 { PTP_OC_MTP_GetObjectPropValue
, "MTP_GetObjectPropValue" },
332 { PTP_OC_MTP_SetObjectPropValue
, "MTP_SetObjectPropValue" },
333 { PTP_OC_MTP_GetObjPropList
, "MTP_GetObjPropList" },
334 { PTP_OC_MTP_SetObjPropList
, "MTP_SetObjPropList" },
335 { PTP_OC_MTP_GetInterdependendPropdesc
, "MTP_GetInterdependendPropdesc" },
336 { PTP_OC_MTP_SendObjectPropList
, "MTP_SendObjectPropList" },
337 { PTP_OC_MTP_GetObjectReferences
, "MTP_GetObjectReferences" },
338 { PTP_OC_MTP_SetObjectReferences
, "MTP_SetObjectReferences" },
339 { PTP_OC_MTP_UpdateDeviceFirmware
, "MTP_UpdateDeviceFirmware" },
340 { PTP_OC_MTP_Skip
, "MTP_Skip" },
341 { PTP_OC_MTP_WMDRMPD_GetSecureTimeChallenge
, "MTP_WMDRMPD_GetSecureTimeChallenge" },
342 { PTP_OC_MTP_WMDRMPD_GetSecureTimeResponse
, "MTP_WMDRMPD_GetSecureTimeResponse" },
343 { PTP_OC_MTP_WMDRMPD_SetLicenseResponse
, "MTP_WMDRMPD_SetLicenseResponse" },
344 { PTP_OC_MTP_WMDRMPD_GetSyncList
, "MTP_WMDRMPD_GetSyncList" },
345 { PTP_OC_MTP_WMDRMPD_SendMeterChallengeQuery
, "MTP_WMDRMPD_SendMeterChallengeQuery" },
346 { PTP_OC_MTP_WMDRMPD_GetMeterChallenge
, "MTP_WMDRMPD_GetMeterChallenge" },
347 { PTP_OC_MTP_WMDRMPD_SetMeterResponse
, "MTP_WMDRMPD_SetMeterResponse" },
348 { PTP_OC_MTP_WMDRMPD_CleanDataStore
, "MTP_WMDRMPD_CleanDataStore" },
349 { PTP_OC_MTP_WMDRMPD_GetLicenseState
, "MTP_WMDRMPD_GetLicenseState" },
350 { PTP_OC_MTP_WMDRMPD_SendWMDRMPDCommand
, "MTP_WMDRMPD_SendWMDRMPDCommand" },
351 { PTP_OC_MTP_WMDRMPD_SendWMDRMPDRequest
, "MTP_WMDRMPD_SendWMDRMPDRequest" },
352 { PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest
, "MTP_WMDRMPD_SendWMDRMPDAppRequest" },
353 { PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse
, "MTP_WMDRMPD_GetWMDRMPDAppResponse" },
354 { PTP_OC_MTP_WMDRMPD_EnableTrustedFilesOperations
, "MTP_WMDRMPD_EnableTrustedFilesOperations" },
355 { PTP_OC_MTP_WMDRMPD_DisableTrustedFilesOperations
, "MTP_WMDRMPD_DisableTrustedFilesOperations" },
356 { PTP_OC_MTP_WMDRMPD_EndTrustedAppSession
, "MTP_WMDRMPD_EndTrustedAppSession" },
357 { PTP_OC_MTP_AAVT_OpenMediaSession
, "MTP_AAVT_OpenMediaSession" },
358 { PTP_OC_MTP_AAVT_CloseMediaSession
, "MTP_AAVT_CloseMediaSession" },
359 { PTP_OC_MTP_AAVT_GetNextDataBlock
, "MTP_AAVT_GetNextDataBlock" },
360 { PTP_OC_MTP_AAVT_SetCurrentTimePosition
, "MTP_AAVT_SetCurrentTimePosition" },
361 { PTP_OC_MTP_WMDRMND_SendRegistrationRequest
, "MTP_WMDRMND_SendRegistrationRequest" },
362 { PTP_OC_MTP_WMDRMND_GetRegistrationResponse
, "MTP_WMDRMND_GetRegistrationResponse" },
363 { PTP_OC_MTP_WMDRMND_GetProximityChallenge
, "MTP_WMDRMND_GetProximityChallenge" },
364 { PTP_OC_MTP_WMDRMND_SendProximityResponse
, "MTP_WMDRMND_SendProximityResponse" },
365 { PTP_OC_MTP_WMDRMND_SendWMDRMNDLicenseRequest
, "MTP_WMDRMND_SendWMDRMNDLicenseRequest" },
366 { PTP_OC_MTP_WMDRMND_GetWMDRMNDLicenseResponse
, "MTP_WMDRMND_GetWMDRMNDLicenseResponse" },
367 { PTP_OC_MTP_WMPPD_ReportAddedDeletedItems
, "MTP_WMPPD_ReportAddedDeletedItems" },
368 { PTP_OC_MTP_WMPPD_ReportAcquiredItems
, "MTP_WMPPD_ReportAcquiredItems" },
369 { PTP_OC_MTP_WMPPD_PlaylistObjectPref
, "MTP_WMPPD_PlaylistObjectPref" },
370 { PTP_OC_MTP_ZUNE_GETUNDEFINED001
, "MTP_ZUNE_GETUNDEFINED001" },
371 { PTP_OC_MTP_WPDWCN_ProcessWFCObject
, "MTP_WPDWCN_ProcessWFCObject" },
374 static value_string_ext ptp_opcode_mtp_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_mtp_names
);
376 static const value_string ptp_opcode_olympus_names
[] = {
377 { PTP_OC_OLYMPUS_Capture
, "OLYMPUS_Capture" },
378 { PTP_OC_OLYMPUS_SelfCleaning
, "OLYMPUS_SelfCleaning" },
379 { PTP_OC_OLYMPUS_SetRGBGain
, "OLYMPUS_SetRGBGain" },
380 { PTP_OC_OLYMPUS_SetPresetMode
, "OLYMPUS_SetPresetMode" },
381 { PTP_OC_OLYMPUS_SetWBBiasAll
, "OLYMPUS_SetWBBiasAll" },
382 { PTP_OC_OLYMPUS_GetCameraControlMode
, "OLYMPUS_GetCameraControlMode" },
383 { PTP_OC_OLYMPUS_SetCameraControlMode
, "OLYMPUS_SetCameraControlMode" },
384 { PTP_OC_OLYMPUS_SetWBRGBGain
, "OLYMPUS_SetWBRGBGain" },
385 { PTP_OC_OLYMPUS_GetDeviceInfo
, "OLYMPUS_GetDeviceInfo" },
386 { PTP_OC_OLYMPUS_Init1
, "OLYMPUS_Init1" },
387 { PTP_OC_OLYMPUS_SetDateTime
, "OLYMPUS_SetDateTime" },
388 { PTP_OC_OLYMPUS_GetDateTime
, "OLYMPUS_GetDateTim" },
389 { PTP_OC_OLYMPUS_SetCameraID
, "OLYMPUS_SetCameraID" },
390 { PTP_OC_OLYMPUS_GetCameraID
, "OLYMPUS_GetCameraID" },
393 static value_string_ext ptp_opcode_olympus_names_ext
= VALUE_STRING_EXT_INIT(ptp_opcode_olympus_names
);
395 static const value_string ptp_respcode_names
[] = {
397 { PTP_RC_GeneralError
, "GeneralError" },
398 { PTP_RC_SessionNotOpen
, "SessionNotOpen" },
399 { PTP_RC_InvalidTransactionID
, "InvalidTransactionID" },
400 { PTP_RC_OperationNotSupported
, "OperationNotSupported" },
401 { PTP_RC_ParameterNotSupported
, "ParameterNotSupported" },
402 { PTP_RC_IncompleteTransfer
, "IncompleteTransfer" },
403 { PTP_RC_InvalidStorageId
, "InvalidStorageId" },
404 { PTP_RC_InvalidObjectHandle
, "InvalidObjectHandle" },
405 { PTP_RC_DevicePropNotSupported
, "DevicePropNotSupported" },
406 { PTP_RC_InvalidObjectFormatCode
, "InvalidObjectFormatCode" },
407 { PTP_RC_StoreFull
, "StoreFull" },
408 { PTP_RC_StoreReadOnly
, "StoreReadOnly" },
409 { PTP_RC_AccessDenied
, "AccessDenied" },
410 { PTP_RC_NoThumbnailPresent
, "NoThumbnailPresent" },
411 { PTP_RC_SelfTestFailed
, "SelfTestFailed" },
412 { PTP_RC_PartialDeletion
, "PartialDeletion" },
413 { PTP_RC_StoreNotAvailable
, "StoreNotAvailable" },
414 { PTP_RC_SpecificationByFormatUnsupported
, "SpecificationByFormatUnsupported" },
415 { PTP_RC_NoValidObjectInfo
, "NoValidObjectInfo" },
416 { PTP_RC_InvalidCodeFormat
, "InvalidCodeFormat" },
417 { PTP_RC_UnknownVendorCode
, "UnknownVendorCode" },
418 { PTP_RC_CaptureAlreadyTerminated
, "CaptureAlreadyTerminated" },
419 { PTP_RC_DeviceBusy
, "DeviceBusy" },
420 { PTP_RC_InvalidParentObject
, "InvalidParentObject" },
421 { PTP_RC_InvalidDevicePropFormat
, "InvalidDevicePropFormat" },
422 { PTP_RC_InvalidDevicePropValue
, "InvalidDevicePropValue" },
423 { PTP_RC_InvalidParameter
, "InvalidParameter" },
424 { PTP_RC_SessionAlreadyOpened
, "SessionAlreadyOpened" },
425 { PTP_RC_TransactionCanceled
, "TransactionCanceled" },
426 { PTP_RC_SpecificationOfDestinationUnsupported
, "SpecificationOfDestinationUnsupported" },
427 { PTP_RC_InvalidEnumHandle
, "InvalidEnumHandle" },
428 { PTP_RC_NoStreamEnabled
, "NoStreamEnabled" },
429 { PTP_RC_InvalidDataSet
, "InvalidDataSet" },
432 /* static value_string_ext ptp_respcode_names_ext = VALUE_STRING_EXT_INIT(ptp_respcode_names); */
434 static const value_string ptp_respcode_ek_names
[] = {
435 { PTP_RC_EK_FilenameRequired
, "EK_FilenameRequired" },
436 { PTP_RC_EK_FilenameConflicts
, "EK_FilenameConflicts" },
437 { PTP_RC_EK_FilenameInvalid
, "EK_FilenameInvalid" },
441 static const value_string ptp_respcode_nikon_names
[] = {
442 { PTP_RC_NIKON_HardwareError
, "NIKON_HardwareError" },
443 { PTP_RC_NIKON_OutOfFocus
, "NIKON_OutOfFocus" },
444 { PTP_RC_NIKON_ChangeCameraModeFailed
, "NIKON_ChangeCameraModeFailed" },
445 { PTP_RC_NIKON_InvalidStatus
, "NIKON_InvalidStatus" },
446 { PTP_RC_NIKON_SetPropertyNotSupported
, "NIKON_SetPropertyNotSupported" },
447 { PTP_RC_NIKON_WbResetError
, "NIKON_WbResetError" },
448 { PTP_RC_NIKON_DustReferenceError
, "NIKON_DustReferenceError" },
449 { PTP_RC_NIKON_ShutterSpeedBulb
, "NIKON_ShutterSpeedBulb" },
450 { PTP_RC_NIKON_MirrorUpSequence
, "NIKON_MirrorUpSequence" },
451 { PTP_RC_NIKON_CameraModeNotAdjustFNumber
, "NIKON_CameraModeNotAdjustFNumber" },
452 { PTP_RC_NIKON_NotLiveView
, "NIKON_NotLiveView" },
453 { PTP_RC_NIKON_MfDriveStepEnd
, "NIKON_MfDriveStepEnd" },
454 { PTP_RC_NIKON_MfDriveStepInsufficiency
, "NIKON_MfDriveStepInsufficiency" },
455 { PTP_RC_NIKON_AdvancedTransferCancel
, "NIKON_AdvancedTransferCancel" },
459 static const value_string ptp_respcode_canon_names
[] = {
460 { PTP_RC_CANON_UNKNOWN_COMMAND
, "CANON_UNKNOWN_COMMAND" },
461 { PTP_RC_CANON_OPERATION_REFUSED
, "CANON_OPERATION_REFUSED" },
462 { PTP_RC_CANON_LENS_COVER
, "CANON_LENS_COVER" },
463 { PTP_RC_CANON_BATTERY_LOW
, "CANON_BATTERY_LOW" },
464 { PTP_RC_CANON_NOT_READY
, "CANON_NOT_READY" },
465 { PTP_RC_CANON_A009
, "CANON_A009" },
469 static const value_string ptp_respcode_mtp_names
[] = {
470 { PTP_RC_MTP_Undefined
, "MTP_Undefined" },
471 { PTP_RC_MTP_Invalid_ObjectPropCode
, "MTP_Invalid_ObjectPropCode" },
472 { PTP_RC_MTP_Invalid_ObjectProp_Format
, "MTP_Invalid_ObjectProp_Format" },
473 { PTP_RC_MTP_Invalid_ObjectProp_Value
, "MTP_Invalid_ObjectProp_Value" },
474 { PTP_RC_MTP_Invalid_ObjectReference
, "MTP_Invalid_ObjectReference" },
475 { PTP_RC_MTP_Invalid_Dataset
, "MTP_Invalid_Dataset" },
476 { PTP_RC_MTP_Specification_By_Group_Unsupported
, "MTP_Specification_By_Group_Unsupported" },
477 { PTP_RC_MTP_Specification_By_Depth_Unsupported
, "MTP_Specification_By_Depth_Unsupported" },
478 { PTP_RC_MTP_Object_Too_Large
, "MTP_Object_Too_Large" },
479 { PTP_RC_MTP_ObjectProp_Not_Supported
, "MTP_ObjectProp_Not_Supported" },
480 { PTP_RC_MTP_Invalid_Media_Session_ID
, "MTP_Invalid_Media_Session_ID" },
481 { PTP_RC_MTP_Media_Session_Limit_Reached
, "MTP_Media_Session_Limit_Reached" },
482 { PTP_RC_MTP_No_More_Data
, "MTP_No_More_Data" },
483 { PTP_RC_MTP_Invalid_WFC_Syntax
, "MTP_Invalid_WFC_Syntax" },
484 { PTP_RC_MTP_WFC_Version_Not_Supported
, "MTP_WFC_Version_Not_Supported" },
488 /* String Names of packet types [3] & [4] */
489 /* PTP/IP definitions */
490 /* enums reformatted from [4] */
493 PTPIP_INIT_COMMAND_REQUEST
= 1,
494 PTPIP_INIT_COMMAND_ACK
= 2,
495 PTPIP_INIT_EVENT_REQUEST
= 3,
496 PTPIP_INIT_EVENT_ACK
= 4,
498 PTPIP_CMD_REQUEST
= 6, /* possibly Operation request in [1] 2.3.6 agrees with [3] */
499 PTPIP_CMD_RESPONSE
= 7, /* possibly Operation response in [1] 2.3.7 agrees with [3] */
501 PTPIP_START_DATA_PACKET
= 9,
502 PTPIP_DATA_PACKET
= 10,
503 PTPIP_CANCEL_TRANSACTION
= 11,
504 PTPIP_END_DATA_PACKET
= 12,
505 PTPIP_PING
= 13, /* possibly Probe Request in [1] 2.3.13 */
506 PTPIP_PONG
= 14 /* possibly Probe Response in [1] 2.3.14 */
509 /* Unless otherwise stated, names are based on info in [3] */
510 static const value_string ptpip_pktType_names
[] = {
511 { PTPIP_INVALID
, "Invalid" },
512 { PTPIP_INIT_COMMAND_REQUEST
, "Init Command Request Packet" },
513 { PTPIP_INIT_COMMAND_ACK
, "Init Command ACK Packet" },
514 { PTPIP_INIT_EVENT_REQUEST
, "Init Event Request Packet" },
515 { PTPIP_INIT_EVENT_ACK
, "Init Event Ack Packet"},
516 { PTPIP_INIT_FAIL
, "Init Fail Packet"},
517 { PTPIP_CMD_REQUEST
, "Operation Request Packet"}, /* string based on [1] */
518 { PTPIP_CMD_RESPONSE
, "Operation Response Packet"}, /* string based on [1] */
519 { PTPIP_EVENT
, "Event Packet"},
520 { PTPIP_START_DATA_PACKET
, "Start Data Packet"},
521 { PTPIP_DATA_PACKET
, "Data Packet"},
522 { PTPIP_CANCEL_TRANSACTION
, "Cancel Packet"},
523 { PTPIP_END_DATA_PACKET
, "End Data Packet"},
524 { PTPIP_PING
, "Probe Request Packet"}, /* string based on [1] */
525 { PTPIP_PONG
, "Probe Response Packet"}, /* string based on [1] */
528 static value_string_ext ptpip_pktType_names_ext
= VALUE_STRING_EXT_INIT(ptpip_pktType_names
);
532 * Primary method to dissect a PTP/IP packet. When a subtype is encounter,
533 * the method will call a subdissector.
536 int dissect_ptpIP (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
538 proto_item
*item_ptr
;
539 proto_tree
*ptp_tree
;
544 /* Check that there's enough data */
545 if ( tvb_captured_length_remaining(tvb
, offset
) < 8 ) /* ptp-photo smallest packet size is 8 */
548 col_set_str(pinfo
->cinfo
,COL_PROTOCOL
, "PTP/IP");
553 "Picture Transfer Protocol");
555 item_ptr
= proto_tree_add_protocol_format(tree
, proto_ptpIP
, tvb
, offset
,
556 -1, "Picture Transfer Protocol");
558 /* creating the tree */
559 ptp_tree
= proto_item_add_subtree(item_ptr
, ett_ptpIP
);
560 /* [1] Defines first 2 fields as length and packet type. (Section 2.3)
561 * Also note: the standard lists all multibyte values in PTP-IP as little-endian
564 /* note: len field size included in total len */
565 proto_tree_add_item(ptp_tree
, hf_ptpIP_len
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
567 /* @todo:maybe add some length verification checks to see if len advertised matches actual len */
569 pktType
= tvb_get_letohl(tvb
, offset
);
570 proto_tree_add_item(ptp_tree
, hf_ptpIP_pktType
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
573 case PTPIP_INIT_COMMAND_REQUEST
:
574 dissect_ptpIP_init_command_request(tvb
, pinfo
, ptp_tree
, &offset
);
576 case PTPIP_INIT_COMMAND_ACK
:
577 dissect_ptpIP_init_command_ack(tvb
, pinfo
, ptp_tree
, &offset
);
579 case PTPIP_INIT_EVENT_REQUEST
:
580 dissect_ptpIP_init_event_request(tvb
, pinfo
, ptp_tree
, &offset
);
582 case PTPIP_INIT_EVENT_ACK
:
583 dissect_ptpIP_init_event_ack(pinfo
);
585 case PTPIP_CMD_REQUEST
:
586 dissect_ptpIP_operation_request(tvb
, pinfo
, ptp_tree
, &offset
);
588 case PTPIP_CMD_RESPONSE
:
589 dissect_ptpIP_operation_response(tvb
, pinfo
, ptp_tree
, &offset
);
592 dissect_ptpIP_event(tvb
, pinfo
, ptp_tree
, &offset
);
594 case PTPIP_START_DATA_PACKET
:
595 dissect_ptpIP_start_data(tvb
, pinfo
, ptp_tree
, &offset
);
597 case PTPIP_DATA_PACKET
:
598 dissect_ptpIP_data(tvb
, pinfo
, ptp_tree
, &offset
);
600 case PTPIP_END_DATA_PACKET
:
601 dissect_ptpIP_end_data(tvb
, pinfo
, ptp_tree
, &offset
);
611 * Method to dissect the Init Command Request sent by the Initiator
612 * in the connection. This packet is defined by [1] Section 2.3.1
614 static void dissect_ptpIP_init_command_request(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
621 "Init Command Request");
623 dissect_ptpIP_guid(tvb
, pinfo
, tree
, offset
);
625 /* grabbing the name */
626 dissect_ptpIP_unicode_name(tvb
, pinfo
, tree
, offset
);
628 /* grabbing protocol version
629 * Note: [3] does not list this in the packet field. . [1] 2.3.1 states it's the last 4
630 * bytes of the packet.
632 dissect_ptpIP_protocol_version(tvb
, tree
, offset
);
637 * Method to dissect the Init Command Ack sent by the Responder
638 * in the connection. This packet is defined by [1] Section 2.3.2
640 static void dissect_ptpIP_init_command_ack(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
642 uint32_t connectionNumber
;
649 /* Grabbing the Connection Number */
650 connectionNumber
= tvb_get_letohl(tvb
, *offset
);
651 proto_tree_add_item(tree
, hf_ptpIP_connectionNumber
, tvb
, *offset
, 4,ENC_LITTLE_ENDIAN
);
659 dissect_ptpIP_guid(tvb
, pinfo
, tree
, offset
);
662 dissect_ptpIP_unicode_name(tvb
,pinfo
, tree
, offset
);
664 /* grabbing protocol version. Note: like in the Init Command Request, [3] doesn't mention
665 * this field, but [1] Section 2.3.2 does.
669 dissect_ptpIP_protocol_version(tvb
, tree
, offset
);
673 * Dissects the Init Event Request packet specified in [1] Section 2.3.3.
674 * Standard states that the packet only has 1 field.
676 static void dissect_ptpIP_init_event_request(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
678 uint32_t connectionNumber
;
683 "Init Event Request");
685 /* Grabbing the Connection Number */
686 connectionNumber
= tvb_get_letohl(tvb
, *offset
);
687 proto_tree_add_item(tree
, hf_ptpIP_connectionNumber
, tvb
, *offset
, 4,ENC_LITTLE_ENDIAN
);
697 * Dissects the Init Event Ack packet specified in [1] Section 2.3.4
699 static void dissect_ptpIP_init_event_ack(packet_info
*pinfo
)
706 /* packet has no payload. */
710 * Dissects the Operation Request Packet specified in [1] Section 2.3.6
711 * Note: many of the fields in this packet move from PTP/IP to PTP layer
712 * of the stack. Work will need to be done in future iterations to make this
713 * compatible with PTP/USB.
715 static void dissect_ptpIP_operation_request(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
718 uint16_t transactionID_offset
= *offset
; /* need to save this to output transaction id in pinfo */
723 "Operation Request Packet ");
725 proto_tree_add_item(tree
,hf_ptpIP_dataPhaseInfo
, tvb
, *offset
, 4, ENC_LITTLE_ENDIAN
);
728 opcode
= tvb_get_letohs(tvb
, *offset
);
729 if (opcode
& PTP_OC_EXTENSION_MASK
)
731 if (pref_vendor
== PTP_VENDOR_UNKNOWN
)
733 proto_tree_add_item(tree
, hf_ptp_vendor_opCode
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
737 value_string_ext
* vendor_values
= NULL
;
741 case PTP_VENDOR_EASTMAN_KODAK
:
742 vendor_values
= &ptp_opcode_ek_names_ext
;
744 case PTP_VENDOR_CANON
:
745 vendor_values
= &ptp_opcode_canon_names_ext
;
747 case PTP_VENDOR_NIKON
:
748 vendor_values
= &ptp_opcode_nikon_names_ext
;
750 case PTP_VENDOR_CASIO
:
751 vendor_values
= &ptp_opcode_casio_names_ext
;
754 vendor_values
= &ptp_opcode_mtp_names_ext
;
756 case PTP_VENDOR_OLYMPUS
:
757 vendor_values
= &ptp_opcode_olympus_names_ext
;
760 DISSECTOR_ASSERT(false);
764 proto_tree_add_uint_format_value(tree
, hf_ptp_vendor_opCode
, tvb
, *offset
, 2, opcode
, "%s (0x%04x)",
765 val_to_str_ext_const(opcode
, vendor_values
, "Unknown"), opcode
);
770 proto_tree_add_item(tree
, hf_ptp_opCode
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
774 transactionID_offset
= *offset
; /* we'll dissect the transactionID later because
775 opcode handling erases the column */
778 /* carving out the parameters. [1] 2.3.6 states there can be at most 5. Params are defined in [2] 10.1 & 10.4 */
781 case PTP_OC_GetDeviceInfo
:
789 case PTP_OC_OpenSession
:
790 dissect_ptp_opCode_openSession(tvb
, pinfo
, tree
, offset
);
792 case PTP_OC_CloseSession
:
800 case PTP_OC_GetStorageIDs
:
806 /* states data is a storage array. Needs eventual investigation. */
811 dissect_ptp_transactionID(tvb
, pinfo
, tree
, &transactionID_offset
);
815 * Dissects the Operation Response Packet specified in [1] Section 2.3.7
816 * Note: many of the fields in this packet move from PTP/IP to PTP layer
817 * of the stack. Work will need to be done in future iterations to make this
818 * compatible with PTP/USB.
820 static void dissect_ptpIP_operation_response(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
827 "Operation Response Packet ");
829 resp
= tvb_get_letohs(tvb
, *offset
);
830 if (resp
& PTP_OC_EXTENSION_MASK
)
832 const value_string
* vendor_values
= NULL
;
835 case PTP_VENDOR_EASTMAN_KODAK
:
836 vendor_values
= ptp_respcode_ek_names
;
838 case PTP_VENDOR_CANON
:
839 vendor_values
= ptp_respcode_canon_names
;
841 case PTP_VENDOR_NIKON
:
842 vendor_values
= ptp_respcode_nikon_names
;
845 vendor_values
= ptp_respcode_mtp_names
;
847 case PTP_VENDOR_UNKNOWN
:
848 case PTP_VENDOR_CASIO
:
849 case PTP_VENDOR_OLYMPUS
:
851 vendor_values
= ptp_respcode_names
;
855 proto_tree_add_uint_format_value(tree
, hf_ptp_vendor_opCode
, tvb
, *offset
, 2, resp
, "%s (0x%04x)",
856 val_to_str_const(resp
, vendor_values
, "Unknown"), resp
);
860 proto_tree_add_item(tree
, hf_ptp_respCode
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
864 dissect_ptp_transactionID(tvb
, pinfo
, tree
, offset
);
869 * Dissects the Event Packet specified in [1] Section 2.3.8
870 * Note: many of the fields in this packet move from PTP/IP to PTP layer
871 * of the stack. Work will need to be done in future iterations to make this
872 * compatible with PTP/USB.
874 static void dissect_ptpIP_event(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
881 proto_tree_add_item(tree
, hf_ptp_eventCode
, tvb
, *offset
, 2, ENC_LITTLE_ENDIAN
);
884 dissect_ptp_transactionID(tvb
, pinfo
, tree
, offset
);
888 * Dissects the Event Packet specified in [1] Section 2.3.9
889 * Note: many of the fields in this packet move from PTP/IP to PTP layer
890 * of the stack. Work will need to be done in future iterations to make this
891 * compatible with PTP/USB.
893 static void dissect_ptpIP_start_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
900 "Start Data Packet ");
902 dissect_ptp_transactionID(tvb
, pinfo
, tree
, offset
);
905 dataLen
= tvb_get_letoh64(tvb
, *offset
);
906 proto_tree_add_item(tree
, hf_ptp_totalDataLength
, tvb
, *offset
, 8, ENC_LITTLE_ENDIAN
);
908 if (dataLen
== UINT64_C(0xFFFFFFFFFFFFFFFF)) /* [1] specifies in 2.3.9 if total data len
909 is this value then len is unknown */
914 " Data Length Unknown");
918 static void dissect_ptpIP_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
926 dissect_ptp_transactionID(tvb
, pinfo
, tree
, offset
);
931 * Dissects the End Data specified in [1] Section 2.3.11
932 * Note: many of the fields in this packet move from PTP/IP to PTP layer
933 * of the stack. Work will need to be done in future iterations to make this
934 * compatible with PTP/USB.
936 static void dissect_ptpIP_end_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
944 dissect_ptp_transactionID(tvb
, pinfo
, tree
, offset
);
948 * Dissects the Opcode Open Session as defined by [2] 10.5.2
950 void dissect_ptp_opCode_openSession(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
957 proto_tree_add_item(tree
, hf_ptp_opCode_param_sessionID
, tvb
, *offset
, 4 , ENC_LITTLE_ENDIAN
);
962 * The transaction ID is defined in [2] 9.3.1
963 * and used in multiple message types. This method handles
964 * parsing the field and adding the value to the info
968 void dissect_ptp_transactionID(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
970 uint32_t transactionID
;
972 transactionID
= tvb_get_letohl(tvb
, *offset
);
973 proto_tree_add_item(tree
, hf_ptp_transactionID
, tvb
, *offset
, 4, ENC_LITTLE_ENDIAN
);
978 " Transaction ID: %d",
983 * This method handles dissecting the Unicode name that is
984 * specificed in multiple packets.
986 static void dissect_ptpIP_unicode_name(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
991 nameLen
= tvb_unicode_strsize(tvb
, *offset
);
992 proto_tree_add_item_ret_string(tree
, hf_ptpIP_name
, tvb
, *offset
, nameLen
, ENC_UTF_16
|ENC_LITTLE_ENDIAN
, pinfo
->pool
, &name
);
994 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " Name: %s", name
);
997 /** Method dissects the protocol version from the packets.
998 * Additional note, section 3 of [1] defines the Binary Protocol version
999 * as 0x00010000 == 1.0 where the Most significant bits are the major version and the least
1000 * significant bits are the minor version.
1002 static void dissect_ptpIP_protocol_version(tvbuff_t
*tvb
, proto_tree
*tree
, uint16_t *offset
)
1005 uint8_t version
[30];
1006 uint32_t protoVersion
;
1007 uint16_t majorVersion
, minorVersion
;
1009 protoVersion
= tvb_get_letohl(tvb
, *offset
);
1010 /* logic to format version */
1011 minorVersion
= protoVersion
& 0xFFFF;
1012 majorVersion
= (protoVersion
& 0xFFFF0000) >>16;
1013 snprintf(version
, sizeof(version
), "%u.%u", majorVersion
, minorVersion
);
1014 proto_tree_add_string(tree
, hf_ptpIP_version
, tvb
, *offset
, 4, version
);
1018 /* Grabbing the GUID */
1019 static void dissect_ptpIP_guid(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, uint16_t *offset
)
1023 guid
= tvb_bytes_to_str(pinfo
->pool
, tvb
, *offset
, PTPIP_GUID_SIZE
);
1024 proto_tree_add_item(tree
, hf_ptpIP_guid
, tvb
, *offset
, PTPIP_GUID_SIZE
, ENC_NA
);
1025 *offset
+= PTPIP_GUID_SIZE
;
1033 void proto_register_ptpip( void )
1035 static hf_register_info hf
[] = {
1038 "Length", "ptpip.len", FT_UINT32
, BASE_DEC
,
1039 NULL
, 0, NULL
, HFILL
}},
1040 { &hf_ptpIP_pktType
, {
1041 "Packet Type", "ptpip.pktType", FT_UINT32
, BASE_HEX
| BASE_EXT_STRING
,
1042 &ptpip_pktType_names_ext
, 0, NULL
, HFILL
}},
1044 "GUID", "ptpip.guid", FT_BYTES
, BASE_NONE
,
1045 NULL
, 0, NULL
, HFILL
}},
1047 "Host Name", "ptpip.name", FT_STRINGZ
, BASE_NONE
,
1048 NULL
, 0, NULL
, HFILL
}},
1049 { &hf_ptpIP_version
, {
1050 "Version", "ptpip.version", FT_STRING
, BASE_NONE
,
1051 NULL
, 0, NULL
, HFILL
}},
1052 { &hf_ptpIP_connectionNumber
, {
1053 "Connection Number", "ptpip.connection", FT_UINT32
, BASE_DEC
,
1054 NULL
, 0, NULL
, HFILL
}},
1055 { &hf_ptpIP_dataPhaseInfo
, {
1056 "Data Phase Info", "ptpip.phaseinfo", FT_UINT32
, BASE_HEX
,
1057 NULL
, 0, NULL
, HFILL
}},
1059 /* leaving names with "ptpip" to try and prevent namespace issues. probably changing later. */
1061 "Operation Code", "ptpip.opcode", FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
,
1062 &ptp_opcode_names_ext
, 0, NULL
, HFILL
}},
1063 { &hf_ptp_vendor_opCode
, {
1064 "Operation Code", "ptpip.opcode", FT_UINT16
, BASE_HEX
,
1065 NULL
, 0, NULL
, HFILL
}},
1066 { &hf_ptp_respCode
, {
1067 "Response Code", "ptpip.respcode", FT_UINT16
, BASE_HEX
,
1068 VALS(ptp_respcode_names
), 0, NULL
, HFILL
}},
1069 { &hf_ptp_eventCode
, {
1070 "Event Code", "ptpip.eventcode", FT_UINT16
, BASE_HEX
,
1071 NULL
, 0, NULL
, HFILL
}},
1072 { &hf_ptp_transactionID
, {
1073 "Transaction ID", "ptpip.transactionID", FT_UINT32
, BASE_HEX
,
1074 NULL
, 0, NULL
, HFILL
}},
1075 { &hf_ptp_totalDataLength
, {
1076 "Total Data Length", "ptpip.datalen", FT_UINT64
, BASE_DEC_HEX
,
1077 NULL
, 0, NULL
, HFILL
}},
1078 { &hf_ptp_opCode_param_sessionID
, {
1079 "Session ID", "ptpip.opcode.param.sessionid", FT_UINT32
, BASE_HEX
,
1080 NULL
, 0, NULL
, HFILL
}},
1083 static int *ett
[] = {
1088 module_t
*ptpIP_module
;
1090 proto_ptpIP
= proto_register_protocol("Picture Transfer Protocol Over IP", "PTP/IP", "ptpip");
1092 proto_register_field_array(proto_ptpIP
, hf
, array_length(hf
));
1093 proto_register_subtree_array(ett
, array_length(ett
));
1095 /* Use register_dissector() to indicate that dissect_ptpIP()
1096 * returns the number of bytes it dissected (or 0 if it thinks the packet
1097 * does not belong to PROTONAME).
1099 ptpIP_handle
= register_dissector("ptpip", dissect_ptpIP
, proto_ptpIP
);
1101 ptpIP_module
= prefs_register_protocol(proto_ptpIP
, NULL
);
1103 prefs_register_enum_preference(ptpIP_module
, "vendor",
1105 "Properly translates vendor specific opcodes",
1106 &pref_vendor
, pref_hsp_role
, false);
1110 void proto_reg_handoff_ptpIP( void ) {
1111 dissector_add_uint_with_preference("tcp.port", PTPIP_PORT
, ptpIP_handle
);
1115 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1120 * indent-tabs-mode: nil
1123 * vi: set shiftwidth=4 tabstop=8 expandtab:
1124 * :indentSize=4:tabSize=8:noTabs=true: