Enable Lua tcp tap userdata.
[obnox/wireshark/wip.git] / epan / dissectors / packet-rdm.c
1 /* packet-rdm.c
2  * RDM (Remote Device Management) packet disassembly.
3  *
4  * $Id$
5  *
6  * This dissector is written by
7  *
8  *  Shaun Jackman <sjackman@gmail.com>
9  *  Copyright 2006 Pathway Connectivity
10  *
11  *  Erwin Rol <erwin@erwinrol.com>
12  *  Copyright 2003 Erwin Rol
13  *
14  *  Wireshark - Network traffic analyzer
15  *  Gerald Combs <gerald@wireshark.org>
16  *  Copyright 1999 Gerald Combs
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  * 
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 51 Franklin Street, Fifth Floor
31  * Boston, MA  02110-1301, USA.
32  */
33 /* 
34  * ANSI E1.20-2006, Entertainment Technology
35  * Remote Device Management over USITT DMX512, describes a method of
36  * bi-directional communications over a USITT DMX512/1990 data link
37  * between an entertainment lighting controller and one or more
38  * remotely controlled lighting devices. The protocol also is intended
39  * to work with the ANSI E1.11-2004 control protocol. It allows
40  * discovery of devices on a DMX512/E1.11 network and the remote
41  * setting of DMX starting addresses, as well as status and fault
42  * reporting back to the control console.
43  */
44
45 #ifdef HAVE_CONFIG_H
46 # include "config.h"
47 #endif
48
49 #include <glib.h>
50 #include <epan/packet.h>
51
52 static int proto_rdm = -1;
53
54 static int hf_rdm_start_code = -1;
55 static int hf_rdm_sub_start_code = -1;
56 static int hf_rdm_message_length = -1;
57 static int hf_rdm_dest_uid = -1;
58 static int hf_rdm_src_uid = -1;
59 static int hf_rdm_transaction_number = -1;
60 static int hf_rdm_response_type = -1;
61 static int hf_rdm_message_count = -1;
62 static int hf_rdm_sub_device = -1;
63 static int hf_rdm_command_class = -1;
64 static int hf_rdm_parameter_id = -1;
65 static int hf_rdm_parameter_data_length = -1;
66 static int hf_rdm_parameter_data = -1;
67 static int hf_rdm_intron = -1;
68 static int hf_rdm_checksum = -1;
69 static int hf_rdm_trailer = -1;
70
71 static int ett_rdm = -1;
72
73 static guint16
74 rdm_checksum(tvbuff_t *tvb, unsigned length)
75 {
76         guint16 sum = 0;
77         unsigned i;
78         for (i = 0; i < length; i++)
79                 sum += tvb_get_guint8(tvb, i);
80         return sum;
81 }
82
83 static void
84 dissect_rdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
85 {
86         if (check_col(pinfo->cinfo, COL_PROTOCOL))
87                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDM");
88         if (check_col(pinfo->cinfo, COL_INFO))
89                 col_clear(pinfo->cinfo, COL_INFO);
90
91         if (tree != NULL) {
92                 unsigned message_length, checksum, checksum_shouldbe,
93                                 parameter_data_length, offset = 0;
94                 proto_item *item;
95
96                 proto_tree *ti = proto_tree_add_item(tree, proto_rdm, tvb,
97                                 offset, -1, FALSE);
98                 proto_tree *rdm_tree = proto_item_add_subtree(ti, ett_rdm);
99
100                 proto_tree_add_item(rdm_tree, hf_rdm_start_code, tvb,
101                                 offset, 1, FALSE);
102                 offset++;
103
104                 proto_tree_add_item(rdm_tree, hf_rdm_sub_start_code, tvb,
105                                 offset, 1, FALSE);
106                 offset++;
107
108                 message_length = tvb_get_guint8(tvb, offset);
109                 proto_tree_add_item(rdm_tree, hf_rdm_message_length, tvb,
110                                 offset, 1, FALSE);
111                 offset++;
112
113                 proto_tree_add_item(rdm_tree, hf_rdm_dest_uid, tvb,
114                                 offset, 6, FALSE);
115                 offset += 6;
116
117                 proto_tree_add_item(rdm_tree, hf_rdm_src_uid, tvb,
118                                 offset, 6, FALSE);
119                 offset += 6;
120
121                 proto_tree_add_item(rdm_tree, hf_rdm_transaction_number, tvb,
122                                 offset, 1, FALSE);
123                 offset++;
124
125                 proto_tree_add_item(rdm_tree, hf_rdm_response_type, tvb,
126                                 offset, 1, FALSE);
127                 offset++;
128
129                 proto_tree_add_item(rdm_tree, hf_rdm_message_count, tvb,
130                                 offset, 1, FALSE);
131                 offset++;
132
133                 proto_tree_add_item(rdm_tree, hf_rdm_sub_device, tvb,
134                                 offset, 2, FALSE);
135                 offset += 2;
136
137                 proto_tree_add_item(rdm_tree, hf_rdm_command_class, tvb,
138                                 offset, 1, FALSE);
139                 offset++;
140
141                 proto_tree_add_item(rdm_tree, hf_rdm_parameter_id, tvb,
142                                 offset, 2, FALSE);
143                 offset += 2;
144
145                 parameter_data_length = tvb_get_guint8(tvb, offset);
146                 proto_tree_add_item(rdm_tree, hf_rdm_parameter_data_length, tvb,
147                                 offset, 1, FALSE);
148                 offset++;
149
150                 if (parameter_data_length > 0) {
151                         proto_tree_add_item(rdm_tree, hf_rdm_parameter_data, tvb,
152                                         offset, parameter_data_length, FALSE);
153                         offset += parameter_data_length;
154                 }
155
156                 if (offset < message_length) {
157                         proto_tree_add_item(rdm_tree, hf_rdm_intron, tvb,
158                                         offset, message_length - offset, FALSE);
159                         offset = message_length;
160                 }
161
162                 checksum_shouldbe = rdm_checksum(tvb, offset);
163                 checksum = tvb_get_ntohs(tvb, offset);
164                 item = proto_tree_add_item(rdm_tree, hf_rdm_checksum, tvb,
165                                 offset, 2, FALSE);
166                 proto_item_append_text(item, checksum == checksum_shouldbe
167                                 ? " [correct]"
168                                 : " [incorrect, should be 0x%04x]", checksum_shouldbe);
169                 offset += 2;
170
171                 if (offset < tvb_length(tvb))
172                         proto_tree_add_item(rdm_tree, hf_rdm_trailer, tvb,
173                                         offset, -1, FALSE);
174         }
175 }
176
177 void
178 proto_register_rdm(void)
179 {
180         static hf_register_info hf[] = {
181                 { &hf_rdm_start_code,
182                         { "Start code", "rdm.sc",
183                                 FT_UINT8, BASE_HEX, NULL, 0x0,
184                                 NULL, HFILL }},
185
186                 { &hf_rdm_sub_start_code,
187                         { "Sub-start code", "rdm.ssc",
188                                 FT_UINT8, BASE_HEX, NULL, 0x0,
189                                 NULL, HFILL }},
190
191                 { &hf_rdm_message_length,
192                         { "Message length", "rdm.len",
193                                 FT_UINT8, BASE_DEC, NULL, 0x0,
194                                 NULL, HFILL }},
195
196                 { &hf_rdm_dest_uid,
197                         { "Destination UID", "rdm.dst",
198                                 FT_BYTES, BASE_HEX, NULL, 0x0,
199                                 NULL, HFILL }},
200
201                 { &hf_rdm_src_uid,
202                         { "Source UID", "rdm.src",
203                                 FT_BYTES, BASE_HEX, NULL, 0x0,
204                                 NULL, HFILL }},
205
206                 { &hf_rdm_transaction_number,
207                         { "Transaction number", "rdm.tn",
208                                 FT_UINT8, BASE_DEC, NULL, 0x0,
209                                 NULL, HFILL }},
210
211                 { &hf_rdm_response_type,
212                         { "Response type", "rdm.rt",
213                                 FT_UINT8, BASE_HEX, NULL, 0x0,
214                                 NULL, HFILL }},
215
216                 { &hf_rdm_message_count,
217                         { "Message count", "rdm.mc",
218                                 FT_UINT8, BASE_DEC, NULL, 0x0,
219                                 NULL, HFILL }},
220
221                 { &hf_rdm_sub_device,
222                         { "Sub-device", "rdm.sd",
223                                 FT_UINT16, BASE_DEC, NULL, 0x0,
224                                 NULL, HFILL }},
225
226                 { &hf_rdm_command_class,
227                         { "Command class", "rdm.cc",
228                                 FT_UINT8, BASE_HEX, NULL, 0x0,
229                                 NULL, HFILL }},
230
231                 { &hf_rdm_parameter_id,
232                         { "Parameter ID", "rdm.pid",
233                                 FT_UINT16, BASE_HEX, NULL, 0x0,
234                                 NULL, HFILL }},
235
236                 { &hf_rdm_parameter_data_length,
237                         { "Parameter data length", "rdm.pdl",
238                                 FT_UINT8, BASE_DEC, NULL, 0x0,
239                                 NULL, HFILL }},
240
241                 { &hf_rdm_parameter_data,
242                         { "Parameter data", "rdm.pd",
243                                 FT_BYTES, BASE_HEX, NULL, 0x0,
244                                 NULL, HFILL }},
245
246                 { &hf_rdm_intron,
247                         { "Intron", "rdm.intron",
248                                 FT_BYTES, BASE_HEX, NULL, 0x0,
249                                 NULL, HFILL }},
250
251                 { &hf_rdm_checksum,
252                         { "Checksum", "rdm.checksum",
253                                 FT_UINT16, BASE_HEX, NULL, 0x0,
254                                 NULL, HFILL }},
255
256                 { &hf_rdm_trailer,
257                         { "Trailer", "rdm.trailer",
258                                 FT_BYTES, BASE_HEX, NULL, 0x0,
259                                 NULL, HFILL }}
260         };
261
262         static gint *ett[] = {
263                 &ett_rdm
264         };
265
266         proto_rdm = proto_register_protocol("Remote Device Management",
267                         "RDM", "rdm");
268         proto_register_field_array(proto_rdm, hf, array_length(hf));
269         proto_register_subtree_array(ett, array_length(ett));
270         register_dissector("rdm", dissect_rdm, proto_rdm);
271 }
272
273 void
274 proto_reg_handoff_rdm(void)
275 {
276 }