GSM A DTAP: add UMTS EVS to supported codecs list IE
[metze/wireshark/wip.git] / epan / dissectors / packet-ptpip.c
1 /* packet-ptpip.c
2  * Routines for PTP/IP (Picture Transfer Protocol) packet dissection
3  * 0xBismarck 2013
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 /**
13  * References:
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
19  *
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.
22  */
23 #include "config.h"
24 #include <epan/packet.h>
25 #include <epan/prefs.h>
26 #include "packet-ptpip.h"
27
28 /* Define */
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 */
32
33 /* trees */
34 static gint ett_ptpIP =  -1;
35 static gint ett_ptpIP_hdr = -1;
36
37 /* PTP/IP Fields */
38 static int proto_ptpIP = -1;
39 static int hf_ptpIP_len = -1; /* [1] Section 2.3 */
40 static int hf_ptpIP_pktType = -1; /* [1] Section 2.3 */
41 static int hf_ptpIP_guid = -1;
42 static int hf_ptpIP_name = -1;
43 static int hf_ptpIP_version = -1;
44 static int hf_ptpIP_connectionNumber = -1;
45 static int hf_ptpIP_dataPhaseInfo = -1;
46
47 /* note: separating the fields to make it easier to divide this code later. */
48
49 /* PTP Fields */
50 /* picking hf_ptp for now. Might need to change later for namespace issues with Precision Time Protocol. */
51 static int hf_ptp_opCode = -1;
52 static int hf_ptp_vendor_opCode = -1;
53 static int hf_ptp_respCode = -1;
54 static int hf_ptp_vendor_respCode = -1;
55 static int hf_ptp_eventCode = -1;
56 static int hf_ptp_transactionID = -1;
57 static int hf_ptp_totalDataLength = -1;
58 static int hf_ptp_opCode_param_sessionID = -1;
59
60 /* function declarations */
61 static int dissect_ptpIP (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_);
62 void dissect_ptpIP_init_command_request (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
63 void dissect_ptpIP_init_command_ack     (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
64 void dissect_ptpIP_init_event_request   (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
65 void dissect_ptpIP_init_event_ack       (               packet_info *pinfo);
66 void dissect_ptpIP_operation_request    (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
67 void dissect_ptpIP_operation_response   (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
68 void dissect_ptpIP_start_data           (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
69 void dissect_ptpIP_data                 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
70 void dissect_ptpIP_end_data             (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
71 void dissect_ptpIP_event                (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
72 void dissect_ptpIP_unicode_name         (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
73 void dissect_ptpIP_protocol_version     (tvbuff_t *tvb,                     proto_tree *tree, guint16 *offset);
74 void dissect_ptpIP_guid                 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset);
75 void proto_register_ptpip( void );
76 void proto_reg_handoff_ptpIP( void );
77
78 typedef enum {
79     PTP_VENDOR_UNKNOWN = 0,
80     PTP_VENDOR_EASTMAN_KODAK = 1,
81     PTP_VENDOR_CANON = 2,
82     PTP_VENDOR_NIKON = 3,
83     PTP_VENDOR_CASIO = 4,
84     PTP_VENDOR_MTP = 5,
85     PTP_VENDOR_OLYMPUS = 6
86 } ptp_vendors;
87
88 static const enum_val_t pref_hsp_role[] = {
89     { "Unknown",        "Unknown vendor",   PTP_VENDOR_UNKNOWN },
90     { "Eastman Kodak",  "Eastman Kodak",    PTP_VENDOR_EASTMAN_KODAK},
91     { "Canon",          "Canon",            PTP_VENDOR_CANON },
92     { "Nikon",          "Nikon",            PTP_VENDOR_NIKON },
93     { "Casio",          "Casio EX-F1",      PTP_VENDOR_CASIO },
94     { "Microsoft / MTP","Microsoft / MTP",  PTP_VENDOR_MTP },
95     { "Olympus",        "Olympus E series", PTP_VENDOR_OLYMPUS },
96     { NULL, NULL, 0 }
97 };
98
99 /* Vendor preference for deciphering opcodes */
100 static int pref_vendor = 0;
101
102
103 static const value_string ptp_opcode_names[] = {
104     { PTP_OC_GetDeviceInfo,                             "GetDeviceInfo" },
105     { PTP_OC_OpenSession,                               "OpenSession" },
106     { PTP_OC_CloseSession,                              "CloseSession" },
107     { PTP_OC_GetStorageIDs,                             "GetStorageIDs" },
108     { PTP_OC_GetStorageInfo,                            "GetStorageInfo" },
109     { PTP_OC_GetNumObjects,                             "GetNumObjects" },
110     { PTP_OC_GetObjectHandles,                          "GetObjectHandles" },
111     { PTP_OC_GetObjectInfo,                             "GetObjectInfo" },
112     { PTP_OC_GetObject,                                 "GetObject" },
113     { PTP_OC_DeleteObject,                              "DeleteObject" },
114     { PTP_OC_SendObjectInfo,                            "SendObjectInfo" },
115     { PTP_OC_SendObject,                                "SendObject" },
116     { PTP_OC_InitiateCapture,                           "InitiateCapture" },
117     { PTP_OC_FormatStore,                               "FormatStore" },
118     { PTP_OC_ResetDevice,                               "ResetDevice" },
119     { PTP_OC_SelfTest,                                  "SelfTest" },
120     { PTP_OC_SetObjectProtection,                       "SetObjectProtection" },
121     { PTP_OC_PowerDown,                                 "PowerDown" },
122     { PTP_OC_GetDevicePropDesc,                         "GetDevicePropDesc" },
123     { PTP_OC_GetDevicePropValue,                        "GetDevicePropValue" },
124     { PTP_OC_SetDevicePropValue,                        "SetDevicePropValue" },
125     { PTP_OC_ResetDevicePropValue,                      "ResetDevicePropValue" },
126     { PTP_OC_TerminateOpenCapture,                      "TerminateOpenCapture" },
127     { PTP_OC_MoveObject,                                "MoveObject" },
128     { PTP_OC_CopyObject,                                "CopyObject" },
129     { PTP_OC_GetPartialObject,                          "GetPartialObject" },
130     { PTP_OC_InitiateOpenCapture,                       "InitiateOpenCapture" },
131     { PTP_OC_StartEnumHandles,                          "StartEnumHandles" },
132     { PTP_OC_EnumHandles,                               "EnumHandles" },
133     { PTP_OC_StopEnumHandles,                           "StopEnumHandles" },
134     { PTP_OC_GetVendorExtensionMaps,                    "GetVendorExtensionMaps" },
135     { PTP_OC_GetVendorDeviceInfo,                       "GetVendorDeviceInfo" },
136     { PTP_OC_GetResizedImageObject,                     "GetResizedImageObject" },
137     { PTP_OC_GetFilesystemManifest,                     "GetFilesystemManifest" },
138     { PTP_OC_GetStreamInfo,                             "GetStreamInfo" },
139     { PTP_OC_GetStream,                                 "GetStream" },
140     { 0,                                                 NULL }
141 };
142 static value_string_ext ptp_opcode_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_names);
143
144 static const value_string ptp_opcode_ek_names[] = {
145     { PTP_OC_EK_GetSerial,                              "EK_GetSerial" },
146     { PTP_OC_EK_SetSerial,                              "EK_SetSerial" },
147     { PTP_OC_EK_SendFileObjectInfo,                     "EK_SendFileObjectInfo" },
148     { PTP_OC_EK_SendFileObject,                         "EK_SendFileObject" },
149     { PTP_OC_EK_SetText,                                "EK_SetText" },
150     { 0,                                                 NULL }
151 };
152 static value_string_ext ptp_opcode_ek_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_ek_names);
153
154 static const value_string ptp_opcode_canon_names[] = {
155     { PTP_OC_CANON_GetPartialObjectInfo,                "CANON_GetPartialObjectInfo" },
156     { PTP_OC_CANON_SetObjectArchive,                    "CANON_SetObjectArchive" },
157     { PTP_OC_CANON_KeepDeviceOn,                        "CANON_KeepDeviceOn" },
158     { PTP_OC_CANON_LockDeviceUI,                        "CANON_LockDeviceUI" },
159     { PTP_OC_CANON_UnlockDeviceUI,                      "CANON_UnlockDeviceUI" },
160     { PTP_OC_CANON_GetObjectHandleByName,               "CANON_GetObjectHandleByName" },
161     { PTP_OC_CANON_InitiateReleaseControl,              "CANON_InitiateReleaseControl" },
162     { PTP_OC_CANON_TerminateReleaseControl,             "CANON_TerminateReleaseControl" },
163     { PTP_OC_CANON_TerminatePlaybackMode,               "CANON_TerminatePlaybackMode" },
164     { PTP_OC_CANON_ViewfinderOn,                        "CANON_ViewfinderOn" },
165     { PTP_OC_CANON_ViewfinderOff,                       "CANON_ViewfinderOff" },
166     { PTP_OC_CANON_DoAeAfAwb,                           "CANON_DoAeAfAwb" },
167     { PTP_OC_CANON_GetCustomizeSpec,                    "CANON_GetCustomizeSpec" },
168     { PTP_OC_CANON_GetCustomizeItemInfo,                "CANON_GetCustomizeItemInfo" },
169     { PTP_OC_CANON_GetCustomizeData,                    "CANON_GetCustomizeData" },
170     { PTP_OC_CANON_SetCustomizeData,                    "CANON_SetCustomizeData" },
171     { PTP_OC_CANON_GetCaptureStatus,                    "CANON_GetCaptureStatus" },
172     { PTP_OC_CANON_CheckEvent,                          "CANON_CheckEvent" },
173     { PTP_OC_CANON_FocusLock,                           "CANON_FocusLock" },
174     { PTP_OC_CANON_FocusUnlock,                         "CANON_FocusUnlock" },
175     { PTP_OC_CANON_GetLocalReleaseParam,                "CANON_GetLocalReleaseParam" },
176     { PTP_OC_CANON_SetLocalReleaseParam,                "CANON_SetLocalReleaseParam" },
177     { PTP_OC_CANON_AskAboutPcEvf,                       "CANON_AskAboutPcEvf" },
178     { PTP_OC_CANON_SendPartialObject,                   "CANON_SendPartialObject" },
179     { PTP_OC_CANON_InitiateCaptureInMemory,             "CANON_InitiateCaptureInMemory" },
180     { PTP_OC_CANON_GetPartialObjectEx,                  "CANON_GetPartialObjectEx" },
181     { PTP_OC_CANON_SetObjectTime,                       "CANON_SetObjectTime" },
182     { PTP_OC_CANON_GetViewfinderImage,                  "CANON_GetViewfinderImage" },
183     { PTP_OC_CANON_GetObjectAttributes,                 "CANON_GetObjectAttributes" },
184     { PTP_OC_CANON_ChangeUSBProtocol,                   "CANON_ChangeUSBProtocol" },
185     { PTP_OC_CANON_GetChanges,                          "CANON_GetChanges" },
186     { PTP_OC_CANON_GetObjectInfoEx,                     "CANON_GetObjectInfoEx" },
187     { PTP_OC_CANON_InitiateDirectTransfer,              "CANON_InitiateDirectTransfer" },
188     { PTP_OC_CANON_TerminateDirectTransfer,             "CANON_TerminateDirectTransfer" },
189     { PTP_OC_CANON_SendObjectInfoByPath,                "CANON_SendObjectInfoByPath" },
190     { PTP_OC_CANON_SendObjectByPath,                    "CANON_SendObjectByPath" },
191     { PTP_OC_CANON_InitiateDirectTansferEx,             "CANON_InitiateDirectTansferEx" },
192     { PTP_OC_CANON_GetAncillaryObjectHandles,           "CANON_GetAncillaryObjectHandles" },
193     { PTP_OC_CANON_GetTreeInfo,                         "CANON_GetTreeInfo" },
194     { PTP_OC_CANON_GetTreeSize,                         "CANON_GetTreeSize" },
195     { PTP_OC_CANON_NotifyProgress,                      "CANON_NotifyProgress" },
196     { PTP_OC_CANON_NotifyCancelAccepted,                "CANON_NotifyCancelAccepted" },
197     { PTP_OC_CANON_902C,                                "CANON_902C" },
198     { PTP_OC_CANON_SetPairingInfo,                      "CANON_SetPairingInfo" },
199     { PTP_OC_CANON_GetPairingInfo,                      "CANON_GetPairingInfo" },
200     { PTP_OC_CANON_DeletePairingInfo,                   "CANON_DeletePairingInfo" },
201     { PTP_OC_CANON_GetMACAddress,                       "CANON_GetMACAddress" },
202     { PTP_OC_CANON_SetDisplayMonitor,                   "CANON_SetDisplayMonitor" },
203     { PTP_OC_CANON_PairingComplete,                     "CANON_PairingComplete" },
204     { PTP_OC_CANON_GetWirelessMAXChannel,               "CANON_GetWirelessMAXChannel" },
205     { PTP_OC_CANON_EOS_GetStorageIDs,                   "CANON_EOS_GetStorageIDs" },
206     { PTP_OC_CANON_EOS_GetStorageInfo,                  "CANON_EOS_GetStorageInfo" },
207     { PTP_OC_CANON_EOS_GetObjectInfo,                   "CANON_EOS_GetObjectInfo" },
208     { PTP_OC_CANON_EOS_GetObject,                       "CANON_EOS_GetObject" },
209     { PTP_OC_CANON_EOS_DeleteObject,                    "CANON_EOS_DeleteObject" },
210     { PTP_OC_CANON_EOS_FormatStore,                     "CANON_EOS_FormatStore" },
211     { PTP_OC_CANON_EOS_GetPartialObject,                "CANON_EOS_GetPartialObject" },
212     { PTP_OC_CANON_EOS_GetDeviceInfoEx,                 "CANON_EOS_GetDeviceInfoEx" },
213     { PTP_OC_CANON_EOS_GetObjectInfoEx,                 "CANON_EOS_GetObjectInfoEx" },
214     { PTP_OC_CANON_EOS_GetThumbEx,                      "CANON_EOS_GetThumbEx" },
215     { PTP_OC_CANON_EOS_SendPartialObject,               "CANON_EOS_SendPartialObject" },
216     { PTP_OC_CANON_EOS_SetObjectAttributes,             "CANON_EOS_SetObjectAttributes" },
217     { PTP_OC_CANON_EOS_GetObjectTime,                   "CANON_EOS_GetObjectTime" },
218     { PTP_OC_CANON_EOS_SetObjectTime,                   "CANON_EOS_SetObjectTime" },
219     { PTP_OC_CANON_EOS_RemoteRelease,                   "CANON_EOS_RemoteRelease" },
220     { PTP_OC_CANON_EOS_SetDevicePropValueEx,            "CANON_EOS_SetDevicePropValueEx" },
221     { PTP_OC_CANON_EOS_GetRemoteMode,                   "CANON_EOS_GetRemoteMode" },
222     { PTP_OC_CANON_EOS_SetRemoteMode,                   "CANON_EOS_SetRemoteMode" },
223     { PTP_OC_CANON_EOS_SetEventMode,                    "CANON_EOS_SetEventMode" },
224     { PTP_OC_CANON_EOS_GetEvent,                        "CANON_EOS_GetEvent" },
225     { PTP_OC_CANON_EOS_TransferComplete,                "CANON_EOS_TransferComplete" },
226     { PTP_OC_CANON_EOS_CancelTransfer,                  "CANON_EOS_CancelTransfer" },
227     { PTP_OC_CANON_EOS_ResetTransfer,                   "CANON_EOS_ResetTransfer" },
228     { PTP_OC_CANON_EOS_PCHDDCapacity,                   "CANON_EOS_PCHDDCapacity" },
229     { PTP_OC_CANON_EOS_SetUILock,                       "CANON_EOS_SetUILock" },
230     { PTP_OC_CANON_EOS_ResetUILock,                     "CANON_EOS_ResetUILock" },
231     { PTP_OC_CANON_EOS_KeepDeviceOn,                    "CANON_EOS_KeepDeviceOn" },
232     { PTP_OC_CANON_EOS_SetNullPacketMode,               "CANON_EOS_SetNullPacketMode" },
233     { PTP_OC_CANON_EOS_UpdateFirmware,                  "CANON_EOS_UpdateFirmware" },
234     { PTP_OC_CANON_EOS_TransferCompleteDT,              "CANON_EOS_TransferCompleteDT" },
235     { PTP_OC_CANON_EOS_CancelTransferDT,                "CANON_EOS_CancelTransferDT" },
236     { PTP_OC_CANON_EOS_SetWftProfile,                   "CANON_EOS_SetWftProfile" },
237     { PTP_OC_CANON_EOS_GetWftProfile,                   "CANON_EOS_GetWftProfile" },
238     { PTP_OC_CANON_EOS_SetProfileToWft,                 "CANON_EOS_SetProfileToWft" },
239     { PTP_OC_CANON_EOS_BulbStart,                       "CANON_EOS_BulbStart" },
240     { PTP_OC_CANON_EOS_BulbEnd,                         "CANON_EOS_BulbEnd" },
241     { PTP_OC_CANON_EOS_RequestDevicePropValue,          "CANON_EOS_RequestDevicePropValue" },
242     { PTP_OC_CANON_EOS_RemoteReleaseOn,                 "CANON_EOS_RemoteReleaseOn" },
243     { PTP_OC_CANON_EOS_RemoteReleaseOff,                "CANON_EOS_RemoteReleaseOff" },
244     { PTP_OC_CANON_EOS_InitiateViewfinder,              "CANON_EOS_InitiateViewfinder" },
245     { PTP_OC_CANON_EOS_TerminateViewfinder,             "CANON_EOS_TerminateViewfinder" },
246     { PTP_OC_CANON_EOS_GetViewFinderData,               "CANON_EOS_GetViewFinderData" },
247     { PTP_OC_CANON_EOS_DoAf,                            "CANON_EOS_DoAf" },
248     { PTP_OC_CANON_EOS_DriveLens,                       "CANON_EOS_DriveLens" },
249     { PTP_OC_CANON_EOS_DepthOfFieldPreview,             "CANON_EOS_DepthOfFieldPreview" },
250     { PTP_OC_CANON_EOS_ClickWB,                         "CANON_EOS_ClickWB" },
251     { PTP_OC_CANON_EOS_Zoom,                            "CANON_EOS_Zoom" },
252     { PTP_OC_CANON_EOS_ZoomPosition,                    "CANON_EOS_ZoomPosition" },
253     { PTP_OC_CANON_EOS_SetLiveAfFrame,                  "CANON_EOS_SetLiveAfFrame" },
254     { PTP_OC_CANON_EOS_AfCancel,                        "CANON_EOS_AfCancel" },
255     { PTP_OC_CANON_EOS_FAPIMessageTX,                   "CANON_EOS_FAPIMessageTX" },
256     { PTP_OC_CANON_EOS_FAPIMessageRX,                   "CANON_EOS_FAPIMessageRX" },
257     { 0,                                                 NULL }
258 };
259 static value_string_ext ptp_opcode_canon_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_canon_names);
260
261 static const value_string ptp_opcode_nikon_names[] = {
262     { PTP_OC_NIKON_GetProfileAllData,                   "NIKON_GetProfileAllData" },
263     { PTP_OC_NIKON_SendProfileData,                     "NIKON_SendProfileData" },
264     { PTP_OC_NIKON_SendProfileData,                     "NIKON_SendProfileData" },
265     { PTP_OC_NIKON_DeleteProfile,                       "NIKON_DeleteProfile" },
266     { PTP_OC_NIKON_SetProfileData,                      "NIKON_SetProfileData" },
267     { PTP_OC_NIKON_AdvancedTransfer,                    "NIKON_AdvancedTransfer" },
268     { PTP_OC_NIKON_GetFileInfoInBlock,                  "NIKON_GetFileInfoInBlock" },
269     { PTP_OC_NIKON_Capture,                             "NIKON_Capture" },
270     { PTP_OC_NIKON_AfDrive,                             "NIKON_AfDrive" },
271     { PTP_OC_NIKON_SetControlMode,                      "NIKON_SetControlMode" },
272     { PTP_OC_NIKON_DelImageSDRAM,                       "NIKON_DelImageSDRAM" },
273     { PTP_OC_NIKON_GetLargeThumb,                       "NIKON_GetLargeThumb" },
274     { PTP_OC_NIKON_CurveDownload,                       "NIKON_CurveDownload" },
275     { PTP_OC_NIKON_CurveUpload,                         "NIKON_CurveUpload" },
276     { PTP_OC_NIKON_CheckEvent,                          "NIKON_CheckEvent" },
277     { PTP_OC_NIKON_DeviceReady,                         "NIKON_DeviceReady" },
278     { PTP_OC_NIKON_SetPreWBData,                        "NIKON_SetPreWBData" },
279     { PTP_OC_NIKON_GetVendorPropCodes,                  "NIKON_GetVendorPropCodes" },
280     { PTP_OC_NIKON_AfCaptureSDRAM,                      "NIKON_AfCaptureSDRAM" },
281     { PTP_OC_NIKON_GetPictCtrlData,                     "NIKON_GetPictCtrlData" },
282     { PTP_OC_NIKON_SetPictCtrlData,                     "NIKON_SetPictCtrlData" },
283     { PTP_OC_NIKON_DelCstPicCtrl,                       "NIKON_DelCstPicCtrl" },
284     { PTP_OC_NIKON_GetPicCtrlCapability,                "NIKON_GetPicCtrlCapability" },
285     { PTP_OC_NIKON_GetPreviewImg,                       "NIKON_GetPreviewImg" },
286     { PTP_OC_NIKON_StartLiveView,                       "NIKON_StartLiveView" },
287     { PTP_OC_NIKON_EndLiveView,                         "NIKON_EndLiveView" },
288     { PTP_OC_NIKON_GetLiveViewImg,                      "NIKON_GetLiveViewImg" },
289     { PTP_OC_NIKON_MfDrive,                             "NIKON_MfDrive" },
290     { PTP_OC_NIKON_ChangeAfArea,                        "NIKON_ChangeAfArea" },
291     { PTP_OC_NIKON_AfDriveCancel,                       "NIKON_AfDriveCancel" },
292     { PTP_OC_NIKON_GetDevicePTPIPInfo,                  "NIKON_GetDevicePTPIPInfo" },
293     { 0,                                                 NULL }
294 };
295 static value_string_ext ptp_opcode_nikon_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_nikon_names);
296
297 static const value_string ptp_opcode_casio_names[] = {
298     { PTP_OC_CASIO_STILL_START,                         "CASIO_STILL_START" },
299     { PTP_OC_CASIO_STILL_STOP,                          "CASIO_STILL_STOP" },
300     { PTP_OC_CASIO_FOCUS,                               "CASIO_FOCUS" },
301     { PTP_OC_CASIO_CF_PRESS,                            "CASIO_CF_PRESS" },
302     { PTP_OC_CASIO_CF_RELEASE,                          "CASIO_CF_RELEASE" },
303     { PTP_OC_CASIO_GET_OBJECT_INFO,                     "CASIO_GET_OBJECT_INFO" },
304     { PTP_OC_CASIO_SHUTTER,                             "CASIO_SHUTTER" },
305     { PTP_OC_CASIO_GET_STILL_HANDLES,                   "CASIO_GET_STILL_HANDLES" },
306     { PTP_OC_CASIO_STILL_RESET,                         "CASIO_STILL_RESET" },
307     { PTP_OC_CASIO_HALF_PRESS,                          "CASIO_HALF_PRESS" },
308     { PTP_OC_CASIO_HALF_RELEASE,                        "CASIO_HALF_RELEASE" },
309     { PTP_OC_CASIO_CS_PRESS,                            "CASIO_CS_PRESS" },
310     { PTP_OC_CASIO_CS_RELEASE,                          "CASIO_CS_RELEASE" },
311     { PTP_OC_CASIO_ZOOM,                                "CASIO_ZOOM" },
312     { PTP_OC_CASIO_CZ_PRESS,                            "CASIO_CZ_PRESS" },
313     { PTP_OC_CASIO_CZ_RELEASE,                          "CASIO_CZ_RELEASE" },
314     { PTP_OC_CASIO_MOVIE_START,                         "CASIO_MOVIE_START" },
315     { PTP_OC_CASIO_MOVIE_STOP,                          "CASIO_MOVIE_STOP" },
316     { PTP_OC_CASIO_MOVIE_PRESS,                         "CASIO_MOVIE_PRESS" },
317     { PTP_OC_CASIO_MOVIE_RELEASE,                       "CASIO_MOVIE_RELEASE" },
318     { PTP_OC_CASIO_GET_MOVIE_HANDLES,                   "CASIO_GET_MOVIE_HANDLES" },
319     { PTP_OC_CASIO_MOVIE_RESET,                         "CASIO_MOVIE_RESET" },
320     { PTP_OC_CASIO_GET_OBJECT,                          "CASIO_GET_OBJECT" },
321     { PTP_OC_CASIO_GET_THUMBNAIL,                       "CASIO_GET_THUMBNAIL" },
322     { 0,                                                 NULL }
323 };
324 static value_string_ext ptp_opcode_casio_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_casio_names);
325
326 static const value_string ptp_opcode_mtp_names[] = {
327     { PTP_OC_MTP_GetObjectPropsSupported,               "MTP_GetObjectPropsSupported" },
328     { PTP_OC_MTP_GetObjectPropDesc,                     "MTP_GetObjectPropDesc" },
329     { PTP_OC_MTP_GetObjectPropValue,                    "MTP_GetObjectPropValue" },
330     { PTP_OC_MTP_SetObjectPropValue,                    "MTP_SetObjectPropValue" },
331     { PTP_OC_MTP_GetObjPropList,                        "MTP_GetObjPropList" },
332     { PTP_OC_MTP_SetObjPropList,                        "MTP_SetObjPropList" },
333     { PTP_OC_MTP_GetInterdependendPropdesc,             "MTP_GetInterdependendPropdesc" },
334     { PTP_OC_MTP_SendObjectPropList,                    "MTP_SendObjectPropList" },
335     { PTP_OC_MTP_GetObjectReferences,                   "MTP_GetObjectReferences" },
336     { PTP_OC_MTP_SetObjectReferences,                   "MTP_SetObjectReferences" },
337     { PTP_OC_MTP_UpdateDeviceFirmware,                  "MTP_UpdateDeviceFirmware" },
338     { PTP_OC_MTP_Skip,                                  "MTP_Skip" },
339     { PTP_OC_MTP_WMDRMPD_GetSecureTimeChallenge,        "MTP_WMDRMPD_GetSecureTimeChallenge" },
340     { PTP_OC_MTP_WMDRMPD_GetSecureTimeResponse,         "MTP_WMDRMPD_GetSecureTimeResponse" },
341     { PTP_OC_MTP_WMDRMPD_SetLicenseResponse,            "MTP_WMDRMPD_SetLicenseResponse" },
342     { PTP_OC_MTP_WMDRMPD_GetSyncList,                   "MTP_WMDRMPD_GetSyncList" },
343     { PTP_OC_MTP_WMDRMPD_SendMeterChallengeQuery,       "MTP_WMDRMPD_SendMeterChallengeQuery" },
344     { PTP_OC_MTP_WMDRMPD_GetMeterChallenge,             "MTP_WMDRMPD_GetMeterChallenge" },
345     { PTP_OC_MTP_WMDRMPD_SetMeterResponse,              "MTP_WMDRMPD_SetMeterResponse" },
346     { PTP_OC_MTP_WMDRMPD_CleanDataStore,                "MTP_WMDRMPD_CleanDataStore" },
347     { PTP_OC_MTP_WMDRMPD_GetLicenseState,               "MTP_WMDRMPD_GetLicenseState" },
348     { PTP_OC_MTP_WMDRMPD_SendWMDRMPDCommand,            "MTP_WMDRMPD_SendWMDRMPDCommand" },
349     { PTP_OC_MTP_WMDRMPD_SendWMDRMPDRequest,            "MTP_WMDRMPD_SendWMDRMPDRequest" },
350     { PTP_OC_MTP_WMDRMPD_SendWMDRMPDAppRequest,         "MTP_WMDRMPD_SendWMDRMPDAppRequest" },
351     { PTP_OC_MTP_WMDRMPD_GetWMDRMPDAppResponse,         "MTP_WMDRMPD_GetWMDRMPDAppResponse" },
352     { PTP_OC_MTP_WMDRMPD_EnableTrustedFilesOperations,  "MTP_WMDRMPD_EnableTrustedFilesOperations" },
353     { PTP_OC_MTP_WMDRMPD_DisableTrustedFilesOperations, "MTP_WMDRMPD_DisableTrustedFilesOperations" },
354     { PTP_OC_MTP_WMDRMPD_EndTrustedAppSession,          "MTP_WMDRMPD_EndTrustedAppSession" },
355     { PTP_OC_MTP_AAVT_OpenMediaSession,                 "MTP_AAVT_OpenMediaSession" },
356     { PTP_OC_MTP_AAVT_CloseMediaSession,                "MTP_AAVT_CloseMediaSession" },
357     { PTP_OC_MTP_AAVT_GetNextDataBlock,                 "MTP_AAVT_GetNextDataBlock" },
358     { PTP_OC_MTP_AAVT_SetCurrentTimePosition,           "MTP_AAVT_SetCurrentTimePosition" },
359     { PTP_OC_MTP_WMDRMND_SendRegistrationRequest,       "MTP_WMDRMND_SendRegistrationRequest" },
360     { PTP_OC_MTP_WMDRMND_GetRegistrationResponse,       "MTP_WMDRMND_GetRegistrationResponse" },
361     { PTP_OC_MTP_WMDRMND_GetProximityChallenge,         "MTP_WMDRMND_GetProximityChallenge" },
362     { PTP_OC_MTP_WMDRMND_SendProximityResponse,         "MTP_WMDRMND_SendProximityResponse" },
363     { PTP_OC_MTP_WMDRMND_SendWMDRMNDLicenseRequest,     "MTP_WMDRMND_SendWMDRMNDLicenseRequest" },
364     { PTP_OC_MTP_WMDRMND_GetWMDRMNDLicenseResponse,     "MTP_WMDRMND_GetWMDRMNDLicenseResponse" },
365     { PTP_OC_MTP_WMPPD_ReportAddedDeletedItems,         "MTP_WMPPD_ReportAddedDeletedItems" },
366     { PTP_OC_MTP_WMPPD_ReportAcquiredItems,             "MTP_WMPPD_ReportAcquiredItems" },
367     { PTP_OC_MTP_WMPPD_PlaylistObjectPref,              "MTP_WMPPD_PlaylistObjectPref" },
368     { PTP_OC_MTP_ZUNE_GETUNDEFINED001,                  "MTP_ZUNE_GETUNDEFINED001" },
369     { PTP_OC_MTP_WPDWCN_ProcessWFCObject,               "MTP_WPDWCN_ProcessWFCObject" },
370     { 0,                                                 NULL }
371 };
372 static value_string_ext ptp_opcode_mtp_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_mtp_names);
373
374 static const value_string ptp_opcode_olympus_names[] = {
375     { PTP_OC_OLYMPUS_Capture,                           "OLYMPUS_Capture" },
376     { PTP_OC_OLYMPUS_SelfCleaning,                      "OLYMPUS_SelfCleaning" },
377     { PTP_OC_OLYMPUS_SetRGBGain,                        "OLYMPUS_SetRGBGain" },
378     { PTP_OC_OLYMPUS_SetPresetMode,                     "OLYMPUS_SetPresetMode" },
379     { PTP_OC_OLYMPUS_SetWBBiasAll,                      "OLYMPUS_SetWBBiasAll" },
380     { PTP_OC_OLYMPUS_GetCameraControlMode,              "OLYMPUS_GetCameraControlMode" },
381     { PTP_OC_OLYMPUS_SetCameraControlMode,              "OLYMPUS_SetCameraControlMode" },
382     { PTP_OC_OLYMPUS_SetWBRGBGain,                      "OLYMPUS_SetWBRGBGain" },
383     { PTP_OC_OLYMPUS_GetDeviceInfo,                     "OLYMPUS_GetDeviceInfo" },
384     { PTP_OC_OLYMPUS_Init1,                             "OLYMPUS_Init1" },
385     { PTP_OC_OLYMPUS_SetDateTime,                       "OLYMPUS_SetDateTime" },
386     { PTP_OC_OLYMPUS_GetDateTime,                       "OLYMPUS_GetDateTim" },
387     { PTP_OC_OLYMPUS_SetCameraID,                       "OLYMPUS_SetCameraID" },
388     { PTP_OC_OLYMPUS_GetCameraID,                       "OLYMPUS_GetCameraID" },
389     { 0,                                                 NULL }
390 };
391 static value_string_ext ptp_opcode_olympus_names_ext = VALUE_STRING_EXT_INIT(ptp_opcode_olympus_names);
392
393 static const value_string ptp_respcode_names[] = {
394     { PTP_RC_OK,                                     "OK" },
395     { PTP_RC_GeneralError,                           "GeneralError" },
396     { PTP_RC_SessionNotOpen,                         "SessionNotOpen" },
397     { PTP_RC_InvalidTransactionID,                   "InvalidTransactionID" },
398     { PTP_RC_OperationNotSupported,                  "OperationNotSupported" },
399     { PTP_RC_ParameterNotSupported,                  "ParameterNotSupported" },
400     { PTP_RC_IncompleteTransfer,                     "IncompleteTransfer" },
401     { PTP_RC_InvalidStorageId,                       "InvalidStorageId" },
402     { PTP_RC_InvalidObjectHandle,                    "InvalidObjectHandle" },
403     { PTP_RC_DevicePropNotSupported,                 "DevicePropNotSupported" },
404     { PTP_RC_InvalidObjectFormatCode,                "InvalidObjectFormatCode" },
405     { PTP_RC_StoreFull,                              "StoreFull" },
406     { PTP_RC_StoreReadOnly,                          "StoreReadOnly" },
407     { PTP_RC_AccessDenied,                           "AccessDenied" },
408     { PTP_RC_NoThumbnailPresent,                     "NoThumbnailPresent" },
409     { PTP_RC_SelfTestFailed,                         "SelfTestFailed" },
410     { PTP_RC_PartialDeletion,                        "PartialDeletion" },
411     { PTP_RC_StoreNotAvailable,                      "StoreNotAvailable" },
412     { PTP_RC_SpecificationByFormatUnsupported,       "SpecificationByFormatUnsupported" },
413     { PTP_RC_NoValidObjectInfo,                      "NoValidObjectInfo" },
414     { PTP_RC_InvalidCodeFormat,                      "InvalidCodeFormat" },
415     { PTP_RC_UnknownVendorCode,                      "UnknownVendorCode" },
416     { PTP_RC_CaptureAlreadyTerminated,               "CaptureAlreadyTerminated" },
417     { PTP_RC_DeviceBusy,                             "DeviceBusy" },
418     { PTP_RC_InvalidParentObject,                    "InvalidParentObject" },
419     { PTP_RC_InvalidDevicePropFormat,                "InvalidDevicePropFormat" },
420     { PTP_RC_InvalidDevicePropValue,                 "InvalidDevicePropValue" },
421     { PTP_RC_InvalidParameter,                       "InvalidParameter" },
422     { PTP_RC_SessionAlreadyOpened,                   "SessionAlreadyOpened" },
423     { PTP_RC_TransactionCanceled,                    "TransactionCanceled" },
424     { PTP_RC_SpecificationOfDestinationUnsupported,  "SpecificationOfDestinationUnsupported" },
425     { PTP_RC_InvalidEnumHandle,                      "InvalidEnumHandle" },
426     { PTP_RC_NoStreamEnabled,                        "NoStreamEnabled" },
427     { PTP_RC_InvalidDataSet,                         "InvalidDataSet" },
428     { 0,                                                 NULL }
429 };
430 /* static value_string_ext ptp_respcode_names_ext = VALUE_STRING_EXT_INIT(ptp_respcode_names); */
431
432 static const value_string ptp_respcode_ek_names[] = {
433     { PTP_RC_EK_FilenameRequired,                    "EK_FilenameRequired" },
434     { PTP_RC_EK_FilenameConflicts,                   "EK_FilenameConflicts" },
435     { PTP_RC_EK_FilenameInvalid,                     "EK_FilenameInvalid" },
436     { 0,                                                 NULL }
437 };
438
439 static const value_string ptp_respcode_nikon_names[] = {
440     { PTP_RC_NIKON_HardwareError,                    "NIKON_HardwareError" },
441     { PTP_RC_NIKON_OutOfFocus,                       "NIKON_OutOfFocus" },
442     { PTP_RC_NIKON_ChangeCameraModeFailed,           "NIKON_ChangeCameraModeFailed" },
443     { PTP_RC_NIKON_InvalidStatus,                    "NIKON_InvalidStatus" },
444     { PTP_RC_NIKON_SetPropertyNotSupported,          "NIKON_SetPropertyNotSupported" },
445     { PTP_RC_NIKON_WbResetError,                     "NIKON_WbResetError" },
446     { PTP_RC_NIKON_DustReferenceError,               "NIKON_DustReferenceError" },
447     { PTP_RC_NIKON_ShutterSpeedBulb,                 "NIKON_ShutterSpeedBulb" },
448     { PTP_RC_NIKON_MirrorUpSequence,                 "NIKON_MirrorUpSequence" },
449     { PTP_RC_NIKON_CameraModeNotAdjustFNumber,       "NIKON_CameraModeNotAdjustFNumber" },
450     { PTP_RC_NIKON_NotLiveView,                      "NIKON_NotLiveView" },
451     { PTP_RC_NIKON_MfDriveStepEnd,                   "NIKON_MfDriveStepEnd" },
452     { PTP_RC_NIKON_MfDriveStepInsufficiency,         "NIKON_MfDriveStepInsufficiency" },
453     { PTP_RC_NIKON_AdvancedTransferCancel,           "NIKON_AdvancedTransferCancel" },
454     { 0,                                                 NULL }
455 };
456
457 static const value_string ptp_respcode_canon_names[] = {
458     { PTP_RC_CANON_UNKNOWN_COMMAND,                  "CANON_UNKNOWN_COMMAND" },
459     { PTP_RC_CANON_OPERATION_REFUSED,                "CANON_OPERATION_REFUSED" },
460     { PTP_RC_CANON_LENS_COVER,                       "CANON_LENS_COVER" },
461     { PTP_RC_CANON_BATTERY_LOW,                      "CANON_BATTERY_LOW" },
462     { PTP_RC_CANON_NOT_READY,                        "CANON_NOT_READY" },
463     { PTP_RC_CANON_A009,                             "CANON_A009" },
464     { 0,                                                 NULL }
465 };
466
467 static const value_string ptp_respcode_mtp_names[] = {
468     { PTP_RC_MTP_Undefined,                          "MTP_Undefined" },
469     { PTP_RC_MTP_Invalid_ObjectPropCode,             "MTP_Invalid_ObjectPropCode" },
470     { PTP_RC_MTP_Invalid_ObjectProp_Format,          "MTP_Invalid_ObjectProp_Format" },
471     { PTP_RC_MTP_Invalid_ObjectProp_Value,           "MTP_Invalid_ObjectProp_Value" },
472     { PTP_RC_MTP_Invalid_ObjectReference,            "MTP_Invalid_ObjectReference" },
473     { PTP_RC_MTP_Invalid_Dataset,                    "MTP_Invalid_Dataset" },
474     { PTP_RC_MTP_Specification_By_Group_Unsupported, "MTP_Specification_By_Group_Unsupported" },
475     { PTP_RC_MTP_Specification_By_Depth_Unsupported, "MTP_Specification_By_Depth_Unsupported" },
476     { PTP_RC_MTP_Object_Too_Large,                   "MTP_Object_Too_Large" },
477     { PTP_RC_MTP_ObjectProp_Not_Supported,           "MTP_ObjectProp_Not_Supported" },
478     { PTP_RC_MTP_Invalid_Media_Session_ID,           "MTP_Invalid_Media_Session_ID" },
479     { PTP_RC_MTP_Media_Session_Limit_Reached,        "MTP_Media_Session_Limit_Reached" },
480     { PTP_RC_MTP_No_More_Data,                       "MTP_No_More_Data" },
481     { PTP_RC_MTP_Invalid_WFC_Syntax,                 "MTP_Invalid_WFC_Syntax" },
482     { PTP_RC_MTP_WFC_Version_Not_Supported,          "MTP_WFC_Version_Not_Supported" },
483     { 0,                                                 NULL }
484 };
485
486 /* String Names of packet types [3] & [4] */
487 /* PTP/IP definitions */
488  /* enums reformatted from [4] */
489 typedef enum {
490     PTPIP_INVALID                = 0,
491     PTPIP_INIT_COMMAND_REQUEST   = 1,
492     PTPIP_INIT_COMMAND_ACK       = 2,
493     PTPIP_INIT_EVENT_REQUEST     = 3,
494     PTPIP_INIT_EVENT_ACK         = 4,
495     PTPIP_INIT_FAIL              = 5,
496     PTPIP_CMD_REQUEST            = 6,  /* possibly Operation request in [1] 2.3.6 agrees with [3]   */
497     PTPIP_CMD_RESPONSE           = 7,  /* possibly Operation response in [1] 2.3.7  agrees with [3] */
498     PTPIP_EVENT                  = 8,
499     PTPIP_START_DATA_PACKET      = 9,
500     PTPIP_DATA_PACKET            = 10,
501     PTPIP_CANCEL_TRANSACTION     = 11,
502     PTPIP_END_DATA_PACKET        = 12,
503     PTPIP_PING                   = 13, /* possibly Probe Request in [1] 2.3.13  */
504     PTPIP_PONG                   = 14  /* possibly Probe Response in [1] 2.3.14 */
505 } ptpip_pktType;
506
507 /* Unless otherwise stated, names are based on info in [3] */
508 static const value_string ptpip_pktType_names[] = {
509     { PTPIP_INVALID,                 "Invalid" },
510     { PTPIP_INIT_COMMAND_REQUEST,    "Init Command Request Packet" },
511     { PTPIP_INIT_COMMAND_ACK,        "Init Command ACK Packet" },
512     { PTPIP_INIT_EVENT_REQUEST,      "Init Event Request Packet" },
513     { PTPIP_INIT_EVENT_ACK,          "Init Event Ack Packet"},
514     { PTPIP_INIT_FAIL,               "Init Fail Packet"},
515     { PTPIP_CMD_REQUEST,             "Operation Request Packet"},  /* string based on [1]  */
516     { PTPIP_CMD_RESPONSE,            "Operation Response Packet"}, /* string based on [1] */
517     { PTPIP_EVENT,                   "Event Packet"},
518     { PTPIP_START_DATA_PACKET,       "Start Data Packet"},
519     { PTPIP_DATA_PACKET,             "Data Packet"},
520     { PTPIP_CANCEL_TRANSACTION,      "Cancel Packet"},
521     { PTPIP_END_DATA_PACKET,         "End Data Packet"},
522     { PTPIP_PING,                    "Probe Request Packet"},      /* string based on [1]  */
523     { PTPIP_PONG,                    "Probe Response Packet"},     /* string based on [1] */
524     { 0,                             NULL }
525 };
526 static value_string_ext ptpip_pktType_names_ext = VALUE_STRING_EXT_INIT(ptpip_pktType_names);
527
528
529 /**
530  * Primary method to dissect a PTP/IP packet. When a subtype is encounter,
531  * the method will call a subdissector.
532  */
533 static
534 int dissect_ptpIP (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
535 {
536     proto_item *item_ptr;
537     proto_tree *ptp_tree;
538     guint16     offset = 0;
539
540     guint32 pktType;
541
542     /* Check that there's enough data */
543     if ( tvb_captured_length_remaining(tvb, offset) < 8 )    /* ptp-photo smallest packet size is 8 */
544         return (0);
545
546     col_set_str(pinfo->cinfo,COL_PROTOCOL, "PTP/IP");
547
548     col_set_str(
549         pinfo->cinfo,
550         COL_INFO,
551         "Picture Transfer Protocol");
552
553     item_ptr = proto_tree_add_protocol_format(tree, proto_ptpIP, tvb, offset,
554          -1, "Picture Transfer Protocol");
555
556     /* creating the tree */
557     ptp_tree = proto_item_add_subtree(item_ptr, ett_ptpIP);
558     /* [1] Defines first 2 fields as length and packet type. (Section 2.3)
559      * Also note: the standard lists all multibyte values in PTP-IP as little-endian
560      */
561
562     /* note: len field size included in total len */
563     proto_tree_add_item(ptp_tree, hf_ptpIP_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
564     offset += 4;
565     /* @todo:maybe add some length verification checks to see if len advertised matches actual len */
566
567     pktType = tvb_get_letohl(tvb, offset);
568     proto_tree_add_item(ptp_tree, hf_ptpIP_pktType, tvb, offset, 4, ENC_LITTLE_ENDIAN);
569     offset += 4;
570     switch (pktType) {
571         case PTPIP_INIT_COMMAND_REQUEST:
572             dissect_ptpIP_init_command_request(tvb, pinfo, ptp_tree, &offset);
573             break;
574         case PTPIP_INIT_COMMAND_ACK:
575             dissect_ptpIP_init_command_ack(tvb, pinfo, ptp_tree, &offset);
576             break;
577         case PTPIP_INIT_EVENT_REQUEST:
578             dissect_ptpIP_init_event_request(tvb, pinfo, ptp_tree, &offset);
579             break;
580         case PTPIP_INIT_EVENT_ACK:
581             dissect_ptpIP_init_event_ack(pinfo);
582             break;
583         case PTPIP_CMD_REQUEST:
584             dissect_ptpIP_operation_request(tvb, pinfo, ptp_tree, &offset);
585             break;
586         case PTPIP_CMD_RESPONSE:
587             dissect_ptpIP_operation_response(tvb, pinfo, ptp_tree, &offset);
588             break;
589         case PTPIP_EVENT:
590             dissect_ptpIP_event(tvb, pinfo, ptp_tree, &offset);
591             break;
592         case PTPIP_START_DATA_PACKET:
593             dissect_ptpIP_start_data(tvb, pinfo, ptp_tree, &offset);
594             break;
595         case PTPIP_DATA_PACKET:
596             dissect_ptpIP_data(tvb, pinfo, ptp_tree, &offset);
597             break;
598         case PTPIP_END_DATA_PACKET:
599             dissect_ptpIP_end_data(tvb, pinfo, ptp_tree, &offset);
600             break;
601         default:
602             break;
603     }
604
605     return (offset);
606 }
607
608 /**
609  * Method to dissect the Init Command Request sent by the Initiator
610  * in the connection. This packet is defined by [1] Section 2.3.1
611  */
612 void dissect_ptpIP_init_command_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
613 {
614     *offset += 0;
615
616     col_set_str(
617         pinfo->cinfo,
618         COL_INFO,
619         "Init Command Request");
620
621     dissect_ptpIP_guid(tvb, pinfo, tree, offset);
622
623     /* grabbing the name */
624     dissect_ptpIP_unicode_name(tvb, pinfo, tree, offset);
625
626     /* grabbing protocol version
627      * Note: [3] does not list this in the packet field. . [1] 2.3.1 states it's the last 4
628      * bytes of the packet.
629     */
630     dissect_ptpIP_protocol_version(tvb, tree, offset);
631     return;
632 }
633
634 /**
635  * Method to dissect the Init Command Ack sent by the Responder
636  * in the connection. This packet is defined by [1] Section 2.3.2
637  */
638 void dissect_ptpIP_init_command_ack(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
639 {
640     guint32 connectionNumber;
641
642     col_set_str(
643         pinfo->cinfo,
644         COL_INFO,
645         "Init Command Ack");
646
647     /* Grabbing the Connection Number */
648     connectionNumber = tvb_get_letohl(tvb, *offset);
649     proto_tree_add_item(tree, hf_ptpIP_connectionNumber, tvb, *offset, 4,ENC_LITTLE_ENDIAN);
650     col_append_fstr(
651         pinfo->cinfo,
652         COL_INFO,
653         " Connection #:%u",
654         connectionNumber);
655     *offset += 4;
656
657     dissect_ptpIP_guid(tvb, pinfo, tree, offset);
658
659     /* grabbing name */
660     dissect_ptpIP_unicode_name(tvb,pinfo, tree, offset);
661
662     /* grabbing protocol version. Note: like in the Init Command Request, [3] doesn't mention
663      * this field, but [1] Section 2.3.2 does.
664      */
665
666
667     dissect_ptpIP_protocol_version(tvb, tree, offset);
668 }
669
670 /**
671  * Dissects the Init Event Request packet specified in [1] Section 2.3.3.
672  * Standard states that the packet only has 1 field.
673  */
674 void dissect_ptpIP_init_event_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
675 {
676     guint32 connectionNumber;
677
678     col_set_str(
679         pinfo->cinfo,
680         COL_INFO,
681         "Init Event Request");
682
683     /* Grabbing the Connection Number */
684     connectionNumber = tvb_get_letohl(tvb, *offset);
685     proto_tree_add_item(tree, hf_ptpIP_connectionNumber, tvb, *offset, 4,ENC_LITTLE_ENDIAN);
686     col_append_fstr(
687         pinfo->cinfo,
688         COL_INFO,
689         " Connection #:%u",
690         connectionNumber);
691     *offset += 4;
692 }
693
694 /**
695  * Dissects the Init Event Ack packet specified in [1] Section 2.3.4
696  */
697 void dissect_ptpIP_init_event_ack(packet_info *pinfo)
698 {
699     col_set_str(
700         pinfo->cinfo,
701         COL_INFO,
702         "Init Event Ack");
703
704     /* packet has no payload. */
705 }
706
707 /**
708  * Dissects the Operation Request Packet specified in [1] Section 2.3.6
709  * Note: many of the fields in this packet move from PTP/IP to PTP layer
710  * of the stack.  Work will need to be done in future iterations to make this
711  * compatible with PTP/USB.
712  */
713 void dissect_ptpIP_operation_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
714 {
715     guint16 opcode;
716     guint16 transactionID_offset = *offset; /* need to save this to output transaction id in pinfo */
717
718     col_set_str(
719         pinfo->cinfo,
720         COL_INFO,
721         "Operation Request Packet ");
722
723     proto_tree_add_item(tree,hf_ptpIP_dataPhaseInfo, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
724     *offset += 4;
725
726     opcode = tvb_get_letohs(tvb, *offset);
727     if (opcode & PTP_OC_EXTENSION_MASK)
728     {
729         if (pref_vendor == PTP_VENDOR_UNKNOWN)
730         {
731             proto_tree_add_item(tree, hf_ptp_vendor_opCode, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
732         }
733         else
734         {
735             value_string_ext* vendor_values = NULL;
736
737             switch(pref_vendor)
738             {
739             case PTP_VENDOR_EASTMAN_KODAK:
740                 vendor_values = &ptp_opcode_ek_names_ext;
741                 break;
742             case PTP_VENDOR_CANON:
743                 vendor_values = &ptp_opcode_canon_names_ext;
744                 break;
745             case PTP_VENDOR_NIKON:
746                 vendor_values = &ptp_opcode_nikon_names_ext;
747                 break;
748             case PTP_VENDOR_CASIO:
749                 vendor_values = &ptp_opcode_casio_names_ext;
750                 break;
751             case PTP_VENDOR_MTP:
752                 vendor_values = &ptp_opcode_mtp_names_ext;
753                 break;
754             case PTP_VENDOR_OLYMPUS:
755                 vendor_values = &ptp_opcode_olympus_names_ext;
756                 break;
757             default:
758                 DISSECTOR_ASSERT(FALSE);
759                 break;
760             }
761
762             proto_tree_add_uint_format_value(tree, hf_ptp_vendor_opCode, tvb, *offset, 2, opcode, "%s (0x%04x)",
763                         val_to_str_ext_const(opcode, vendor_values, "Unknown"), opcode);
764         }
765     }
766     else
767     {
768         proto_tree_add_item(tree, hf_ptp_opCode, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
769     }
770     *offset += 2;
771
772     transactionID_offset = *offset; /* we'll dissect the transactionID later because
773                                        opcode handling erases the column */
774     *offset += 4;
775
776     /* carving out the parameters. [1] 2.3.6 states there can be at most 5. Params are defined in [2] 10.1 & 10.4 */
777     switch (opcode)
778     {
779         case PTP_OC_GetDeviceInfo:
780             /* [1] 10.5.1 */
781             col_set_str(
782                 pinfo->cinfo,
783                 COL_INFO,
784                 "GetDeviceInfo");
785             /* No parameters */
786             break;
787         case PTP_OC_OpenSession:
788             dissect_ptp_opCode_openSession(tvb, pinfo, tree, offset);
789             break;
790         case PTP_OC_CloseSession:
791             /* [1] 10.5.3 */
792             col_set_str(
793                 pinfo->cinfo,
794                 COL_INFO,
795                 "CloseSession");
796             /* No parameters */
797             break;
798         case PTP_OC_GetStorageIDs:
799             /* [2]  10.5.4 */
800             col_set_str(
801                 pinfo->cinfo,
802                 COL_INFO,
803                 "GetStorageIDs");
804             /* states data is a storage array. Needs eventual investigation. */
805             break;
806         default:
807             break;
808     }
809     dissect_ptp_transactionID(tvb, pinfo, tree, &transactionID_offset);
810 }
811
812 /**
813  * Dissects the Operation Response Packet specified in [1] Section 2.3.7
814  * Note: many of the fields in this packet move from PTP/IP to PTP layer
815  * of the stack.  Work will need to be done in future iterations to make this
816  * compatible with PTP/USB.
817  */
818 void dissect_ptpIP_operation_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
819 {
820     guint16 resp;
821
822     col_set_str(
823         pinfo->cinfo,
824         COL_INFO,
825         "Operation Response Packet ");
826
827     resp = tvb_get_letohs(tvb, *offset);
828     if (resp & PTP_OC_EXTENSION_MASK)
829     {
830         const value_string* vendor_values = NULL;
831         switch(pref_vendor)
832         {
833         case PTP_VENDOR_EASTMAN_KODAK:
834             vendor_values = ptp_respcode_ek_names;
835             break;
836         case PTP_VENDOR_CANON:
837             vendor_values = ptp_respcode_canon_names;
838             break;
839         case PTP_VENDOR_NIKON:
840             vendor_values = ptp_respcode_nikon_names;
841             break;
842         case PTP_VENDOR_MTP:
843             vendor_values = ptp_respcode_mtp_names;
844             break;
845         case PTP_VENDOR_UNKNOWN:
846         case PTP_VENDOR_CASIO:
847         case PTP_VENDOR_OLYMPUS:
848         default:
849             vendor_values = ptp_respcode_names;
850             break;
851         }
852
853         proto_tree_add_uint_format_value(tree, hf_ptp_vendor_opCode, tvb, *offset, 2, resp, "%s (0x%04x)",
854                         val_to_str_const(resp, vendor_values, "Unknown"), resp);
855     }
856     else
857     {
858         proto_tree_add_item(tree, hf_ptp_respCode, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
859     }
860     *offset += 2;
861
862     dissect_ptp_transactionID(tvb, pinfo, tree, offset);
863
864 }
865
866 /**
867  * Dissects the Event Packet specified in [1] Section 2.3.8
868  * Note: many of the fields in this packet move from PTP/IP to PTP layer
869  * of the stack.  Work will need to be done in future iterations to make this
870  * compatible with PTP/USB.
871  */
872 void dissect_ptpIP_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
873 {
874     col_set_str(
875         pinfo->cinfo,
876         COL_INFO,
877         "Event Packet ");
878
879     proto_tree_add_item(tree, hf_ptp_eventCode, tvb, *offset, 2, ENC_LITTLE_ENDIAN);
880     *offset += 2;
881
882     dissect_ptp_transactionID(tvb, pinfo, tree, offset);
883 }
884
885 /**
886  * Dissects the Event Packet specified in [1] Section 2.3.9
887  * Note: many of the fields in this packet move from PTP/IP to PTP layer
888  * of the stack.  Work will need to be done in future iterations to make this
889  * compatible with PTP/USB.
890  */
891 void dissect_ptpIP_start_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
892 {
893     guint64 dataLen;
894
895     col_set_str(
896         pinfo->cinfo,
897         COL_INFO,
898         "Start Data Packet ");
899
900     dissect_ptp_transactionID(tvb, pinfo, tree, offset);
901
902
903     dataLen = tvb_get_letoh64(tvb, *offset);
904     proto_tree_add_item(tree, hf_ptp_totalDataLength, tvb, *offset, 8, ENC_LITTLE_ENDIAN);
905     *offset += 8;
906     if (dataLen == G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF)) /* [1] specifies in 2.3.9 if total data len
907                                                               is this value then len is unknown */
908     {
909         col_append_str(
910             pinfo->cinfo,
911             COL_INFO,
912             " Data Length Unknown");
913     }
914 }
915
916 void dissect_ptpIP_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
917 {
918
919     col_set_str(
920         pinfo->cinfo,
921         COL_INFO,
922         "Data Packet ");
923
924     dissect_ptp_transactionID(tvb, pinfo, tree, offset);
925
926 }
927
928 /**
929  * Dissects the End Data specified in [1] Section 2.3.11
930  * Note: many of the fields in this packet move from PTP/IP to PTP layer
931  * of the stack.  Work will need to be done in future iterations to make this
932  * compatible with PTP/USB.
933  */
934 void dissect_ptpIP_end_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
935 {
936
937     col_set_str(
938         pinfo->cinfo,
939         COL_INFO,
940         "End Data Packet ");
941
942     dissect_ptp_transactionID(tvb, pinfo, tree, offset);
943 }
944
945 /**
946  * Dissects the Opcode Open Session as defined by [2] 10.5.2
947  */
948 void dissect_ptp_opCode_openSession(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
949 {
950     col_set_str(
951         pinfo->cinfo,
952         COL_INFO,
953         "OpenSession");
954
955     proto_tree_add_item(tree, hf_ptp_opCode_param_sessionID, tvb, *offset, 4 , ENC_LITTLE_ENDIAN);
956     *offset += 4;
957 }
958
959 /**
960  * The transaction ID is defined  in [2]  9.3.1
961  * and used in multiple message types. This method handles
962  * parsing the field and adding the value to the info
963  * column.
964  *
965  */
966 void dissect_ptp_transactionID(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
967 {
968     guint32 transactionID;
969
970     transactionID = tvb_get_letohl(tvb, *offset);
971     proto_tree_add_item(tree, hf_ptp_transactionID, tvb, *offset, 4, ENC_LITTLE_ENDIAN);
972     *offset += 4;
973     col_append_fstr(
974         pinfo->cinfo,
975         COL_INFO,
976         " Transaction ID: %d",
977         transactionID);
978 }
979
980 /**
981  * This method handles dissecting the Unicode name that is
982  * specificed in multiple packets.
983  */
984 void dissect_ptpIP_unicode_name(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
985 {
986     const guint8 *name;
987     gint          nameLen;
988
989     nameLen = tvb_unicode_strsize(tvb, *offset);
990     proto_tree_add_item_ret_string(tree, hf_ptpIP_name, tvb, *offset, nameLen, ENC_UTF_16|ENC_LITTLE_ENDIAN, wmem_packet_scope(), &name);
991     *offset += nameLen;
992     col_append_fstr(pinfo->cinfo, COL_INFO, " Name: %s", name);
993 }
994
995 /** Method dissects the protocol version from the packets.
996  * Additional note, section 3 of [1] defines the Binary Protocol version
997  * as 0x00010000 == 1.0 where the Most significant bits are the major version and the least
998  * significant bits are the minor version.
999  */
1000 void dissect_ptpIP_protocol_version(tvbuff_t *tvb, proto_tree *tree, guint16 *offset)
1001 {
1002
1003     guint8  version[30];
1004     guint32 protoVersion;
1005     guint16 majorVersion, minorVersion;
1006
1007     protoVersion = tvb_get_letohl(tvb, *offset);
1008     /* logic to format version */
1009     minorVersion = protoVersion & 0xFFFF;
1010     majorVersion = (protoVersion & 0xFFFF0000) >>16;
1011     g_snprintf(version, sizeof(version), "%u.%u", majorVersion, minorVersion);
1012     proto_tree_add_string(tree, hf_ptpIP_version, tvb, *offset, 4, version);
1013     *offset += 4;
1014 }
1015
1016 /* Grabbing the GUID */
1017 void dissect_ptpIP_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 *offset)
1018 {
1019     guint8 *guid;
1020
1021     guid = tvb_bytes_to_str(wmem_packet_scope(), tvb, *offset, PTPIP_GUID_SIZE);
1022     proto_tree_add_item(tree, hf_ptpIP_guid, tvb, *offset, PTPIP_GUID_SIZE, ENC_NA);
1023     *offset += PTPIP_GUID_SIZE;
1024     col_append_fstr(
1025         pinfo->cinfo,
1026         COL_INFO,
1027         " GUID: %s",
1028         guid);
1029 }
1030
1031 void proto_register_ptpip( void )
1032 {
1033     static hf_register_info hf[] = {
1034         /* PTP/IP layer */
1035         { &hf_ptpIP_len, {
1036             "Length", "ptpip.len", FT_UINT32, BASE_DEC,
1037             NULL, 0, NULL, HFILL }},
1038         { &hf_ptpIP_pktType, {
1039             "Packet Type", "ptpip.pktType", FT_UINT32, BASE_HEX | BASE_EXT_STRING,
1040             &ptpip_pktType_names_ext, 0, NULL, HFILL }},
1041         { &hf_ptpIP_guid, {
1042             "GUID", "ptpip.guid", FT_BYTES, BASE_NONE,
1043             NULL, 0, NULL, HFILL }},
1044         { &hf_ptpIP_name, {
1045             "Host Name", "ptpip.name", FT_STRINGZ, STR_UNICODE,
1046             NULL, 0, NULL, HFILL }},
1047         { &hf_ptpIP_version, {
1048             "Version", "ptpip.version", FT_STRING, BASE_NONE,
1049             NULL, 0, NULL, HFILL }},
1050         { &hf_ptpIP_connectionNumber, {
1051             "Connection Number", "ptpip.connection", FT_UINT32, BASE_DEC,
1052             NULL, 0, NULL, HFILL }},
1053         { &hf_ptpIP_dataPhaseInfo, {
1054             "Data Phase Info", "ptpip.phaseinfo", FT_UINT32, BASE_HEX,
1055             NULL, 0, NULL, HFILL }},
1056         /* PTP layer */
1057              /* leaving names with "ptpip" to try and prevent namespace issues. probably changing later. */
1058         { &hf_ptp_opCode, {
1059             "Operation Code", "ptpip.opcode", FT_UINT16, BASE_HEX|BASE_EXT_STRING,
1060             &ptp_opcode_names_ext, 0, NULL, HFILL }},
1061         { &hf_ptp_vendor_opCode, {
1062             "Operation Code", "ptpip.opcode", FT_UINT16, BASE_HEX,
1063             NULL, 0, NULL, HFILL }},
1064         { &hf_ptp_respCode, {
1065             "Response Code", "ptpip.respcode", FT_UINT16, BASE_HEX,
1066             VALS(ptp_respcode_names), 0, NULL, HFILL }},
1067         { &hf_ptp_vendor_respCode, {
1068             "Response Code", "ptpip.respcode", FT_UINT16, BASE_HEX,
1069             NULL, 0, NULL, HFILL }},
1070         { &hf_ptp_eventCode, {
1071             "Event Code", "ptpip.eventcode", FT_UINT16, BASE_HEX,
1072             NULL, 0, NULL, HFILL }},
1073         { &hf_ptp_transactionID, {
1074             "Transaction ID", "ptpip.transactionID", FT_UINT32, BASE_HEX,
1075             NULL, 0, NULL, HFILL }},
1076         { &hf_ptp_totalDataLength, {
1077             "Total Data Length", "ptpip.datalen", FT_UINT64, BASE_DEC_HEX,
1078             NULL, 0, NULL, HFILL }},
1079         { &hf_ptp_opCode_param_sessionID, {
1080             "Session ID", "ptpip.opcode.param.sessionid", FT_UINT32, BASE_HEX,
1081             NULL, 0, NULL, HFILL }},
1082
1083     };
1084     static gint *ett[] = {
1085         &ett_ptpIP,
1086         &ett_ptpIP_hdr
1087     };
1088
1089     module_t *ptpIP_module;
1090
1091     proto_ptpIP = proto_register_protocol("Picture Transfer Protocol Over IP", "PTP/IP", "ptpip");
1092
1093     proto_register_field_array(proto_ptpIP, hf, array_length(hf));
1094     proto_register_subtree_array(ett, array_length(ett));
1095
1096     ptpIP_module = prefs_register_protocol(proto_ptpIP, NULL);
1097
1098     prefs_register_enum_preference(ptpIP_module, "vendor",
1099             "Camera vendor",
1100             "Properly translates vendor specific opcodes",
1101             &pref_vendor, pref_hsp_role, FALSE);
1102
1103 }
1104
1105 void proto_reg_handoff_ptpIP( void ) {
1106
1107     dissector_handle_t ptpIP_handle;
1108
1109     /*  Use create_dissector_handle() to indicate that dissect_ptpIP()
1110     *  returns the number of bytes it dissected (or 0 if it thinks the packet
1111     *  does not belong to PROTONAME).
1112     */
1113
1114     ptpIP_handle = create_dissector_handle(dissect_ptpIP, proto_ptpIP);
1115     dissector_add_uint_with_preference("tcp.port", PTPIP_PORT, ptpIP_handle);
1116 }
1117
1118 /*
1119  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1120  *
1121  * Local variables:
1122  * c-basic-offset: 4
1123  * tab-width: 8
1124  * indent-tabs-mode: nil
1125  * End:
1126  *
1127  * vi: set shiftwidth=4 tabstop=8 expandtab:
1128  * :indentSize=4:tabSize=8:noTabs=true:
1129  */