From Didier Gautheron:
[obnox/wireshark/wip.git] / epan / dissectors / packet-artnet.c
1 /* packet-artnet.c
2  * Routines for Art-Net packet disassembly
3  *
4  * $Id$
5  *
6  * Copyright (c) 2003 by Erwin Rol <erwin@erwinrol.com>
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1999 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 /* Include files */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <time.h>
37 #include <string.h>
38 #include <epan/packet.h>
39 #include <epan/addr_resolv.h>
40 #include <epan/prefs.h>
41 #include <epan/strutil.h>
42
43 /*
44  * See
45  *
46  *      http://www.artisticlicence.com/art-net.pdf
47  */
48
49 /* Define udp_port for ArtNET */
50
51 #define UDP_PORT_ARTNET 0x1936
52
53 #define ARTNET_HEADER_LENGTH                 10
54 #define ARTNET_POLL_LENGTH                   4
55 #define ARTNET_POLL_REPLY_LENGTH             197
56 #define ARTNET_POLL_REPLY_PORT_INFO_LENGTH   22
57 #define ARTNET_POLL_REPLY_PORT_TYPES_LENGTH  4
58 #define ARTNET_POLL_REPLY_GOOD_INPUT_LENGTH  4
59 #define ARTNET_POLL_REPLY_GOOD_OUTPUT_LENGTH 4
60 #define ARTNET_POLL_REPLY_SWIN_LENGTH        4
61 #define ARTNET_POLL_REPLY_SWOUT_LENGTH       4
62 #define ARTNET_ADDRESS_LENGTH                97
63 #define ARTNET_ADDRESS_SWIN_LENGTH           4
64 #define ARTNET_ADDRESS_SWOUT_LENGTH          4
65 #define ARTNET_OUTPUT_LENGTH                 1
66 #define ARTNET_INPUT_LENGTH                  10
67 #define ARTNET_INPUT_INPUT_LENGTH            4
68 #define ARTNET_FIRMWARE_MASTER_LENGTH        1035
69 #define ARTNET_FIRMWARE_REPLY_LENGTH         26
70 #define ARTNET_VIDEO_SETUP_LENGTH            74
71 #define ARTNET_VIDEO_PALETTE_LENGTH          55
72 #define ARTNET_VIDEO_DATA_LENGTH             8
73
74
75 #define ARTNET_OP_POLL               0x2000
76 #define ARTNET_OP_POLL_REPLY         0x2100
77 #define ARTNET_OP_POLL_SERVER_REPLY  0x2200
78 #define ARTNET_OP_OUTPUT             0x5000
79 #define ARTNET_OP_ADDRESS            0x6000
80 #define ARTNET_OP_INPUT              0x7000
81 #define ARTNET_OP_VIDEO_SETUP        0xa010
82 #define ARTNET_OP_VIDEO_PALETTE      0xa020
83 #define ARTNET_OP_VIDEO_DATA         0xa040
84
85 #define ARTNET_OP_TOD_REQUEST        0x8000
86 #define ARTNET_OP_TOD_DATA           0x8100
87 #define ARTNET_OP_TOD_CONTROL        0x8200
88 #define ARTNET_OP_RDM                0x8300
89
90 #define ARTNET_OP_MAC_MASTER         0xf000
91 #define ARTNET_OP_MAC_SLAVE          0xf100
92 #define ARTNET_OP_FIRMWARE_MASTER    0xf200
93 #define ARTNET_OP_FIRMWARE_REPLY     0xf300
94
95 #define ARTNET_OP_IP_PROG            0xf800
96 #define ARTNET_OP_IP_PROG_REPLY      0xf900
97
98 static const value_string artnet_opcode_vals[] = {
99   { ARTNET_OP_POLL,              "ArtPoll packet" },
100   { ARTNET_OP_POLL_REPLY,        "ArtPollReply packet" },
101   { ARTNET_OP_POLL_SERVER_REPLY, "ArtPollServerReply packet" },
102   { ARTNET_OP_OUTPUT,            "ArtDMX data packet" },
103   { ARTNET_OP_ADDRESS,           "ArtAddress packet" },
104   { ARTNET_OP_INPUT,             "ArtInput packet" },
105   { ARTNET_OP_VIDEO_SETUP,       "ArtVideoSetup packet" },
106   { ARTNET_OP_VIDEO_PALETTE,     "ArtVideoPalette packet" },
107   { ARTNET_OP_VIDEO_DATA,        "ArtVideoData packet" },
108   { ARTNET_OP_TOD_REQUEST,       "ArtTodRequest packet" },
109   { ARTNET_OP_TOD_DATA,          "ArtTodData packet" },
110   { ARTNET_OP_TOD_CONTROL,       "ArtTodControl packet" },
111   { ARTNET_OP_RDM,               "ArtRdm packet" },
112   { ARTNET_OP_MAC_MASTER,        "ArtMacMaster packet" },
113   { ARTNET_OP_MAC_SLAVE,         "ArtMacSlave packet" },
114   { ARTNET_OP_FIRMWARE_MASTER,   "ArtFirmwareMaster packet" },
115   { ARTNET_OP_FIRMWARE_REPLY,    "ArtFirmwareReply packet" },
116   { ARTNET_OP_IP_PROG,           "ArtIpProg packet" },
117   { ARTNET_OP_IP_PROG_REPLY,     "ArtIpProgReply packet" },
118   { 0,                           NULL }
119 };
120
121 static const value_string artnet_oem_code_vals[] = {
122   { 0x0000, "Artistic Licence:DMX-Hub:4x DMX in,4x DMX out" },
123   { 0x0001, "ADB:Netgate:4x DMX in,4x DMX out" },
124   { 0x0002, "MA Lighting:TBA:4x DMX in,4x DMX out" },
125   { 0x0003, "Artistic Licence:Ether-Lynx:2x DMX in,4x DMX out" },
126   { 0x0004, "LewLight:Capture v2:TBA" },
127   { 0x0005, "High End:TBA:TBA" },
128   { 0x0006, "Avolites:TBA:TBA" },
129   { 0x0010, "Artistic Licence:Down-Lynx:2x DMX out. Wall Panel." },
130   { 0x0011, "Artistic Licence:Up-Lynx:2x DMX in. Wall Panel" },
131   { 0x0014, "Artistic Licence:Net-Lynx O/P:2x DMX out. Boxed Product" },
132   { 0x0015, "Artistic Licence:Net-Lynx I/P:2x DMX in. Boxed Product" },
133   { 0x0030, "Doug Fleenor Design:TBA:2x DMX out" },
134   { 0x0031, "Doug Fleenor Design:TBA:2x DMX in" },
135   { 0x0050, "Goddard Design:DMX-Link (tm) O/P:2x DMX out" },
136   { 0x0051, "Goddard Design:DMX-Link (tm) I/P:2x DMX in" },
137   { 0x0070, "ADB:Net-Port O/P:2x DMX out" },
138   { 0x0071, "ADB:Net-Port I/P:2x DMX in" },
139   { 0x0072, "ADB:Reserved:" },
140   { 0x0073, "ADB:Reserved:" },
141   { 0x0074, "ADB:Reserved:" },
142   { 0x0075, "ADB:Reserved:" },
143   { 0x0076, "ADB:Reserved:" },
144   { 0x0077, "ADB:Reserved:" },
145   { 0x0078, "ADB:Reserved:" },
146   { 0x0079, "ADB:Reserved:" },
147   { 0x007A, "ADB:Reserved:" },
148   { 0x007B, "ADB:Reserved:" },
149   { 0x007C, "ADB:Reserved:" },
150   { 0x007D, "ADB:Reserved:" },
151   { 0x007E, "ADB:Reserved:" },
152   { 0x007F, "ADB:Reserved:" },
153   { 0x008C, "Zero 88:TBA:2x DMX out" },
154   { 0x008D, "Zero 88:TBA:2x DMX in" },
155   { 0x008E, "Flying Pig:TBA:2x DMX out" },
156   { 0x008F, "Flying Pig:TBA:2x DMX in" },
157   { 0x0090, "ELC:ELC 2:2x DMX out" },
158   { 0x0091, "ELC:ELC 4:4x DMX in. 4x DMX out" },
159   { 0x0180, "Martin:Maxxyz:4x DMX in. 4x DMX out" },
160   { 0x0190, "Enttec:Reserved:" },
161   { 0x0191, "Enttec:Reserved:" },
162   { 0x0192, "Enttec:Reserved:" },
163   { 0x0193, "Enttec:Reserved:" },
164   { 0x0194, "Enttec:Reserved:" },
165   { 0x0195, "Enttec:Reserved:" },
166   { 0x0196, "Enttec:Reserved:" },
167   { 0x0197, "Enttec:Reserved:" },
168   { 0x0198, "Enttec:Reserved:" },
169   { 0x0199, "Enttec:Reserved:" },
170   { 0x019A, "Enttec:Reserved:" },
171   { 0x019B, "Enttec:Reserved:" },
172   { 0x019C, "Enttec:Reserved:" },
173   { 0x019D, "Enttec:Reserved:" },
174   { 0x019E, "Enttec:Reserved:" },
175   { 0x019F, "Enttec:Reserved:" },
176   { 0x8000, "ADB:Netgate XT:Video output and trigger inputs" },
177   { 0x8001, "Artistic Licence:Net-Patch:TBA" },
178   { 0x8002, "Artistic Licence:DMX-Hub XT:Video output and trigger inputs" },
179   { 0x8003, "Artistic Licence:No-Worries XT:Real time data record - playback" },
180   { 0,      NULL }
181 };
182
183 static const value_string artnet_esta_man_vals[] = {
184   { 0x414C, "Artistic Licence" },
185   { 0,      NULL }
186 };
187
188 #define ARTNET_AC_NONE           0x00
189 #define ARTNET_AC_CANCEL_MERGE   0x01
190 #define ARTNET_AC_LED_NORMAL     0x02
191 #define ARTNET_AC_LED_MUTE       0x03
192 #define ARTNET_AC_LED_LOCATE     0x04
193 #define ARTNET_AC_RESET_RX_FLAGS 0x05
194 #define ARTNET_AC_MERGE_LTP0     0x10
195 #define ARTNET_AC_MERGE_LTP1     0x11
196 #define ARTNET_AC_MERGE_LTP2     0x12
197 #define ARTNET_AC_MERGE_LTP3     0x13
198 #define ARTNET_AC_MERGE_HTP0     0x50
199 #define ARTNET_AC_MERGE_HTP1     0x51
200 #define ARTNET_AC_MERGE_HTP2     0x52
201 #define ARTNET_AC_MERGE_HTP3     0x53
202 #define ARTNET_AC_CLEAR_OP0      0x90
203 #define ARTNET_AC_CLEAR_OP1      0x91
204 #define ARTNET_AC_CLEAR_OP2      0x92
205 #define ARTNET_AC_CLEAR_OP3      0x93
206
207 static const value_string artnet_address_command_vals[] = {
208   { ARTNET_AC_NONE,            "No Action" },
209   { ARTNET_AC_CANCEL_MERGE,    "Cancel merge" },
210   { ARTNET_AC_LED_NORMAL,      "LED Normal" },
211   { ARTNET_AC_LED_MUTE,        "LED Mute" },
212   { ARTNET_AC_LED_LOCATE,      "LED Locate" },
213   { ARTNET_AC_RESET_RX_FLAGS,  "Reset SIP text" },
214   { ARTNET_AC_MERGE_LTP0,      "DMX port 1 LTP" },
215   { ARTNET_AC_MERGE_LTP1,      "DMX port 2 LTP" },
216   { ARTNET_AC_MERGE_LTP2,      "DXM port 3 LTP" },
217   { ARTNET_AC_MERGE_LTP3,      "DMX port 4 LTP" },
218   { ARTNET_AC_MERGE_HTP0,      "DMX port 1 HTP" },
219   { ARTNET_AC_MERGE_HTP1,      "DMX port 2 HTP" },
220   { ARTNET_AC_MERGE_HTP2,      "DXM port 3 HTP" },
221   { ARTNET_AC_MERGE_HTP3,      "DMX port 4 HTP" },
222   { ARTNET_AC_CLEAR_OP0,       "Clear DMX port 1" },
223   { ARTNET_AC_CLEAR_OP1,       "Clear DMX port 2" },
224   { ARTNET_AC_CLEAR_OP2,       "Clear DXM port 3" },
225   { ARTNET_AC_CLEAR_OP3,       "Clear DMX port 4" },
226   { 0,                         NULL }
227 };
228
229 #define ARTNET_FT_FIRM_FIRST 0x00
230 #define ARTNET_FT_FIRM_CONT  0x01
231 #define ARTNET_FT_FIRM_LAST  0x02
232 #define ARTNET_FT_UBEA_FIRST 0x03
233 #define ARTNET_FT_UBEA_CONT  0x04
234 #define ARTNET_FT_UBEA_LAST  0x05
235
236 static const value_string artnet_firmware_master_type_vals[] = {
237   { ARTNET_FT_FIRM_FIRST, "FirmFirst" },
238   { ARTNET_FT_FIRM_CONT,  "FirmCont" },
239   { ARTNET_FT_FIRM_LAST,  "FirmLast" },
240   { ARTNET_FT_UBEA_FIRST, "UbeaFirst" },
241   { ARTNET_FT_UBEA_CONT,  "UbeaCont" },
242   { ARTNET_FT_UBEA_LAST,  "UbeaLast" },
243   { 0,                    NULL }
244 };
245
246 #define ARTNET_FRT_FIRM_BLOCK_GOOD 0x00
247 #define ARTNET_FRT_FIRM_ALL_GOOD   0x01
248 #define ARTNET_FRT_FIRM_FAIL       0xff
249
250 static const value_string artnet_firmware_reply_type_vals[] = {
251   { ARTNET_FRT_FIRM_BLOCK_GOOD, "FirmBlockGood" },
252   { ARTNET_FRT_FIRM_ALL_GOOD,   "FirmAllGood" },
253   { ARTNET_FRT_FIRM_FAIL,       "FirmFail" },
254   { 0,                          NULL }
255 };
256
257 static const value_string artnet_tod_request_command_vals[] = {
258   { 0,                   NULL }
259 };
260
261 #define ARTNET_TDC_TOD_FULL    0x00
262 #define ARTNET_TDC_TOD_NAK     0xFF
263
264 static const value_string artnet_tod_data_command_vals[] = {
265   { ARTNET_TDC_TOD_FULL,    "TodFull" },
266   { ARTNET_TDC_TOD_NAK,     "TodNak" },
267   { 0,                      NULL }
268 };
269
270 #define ARTNET_TCC_ATC_NONE  0x00
271 #define ARTNET_TCC_ATC_FLUSH 0x01
272
273 static const value_string artnet_tod_control_command_vals[] = {
274   { ARTNET_TCC_ATC_NONE,  "AtcNone" },
275   { ARTNET_TCC_ATC_FLUSH, "AtcFlush" },
276   { 0,                    NULL }
277 };
278
279 #define ARTNET_RC_AR_PROCESS  0x00
280
281 static const value_string artnet_rdm_command_vals[] = {
282   { ARTNET_RC_AR_PROCESS,  "ArProcess" },
283   { 0,                     NULL }
284 };
285
286 void proto_reg_handoff_artnet(void);
287
288 /* Define the artnet proto */
289 static int proto_artnet = -1;
290
291
292 /* general */
293 static int hf_artnet_filler = -1;
294 static int hf_artnet_spare = -1;
295
296 /* Header */
297 static int hf_artnet_header = -1;
298 static int hf_artnet_header_id = -1;
299 static int hf_artnet_header_opcode = -1;
300 static int hf_artnet_header_protver = -1;
301
302 /* ArtPoll */
303 static int hf_artnet_poll = -1;
304 static int hf_artnet_poll_talktome = -1;
305 static int hf_artnet_poll_talktome_reply_dest = -1;
306 static int hf_artnet_poll_talktome_reply_type = -1;
307 static int hf_artnet_poll_talktome_unused = -1;
308
309 /* ArtPollReply */
310 static int hf_artnet_poll_reply = -1;
311 static int hf_artnet_poll_reply_ip_address = -1;
312 static int hf_artnet_poll_reply_port_nr = -1;
313 static int hf_artnet_poll_reply_versinfo = -1;
314 static int hf_artnet_poll_reply_subswitch = -1;
315 static int hf_artnet_poll_reply_oem = -1;
316 static int hf_artnet_poll_reply_ubea_version = -1;
317 static int hf_artnet_poll_reply_status = -1;
318 static int hf_artnet_poll_reply_esta_man = -1;
319 static int hf_artnet_poll_reply_short_name = -1;
320 static int hf_artnet_poll_reply_long_name = -1;
321 static int hf_artnet_poll_reply_node_report = -1;
322 static int hf_artnet_poll_reply_port_info = -1;
323 static int hf_artnet_poll_reply_num_ports = -1;
324 static int hf_artnet_poll_reply_port_types = -1;
325 static int hf_artnet_poll_reply_port_types_1 = -1;
326 static int hf_artnet_poll_reply_port_types_2 = -1;
327 static int hf_artnet_poll_reply_port_types_3 = -1;
328 static int hf_artnet_poll_reply_port_types_4 = -1;
329 static int hf_artnet_poll_reply_good_input = -1;
330 static int hf_artnet_poll_reply_good_input_1 = -1;
331 static int hf_artnet_poll_reply_good_input_2 = -1;
332 static int hf_artnet_poll_reply_good_input_3 = -1;
333 static int hf_artnet_poll_reply_good_input_4 = -1;
334 static int hf_artnet_poll_reply_good_output = -1;
335 static int hf_artnet_poll_reply_good_output_1 = -1;
336 static int hf_artnet_poll_reply_good_output_2 = -1;
337 static int hf_artnet_poll_reply_good_output_3 = -1;
338 static int hf_artnet_poll_reply_good_output_4 = -1;
339 static int hf_artnet_poll_reply_swin = -1;
340 static int hf_artnet_poll_reply_swin_1 = -1;
341 static int hf_artnet_poll_reply_swin_2 = -1;
342 static int hf_artnet_poll_reply_swin_3 = -1;
343 static int hf_artnet_poll_reply_swin_4 = -1;
344 static int hf_artnet_poll_reply_swout = -1;
345 static int hf_artnet_poll_reply_swout_1 = -1;
346 static int hf_artnet_poll_reply_swout_2 = -1;
347 static int hf_artnet_poll_reply_swout_3 = -1;
348 static int hf_artnet_poll_reply_swout_4 = -1;
349 static int hf_artnet_poll_reply_swvideo = -1;
350 static int hf_artnet_poll_reply_swmacro = -1;
351 static int hf_artnet_poll_reply_swremote = -1;
352 static int hf_artnet_poll_reply_mac = -1;
353
354 /* ArtOutput */
355 static int hf_artnet_output = -1;
356 static int hf_artnet_output_sequence = -1;
357 static int hf_artnet_output_physical = -1;
358 static int hf_artnet_output_universe = -1;
359 static int hf_artnet_output_length = -1;
360 static int hf_artnet_output_data = -1;
361 static int hf_artnet_output_dmx_data = -1;
362 static int hf_artnet_output_data_filter = -1;
363
364 /* ArtAddress */
365 static int hf_artnet_address = -1;
366 static int hf_artnet_address_short_name = -1;
367 static int hf_artnet_address_long_name = -1;
368 static int hf_artnet_address_swin = -1;
369 static int hf_artnet_address_swin_1 = -1;
370 static int hf_artnet_address_swin_2 = -1;
371 static int hf_artnet_address_swin_3 = -1;
372 static int hf_artnet_address_swin_4 = -1;
373 static int hf_artnet_address_swout = -1;
374 static int hf_artnet_address_swout_1 = -1;
375 static int hf_artnet_address_swout_2 = -1;
376 static int hf_artnet_address_swout_3 = -1;
377 static int hf_artnet_address_swout_4 = -1;
378 static int hf_artnet_address_subswitch = -1;
379 static int hf_artnet_address_swvideo = -1;
380 static int hf_artnet_address_command = -1;
381
382 /* ArtInput */
383 static int hf_artnet_input = -1;
384 static int hf_artnet_input_num_ports = -1;
385 static int hf_artnet_input_input = -1;
386 static int hf_artnet_input_input_1 = -1;
387 static int hf_artnet_input_input_2 = -1;
388 static int hf_artnet_input_input_3 = -1;
389 static int hf_artnet_input_input_4 = -1;
390
391 /* ArtFirmwareMaster */
392 static int hf_artnet_firmware_master = -1;
393 static int hf_artnet_firmware_master_type = -1;
394 static int hf_artnet_firmware_master_block_id = -1;
395 static int hf_artnet_firmware_master_length = -1;
396 static int hf_artnet_firmware_master_data = -1;
397
398 /* ArtFirmwareReply */
399 static int hf_artnet_firmware_reply = -1;
400 static int hf_artnet_firmware_reply_type = -1;
401
402 /* ArtVideoSetup */
403 static int hf_artnet_video_setup = -1;
404 static int hf_artnet_video_setup_control = -1;
405 static int hf_artnet_video_setup_font_height = -1;
406 static int hf_artnet_video_setup_first_font = -1;
407 static int hf_artnet_video_setup_last_font = -1;
408 static int hf_artnet_video_setup_win_font_name = -1;
409 static int hf_artnet_video_setup_font_data = -1;
410
411 /* ArtVideoPalette */
412 static int hf_artnet_video_palette = -1;
413 static int hf_artnet_video_palette_colour_red = -1;
414 static int hf_artnet_video_palette_colour_green = -1;
415 static int hf_artnet_video_palette_colour_blue = -1;
416
417 /* ArtVideoData */
418 static int hf_artnet_video_data = -1;
419 static int hf_artnet_video_data_pos_x = -1;
420 static int hf_artnet_video_data_pos_y = -1;
421 static int hf_artnet_video_data_len_x = -1;
422 static int hf_artnet_video_data_len_y = -1;
423 static int hf_artnet_video_data_data = -1;
424
425 /* ArtPollServerReply */
426 static int hf_artnet_poll_server_reply = -1;
427
428 /* ArtTodRequest */
429 static int hf_artnet_tod_request = -1;
430 static int hf_artnet_tod_request_command = -1;
431 static int hf_artnet_tod_request_ad_count = -1;
432 static int hf_artnet_tod_request_address = -1;
433
434 /* ArtTodData */
435 static int hf_artnet_tod_data = -1;
436 static int hf_artnet_tod_data_port = -1;
437 static int hf_artnet_tod_data_command_response = -1;
438 static int hf_artnet_tod_data_address = -1;
439 static int hf_artnet_tod_data_uid_total = -1;
440 static int hf_artnet_tod_data_block_count = -1;
441 static int hf_artnet_tod_data_uid_count = -1;
442 static int hf_artnet_tod_data_tod = -1;
443
444 /* ArtTodControl */
445 static int hf_artnet_tod_control = -1;
446 static int hf_artnet_tod_control_command = -1;
447 static int hf_artnet_tod_control_address = -1;
448
449 /* ArtRdm */
450 static int hf_artnet_rdm = -1;
451 static int hf_artnet_rdm_command = -1;
452 static int hf_artnet_rdm_address = -1;
453
454 /* ArtIpProg */
455 static int hf_artnet_ip_prog = -1;
456 static int hf_artnet_ip_prog_command = -1;
457 static int hf_artnet_ip_prog_command_prog_port = -1;
458 static int hf_artnet_ip_prog_command_prog_sm = -1;
459 static int hf_artnet_ip_prog_command_prog_ip = -1;
460 static int hf_artnet_ip_prog_command_reset = -1;
461 static int hf_artnet_ip_prog_command_unused = -1;
462 static int hf_artnet_ip_prog_command_prog_enable = -1;
463 static int hf_artnet_ip_prog_ip = -1;
464 static int hf_artnet_ip_prog_sm = -1;
465 static int hf_artnet_ip_prog_port = -1;
466
467 /* ArtIpProgReply */
468 static int hf_artnet_ip_prog_reply = -1;
469 static int hf_artnet_ip_prog_reply_ip = -1;
470 static int hf_artnet_ip_prog_reply_sm = -1;
471 static int hf_artnet_ip_prog_reply_port = -1;
472
473 /* Define the tree for artnet */
474 static int ett_artnet = -1;
475
476 /*
477  * Here are the global variables associated with the preferences
478  * for artnet
479  */
480
481 static guint global_udp_port_artnet = UDP_PORT_ARTNET;
482 static gint global_disp_chan_val_type = 0;
483 static gint global_disp_col_count = 16;
484 static gint global_disp_chan_nr_type = 0;
485
486 /* A static handle for the rdm dissector */
487 static dissector_handle_t rdm_handle;
488
489 static guint
490 dissect_artnet_poll(tvbuff_t *tvb, guint offset, proto_tree *tree)
491 {
492   guint8 talktome;
493   proto_tree *flags_tree, *flags_item;
494
495   talktome = tvb_get_guint8(tvb, offset);
496   flags_item = proto_tree_add_uint(tree, hf_artnet_poll_talktome, tvb,
497                                    offset, 1, talktome);
498
499   flags_tree=proto_item_add_subtree(flags_item, ett_artnet);
500   proto_tree_add_item(flags_tree, hf_artnet_poll_talktome_reply_dest, tvb, offset, 1, FALSE);
501   proto_tree_add_item(flags_tree, hf_artnet_poll_talktome_reply_type, tvb, offset, 1, FALSE);
502   proto_tree_add_item(flags_tree, hf_artnet_poll_talktome_unused, tvb, offset, 1, FALSE);
503
504   offset += 1;
505
506   proto_tree_add_item(tree, hf_artnet_filler, tvb,
507                       offset, 1, FALSE);
508   offset += 1;
509
510   return offset;
511 }
512
513 static guint
514 dissect_artnet_poll_reply(tvbuff_t *tvb, guint offset, proto_tree *tree)
515 {
516   proto_tree *hi,*si,*ti;
517   guint8 swin,swout,swvideo,swmacro,swremote;
518   guint8 port_types,good_input,good_output;
519   guint16 num_ports;
520
521   proto_tree_add_item(tree, hf_artnet_poll_reply_ip_address, tvb,
522                       offset, 4, FALSE);
523   offset += 4;
524
525   proto_tree_add_item(tree, hf_artnet_poll_reply_port_nr, tvb,
526                       offset, 2, TRUE);
527   offset += 2;
528
529   proto_tree_add_item(tree, hf_artnet_poll_reply_versinfo, tvb,
530                       offset, 2, FALSE);
531   offset += 2;
532
533   proto_tree_add_item(tree, hf_artnet_poll_reply_subswitch, tvb,
534                       offset, 2, FALSE);
535   offset += 2;
536
537   proto_tree_add_item(tree, hf_artnet_poll_reply_oem, tvb,
538                       offset, 2, FALSE);
539   offset += 2;
540
541   proto_tree_add_item(tree, hf_artnet_poll_reply_ubea_version, tvb,
542                       offset, 1, FALSE);
543   offset += 1;
544
545   proto_tree_add_item(tree, hf_artnet_poll_reply_status, tvb,
546                       offset, 1, FALSE);
547   offset += 1;
548
549   proto_tree_add_item(tree, hf_artnet_poll_reply_esta_man, tvb,
550                       offset, 2, TRUE);
551   offset += 2;
552
553   proto_tree_add_item(tree, hf_artnet_poll_reply_short_name,
554                       tvb, offset, 18, FALSE);
555   offset += 18;
556
557   proto_tree_add_item(tree, hf_artnet_poll_reply_long_name,
558                       tvb, offset, 64, FALSE);
559   offset += 64;
560
561   proto_tree_add_item(tree, hf_artnet_poll_reply_node_report,
562                       tvb, offset, 64, FALSE);
563   offset += 64;
564
565
566   hi = proto_tree_add_item(tree,
567                            hf_artnet_poll_reply_port_info,
568                            tvb,
569                            offset,
570                            ARTNET_POLL_REPLY_PORT_INFO_LENGTH,
571                            FALSE);
572
573   si = proto_item_add_subtree(hi, ett_artnet);
574
575   num_ports = tvb_get_ntohs(tvb, offset);
576   proto_tree_add_uint(si, hf_artnet_poll_reply_num_ports, tvb,
577                       offset, 2, num_ports);
578   offset += 2;
579
580   hi = proto_tree_add_item(si,
581                            hf_artnet_poll_reply_port_types,
582                            tvb,
583                            offset,
584                            ARTNET_POLL_REPLY_PORT_TYPES_LENGTH,
585                            FALSE);
586
587   ti = proto_item_add_subtree(hi, ett_artnet);
588
589   port_types = tvb_get_guint8(tvb, offset);
590   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_1, tvb,
591                       offset, 1, port_types);
592   offset += 1;
593
594   port_types = tvb_get_guint8(tvb, offset);
595   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_2, tvb,
596                       offset, 1, port_types);
597   offset += 1;
598
599   port_types = tvb_get_guint8(tvb, offset);
600   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_3, tvb,
601                       offset, 1, port_types);
602   offset += 1;
603
604   port_types = tvb_get_guint8(tvb, offset);
605   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_4, tvb,
606                       offset, 1, port_types);
607   offset += 1;
608
609   hi = proto_tree_add_item(si,
610                            hf_artnet_poll_reply_good_input,
611                            tvb,
612                            offset,
613                            ARTNET_POLL_REPLY_GOOD_INPUT_LENGTH,
614                            FALSE);
615
616   ti = proto_item_add_subtree(hi, ett_artnet);
617
618   good_input = tvb_get_guint8(tvb, offset);
619   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_1, tvb,
620                       offset, 1, good_input);
621   offset += 1;
622
623   good_input = tvb_get_guint8(tvb, offset);
624   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_2, tvb,
625                       offset, 1, good_input);
626   offset += 1;
627
628   good_input = tvb_get_guint8(tvb, offset);
629   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_3, tvb,
630                       offset, 1, good_input);
631   offset += 1;
632
633   good_input = tvb_get_guint8(tvb, offset);
634   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_4, tvb,
635                       offset, 1, good_input);
636   offset += 1;
637
638   hi = proto_tree_add_item(si,
639                            hf_artnet_poll_reply_good_output,
640                            tvb,
641                            offset,
642                            ARTNET_POLL_REPLY_GOOD_OUTPUT_LENGTH,
643                            FALSE);
644
645   ti = proto_item_add_subtree(hi, ett_artnet);
646
647   good_output = tvb_get_guint8(tvb, offset);
648   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_1, tvb,
649                       offset, 1, good_output);
650   offset += 1;
651
652   good_output = tvb_get_guint8(tvb, offset);
653   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_2, tvb,
654                       offset, 1, good_output);
655   offset += 1;
656
657   good_output = tvb_get_guint8(tvb, offset);
658   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_3, tvb,
659                       offset, 1, good_output);
660   offset += 1;
661
662   good_output = tvb_get_guint8(tvb, offset);
663   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_4, tvb,
664                       offset, 1, good_output);
665   offset += 1;
666
667   hi = proto_tree_add_item(si,
668                            hf_artnet_poll_reply_swin,
669                            tvb,
670                            offset,
671                            ARTNET_POLL_REPLY_SWIN_LENGTH,
672                            FALSE);
673
674   ti = proto_item_add_subtree(hi, ett_artnet);
675
676   swin = tvb_get_guint8(tvb, offset);
677   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_1, tvb,
678                       offset, 1, swin);
679   offset += 1;
680
681   swin = tvb_get_guint8(tvb, offset);
682   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_2, tvb,
683                       offset, 1, swin);
684   offset += 1;
685
686   swin = tvb_get_guint8(tvb, offset);
687   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_3, tvb,
688                       offset, 1, swin);
689   offset += 1;
690
691   swin = tvb_get_guint8(tvb, offset);
692   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_4, tvb,
693                       offset, 1, swin);
694   offset += 1;
695
696   hi = proto_tree_add_item(si,
697                            hf_artnet_poll_reply_swout,
698                            tvb,
699                            offset,
700                            ARTNET_POLL_REPLY_SWOUT_LENGTH,
701                            FALSE);
702
703   ti = proto_item_add_subtree(hi, ett_artnet);
704
705   swout = tvb_get_guint8(tvb, offset);
706   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_1, tvb,
707                       offset, 1, swout);
708   offset += 1;
709
710   swout = tvb_get_guint8(tvb, offset);
711   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_2, tvb,
712                       offset, 1, swout);
713   offset += 1;
714
715   swout = tvb_get_guint8(tvb, offset);
716   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_3, tvb,
717                       offset, 1, swout);
718   offset += 1;
719
720   swout = tvb_get_guint8(tvb, offset);
721   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_4, tvb,
722                       offset, 1, swout);
723   offset += 1;
724
725   swvideo = tvb_get_guint8(tvb, offset);
726   proto_tree_add_uint(tree, hf_artnet_poll_reply_swvideo, tvb,
727                       offset, 1, swvideo);
728   offset += 1;
729
730   swmacro = tvb_get_guint8(tvb, offset);
731   proto_tree_add_uint(tree, hf_artnet_poll_reply_swmacro, tvb,
732                       offset, 1, swmacro);
733   offset += 1;
734
735   swremote = tvb_get_guint8(tvb, offset);
736   proto_tree_add_uint(tree, hf_artnet_poll_reply_swremote, tvb,
737                       offset, 1, swremote);
738   offset += 1;
739
740   proto_tree_add_item(tree, hf_artnet_spare, tvb,
741                       offset, 4, FALSE);
742   offset += 4;
743
744   proto_tree_add_item(tree, hf_artnet_poll_reply_mac,
745                         tvb, offset, 6, FALSE);
746
747   offset += 6;
748
749   return offset;
750 }
751
752 static guint
753 dissect_artnet_output(tvbuff_t *tvb, guint offset, proto_tree *tree)
754 {
755   proto_tree *hi,*si;
756   proto_item *item;
757   guint16 length,r,c,row_count;
758   guint8 v;
759   static char string[255];
760   char* ptr;
761   const char* chan_format[] = {
762     "%2u ",
763     "%02x ",
764     "%3u "
765   };
766   const char* string_format[] = {
767     "%03x: %s",
768     "%3u: %s"
769   };
770
771   proto_tree_add_item(tree, hf_artnet_output_sequence, tvb,
772                       offset, 1, FALSE);
773   offset += 1;
774
775   proto_tree_add_item(tree, hf_artnet_output_physical, tvb,
776                       offset, 1, FALSE);
777   offset += 1;
778
779   proto_tree_add_item(tree, hf_artnet_output_universe, tvb,
780                       offset, 2, TRUE);
781   offset += 2;
782
783   length = tvb_get_ntohs(tvb, offset);
784   proto_tree_add_uint(tree, hf_artnet_output_length, tvb,
785                       offset, 2, length);
786   offset += 2;
787
788   hi = proto_tree_add_item(tree,
789                            hf_artnet_output_data,
790                            tvb,
791                            offset,
792                            length,
793                            FALSE);
794                                                                                                                 
795   si = proto_item_add_subtree(hi, ett_artnet);
796
797   row_count = (length/global_disp_col_count) + ((length%global_disp_col_count) == 0 ? 0 : 1);
798   ptr = string;
799   /* XX: In theory the g_snprintf statements below could store '\0' bytes off the end of the     */
800   /*     'string' buffer'. This is so since g_snprint returns the number of characters which     */
801   /*     "would have been written" (whether or not there was room) and since ptr is always       */
802   /*     incremented by this amount. In practice the string buffer is large enough such that the */
803   /*     string buffer size is not exceeded even with the maximum number of columns which might  */
804   /*     be displayed.                                                                           */
805   /*     ToDo: consider recoding slightly ...                                                    */
806   for (r=0; r < row_count;r++) {
807     for (c=0;(c < global_disp_col_count) && (((r*global_disp_col_count)+c) < length);c++) {
808       if ((c % (global_disp_col_count/2)) == 0) {
809         ptr += g_snprintf(ptr, (gulong)(sizeof string - strlen(string)), " ");
810       }
811
812       v = tvb_get_guint8(tvb, (offset+(r*global_disp_col_count)+c));
813       if (global_disp_chan_val_type == 0) {
814         v = (v * 100) / 255;
815         if (v == 100) {
816           ptr += g_snprintf(ptr, (gulong)(sizeof string - strlen(string)), "FL ");
817         } else {
818           ptr += g_snprintf(ptr, (gulong)(sizeof string - strlen(string)), chan_format[global_disp_chan_val_type], v);
819         }
820       } else {
821         ptr += g_snprintf(ptr, (gulong)(sizeof string - strlen(string)), chan_format[global_disp_chan_val_type], v);
822       }
823     }
824     
825     proto_tree_add_none_format(si,hf_artnet_output_dmx_data, tvb,
826                                offset+(r*global_disp_col_count), c, 
827                                string_format[global_disp_chan_nr_type], (r*global_disp_col_count)+1, string);
828     ptr = string;
829   }
830
831   /* Add the real type hidden */
832   item = proto_tree_add_item(si, hf_artnet_output_data_filter, tvb,
833                       offset, length, FALSE );
834   PROTO_ITEM_SET_HIDDEN(item);
835   offset += length;
836
837   return offset;
838 }
839
840 static guint
841 dissect_artnet_address(tvbuff_t *tvb, guint offset, proto_tree *tree) {
842   proto_tree *hi,*si,*ti;
843   guint8 swin,swout,swvideo,command;
844
845   proto_tree_add_item(tree, hf_artnet_filler, tvb,
846                       offset, 2, FALSE);
847   offset += 2;
848
849   proto_tree_add_item(tree, hf_artnet_address_short_name,
850                       tvb, offset, 18, FALSE);
851   offset += 18;
852
853   proto_tree_add_item(tree, hf_artnet_address_long_name,
854                       tvb, offset, 64, FALSE);
855   offset += 64;
856
857   hi = proto_tree_add_item(tree,
858                            hf_artnet_address_swin,
859                            tvb,
860                            offset,
861                            ARTNET_ADDRESS_SWIN_LENGTH,
862                            FALSE);
863
864   ti = proto_item_add_subtree(hi, ett_artnet);
865
866   swin = tvb_get_guint8(tvb, offset);
867   proto_tree_add_uint(ti, hf_artnet_address_swin_1, tvb,
868                       offset, 1, swin);
869   offset += 1;
870
871   swin = tvb_get_guint8(tvb, offset);
872   proto_tree_add_uint(ti, hf_artnet_address_swin_2, tvb,
873                       offset, 1, swin);
874   offset += 1;
875
876   swin = tvb_get_guint8(tvb, offset);
877   proto_tree_add_uint(ti, hf_artnet_address_swin_3, tvb,
878                       offset, 1, swin);
879   offset += 1;
880
881   swin = tvb_get_guint8(tvb, offset);
882   proto_tree_add_uint(ti, hf_artnet_address_swin_4, tvb,
883                       offset, 1, swin);
884   offset += 1;
885
886   hi = proto_tree_add_item(tree,
887                            hf_artnet_address_swout,
888                            tvb,
889                            offset,
890                            ARTNET_ADDRESS_SWOUT_LENGTH,
891                            FALSE);
892
893   si = proto_item_add_subtree(hi, ett_artnet);
894
895   swout = tvb_get_guint8(tvb, offset);
896   proto_tree_add_uint(si, hf_artnet_address_swout_1, tvb,
897                       offset, 1, swout);
898   offset += 1;
899
900   swout = tvb_get_guint8(tvb, offset);
901   proto_tree_add_uint(si, hf_artnet_address_swout_2, tvb,
902                       offset, 1, swout);
903   offset += 1;
904
905   swout = tvb_get_guint8(tvb, offset);
906   proto_tree_add_uint(si, hf_artnet_address_swout_3, tvb,
907                       offset, 1, swout);
908   offset += 1;
909
910   swout = tvb_get_guint8(tvb, offset);
911   proto_tree_add_uint(si, hf_artnet_address_swout_4, tvb,
912                       offset, 1, swout);
913   offset += 1;
914
915   swvideo = tvb_get_guint8(tvb, offset);
916   proto_tree_add_uint(tree, hf_artnet_address_swvideo, tvb,
917                       offset, 1, swvideo);
918   offset += 1;
919
920   command = tvb_get_guint8(tvb, offset);
921   proto_tree_add_uint(tree, hf_artnet_address_command, tvb,
922                       offset, 1, command);
923
924   offset += 1;
925
926   return offset;
927 }
928
929 static guint
930 dissect_artnet_input(tvbuff_t *tvb, guint offset, proto_tree *tree) {
931   proto_tree *hi,*si;
932   guint16 num_ports;
933   guint8 input;
934
935   proto_tree_add_item(tree, hf_artnet_filler, tvb,
936                       offset, 2, FALSE);
937   offset += 2;
938
939   num_ports = tvb_get_letohs(tvb, offset);
940   proto_tree_add_uint(tree, hf_artnet_input_num_ports, tvb,
941                       offset, 2, num_ports);
942   offset += 2;
943
944   hi = proto_tree_add_item(tree,
945                            hf_artnet_input_input,
946                            tvb,
947                            offset,
948                            ARTNET_INPUT_INPUT_LENGTH,
949                            FALSE);
950
951   si = proto_item_add_subtree(hi, ett_artnet);
952
953   input = tvb_get_guint8(tvb, offset);
954   proto_tree_add_uint(si, hf_artnet_input_input_1, tvb,
955                       offset, 1, input);
956   offset += 1;
957
958   input = tvb_get_guint8(tvb, offset);
959   proto_tree_add_uint(si, hf_artnet_input_input_2, tvb,
960                       offset, 1, input);
961   offset += 1;
962
963   input = tvb_get_guint8(tvb, offset);
964   proto_tree_add_uint(si, hf_artnet_input_input_3, tvb,
965                       offset, 1, input);
966   offset += 1;
967
968   input = tvb_get_guint8(tvb, offset);
969   proto_tree_add_uint(si, hf_artnet_input_input_4, tvb,
970                       offset, 1, input);
971   offset += 1;
972
973   return offset;
974 }
975
976 static guint
977 dissect_artnet_video_setup(tvbuff_t *tvb, guint offset, proto_tree *tree ) {
978   guint32 size;
979   guint8 control,font_height, last_font,first_font;
980
981   proto_tree_add_item(tree, hf_artnet_filler, tvb,
982                       offset, 4, FALSE);
983   offset += 4;
984
985   control = tvb_get_guint8(tvb, offset);
986   proto_tree_add_uint(tree, hf_artnet_video_setup_control, tvb,
987                       offset, 1, control);
988   offset += 1;
989
990   font_height = tvb_get_guint8(tvb, offset);
991   proto_tree_add_uint(tree, hf_artnet_video_setup_font_height, tvb,
992                       offset, 1, font_height);
993   offset += 1;
994
995   first_font = tvb_get_guint8(tvb, offset);
996   proto_tree_add_uint(tree, hf_artnet_video_setup_first_font, tvb,
997                       offset, 1, first_font);
998   offset += 1;
999
1000   last_font = tvb_get_guint8(tvb, offset);
1001   proto_tree_add_uint(tree, hf_artnet_video_setup_last_font, tvb,
1002                       offset, 1, last_font);
1003   offset += 1;
1004
1005   proto_tree_add_item(tree, hf_artnet_video_setup_win_font_name,
1006                       tvb, offset, 64, FALSE);
1007   offset += 64;
1008
1009   size = last_font * font_height;
1010
1011   proto_tree_add_item(tree, hf_artnet_video_setup_font_data, tvb,
1012                       offset, size, FALSE );
1013
1014   offset += size;
1015
1016   return offset;
1017 }
1018
1019 static guint
1020 dissect_artnet_video_palette(tvbuff_t *tvb, guint offset, proto_tree *tree)
1021 {
1022   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1023                       offset, 2, FALSE);
1024   offset += 2;
1025
1026   proto_tree_add_item(tree, hf_artnet_video_palette_colour_red, tvb,
1027                       offset, 17, FALSE );
1028   offset += 17;
1029
1030   proto_tree_add_item(tree, hf_artnet_video_palette_colour_green, tvb,
1031                       offset, 17, FALSE );
1032   offset += 17;
1033
1034   proto_tree_add_item(tree, hf_artnet_video_palette_colour_blue, tvb,
1035                       offset, 17, FALSE );
1036   offset += 17;
1037
1038   return offset;
1039 }
1040
1041 static guint
1042 dissect_artnet_video_data(tvbuff_t *tvb, guint offset, proto_tree *tree) {
1043   guint8 len_x, len_y;
1044   guint32 size;
1045
1046   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1047                       offset, 2, FALSE);
1048   offset += 2;
1049
1050   proto_tree_add_item(tree, hf_artnet_video_data_pos_x, tvb,
1051                       offset, 1, FALSE);
1052   offset += 1;
1053
1054   proto_tree_add_item(tree, hf_artnet_video_data_pos_y, tvb,
1055                       offset, 1, FALSE);
1056   offset += 1;
1057
1058   len_x = tvb_get_guint8(tvb, offset);
1059   proto_tree_add_uint(tree, hf_artnet_video_data_len_x, tvb,
1060                       offset, 1, len_x);
1061   offset += 1;
1062
1063   len_y = tvb_get_guint8(tvb, offset);
1064   proto_tree_add_uint(tree, hf_artnet_video_data_len_y, tvb,
1065                       offset, 1, len_y);
1066   offset += 1;
1067
1068   size = len_x * len_y * 2;
1069
1070   proto_tree_add_item(tree, hf_artnet_video_data_data, tvb,
1071                       offset, size, FALSE );
1072
1073   offset += size;
1074
1075   return offset;
1076 }
1077
1078 static guint
1079 dissect_artnet_firmware_master(tvbuff_t *tvb, guint offset, proto_tree *tree ) {
1080   guint8 type,block_id;
1081   guint32 length;
1082
1083   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1084                       offset, 2, FALSE);
1085   offset += 2;
1086
1087   type = tvb_get_guint8(tvb, offset);
1088   proto_tree_add_uint(tree, hf_artnet_firmware_master_type, tvb,
1089                       offset, 1, type);
1090   offset += 1;
1091
1092   block_id = tvb_get_guint8(tvb, offset);
1093   proto_tree_add_uint(tree, hf_artnet_firmware_master_block_id, tvb,
1094                       offset, 1, block_id);
1095   offset += 1;
1096
1097   length = tvb_get_ntohl(tvb, offset);
1098   proto_tree_add_uint(tree, hf_artnet_firmware_master_length, tvb,
1099                       offset, 4, length);
1100   offset += 4;
1101
1102   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1103                       offset, 20, FALSE );
1104
1105   offset += 20;
1106
1107   proto_tree_add_item(tree, hf_artnet_firmware_master_data, tvb,
1108                       offset, 1024, FALSE );
1109
1110   offset += 1024;
1111
1112   return offset;
1113 }
1114
1115 static guint
1116 dissect_artnet_firmware_reply(tvbuff_t *tvb, guint offset, proto_tree *tree) {
1117   guint8 type;
1118
1119   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1120                       offset, 2, FALSE);
1121   offset += 2;
1122
1123   type = tvb_get_guint8(tvb, offset);
1124   proto_tree_add_uint(tree, hf_artnet_firmware_reply_type, tvb,
1125                       offset, 1, type);
1126   offset += 1;
1127
1128   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1129                       offset, 21, FALSE );
1130
1131   offset += 21;
1132
1133   return offset;
1134 }
1135
1136 static guint
1137 dissect_artnet_tod_request(tvbuff_t *tvb, guint offset, proto_tree *tree)
1138 {
1139   guint8 ad_count;
1140
1141   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1142                       offset, 2, FALSE);
1143   offset += 2;
1144
1145   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1146                       offset, 8, FALSE);
1147   offset += 8;
1148
1149   proto_tree_add_item(tree, hf_artnet_tod_request_command, tvb,
1150                       offset, 1, FALSE);
1151   offset += 1;
1152
1153   ad_count = tvb_get_guint8(tvb, offset);
1154   proto_tree_add_uint(tree, hf_artnet_tod_request_ad_count, tvb,
1155                       offset, 1, ad_count);
1156   offset += 1;
1157
1158   proto_tree_add_item(tree, hf_artnet_tod_request_address, tvb,
1159                       offset, ad_count, FALSE);
1160   offset += ad_count;
1161
1162   return offset;
1163 }
1164
1165 static guint
1166 dissect_artnet_tod_data(tvbuff_t *tvb, guint offset, proto_tree *tree)
1167 {
1168   guint8 i,uid_count;
1169
1170   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1171                       offset, 1, FALSE);
1172   offset += 1;
1173
1174   proto_tree_add_item(tree, hf_artnet_tod_data_port, tvb,
1175                       offset, 1, FALSE);
1176   offset += 1;
1177
1178   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1179                       offset, 8, FALSE);
1180   offset += 8;
1181
1182   proto_tree_add_item(tree, hf_artnet_tod_data_command_response, tvb,
1183                       offset, 1, FALSE);
1184   offset += 1;
1185
1186   proto_tree_add_item(tree, hf_artnet_tod_data_address, tvb,
1187                       offset, 1, FALSE);
1188   offset += 1;
1189
1190   proto_tree_add_item(tree, hf_artnet_tod_data_uid_total, tvb,
1191                       offset, 2, FALSE);
1192   offset += 2;
1193
1194   proto_tree_add_item(tree, hf_artnet_tod_data_block_count, tvb,
1195                       offset, 1, FALSE);
1196   offset += 1;
1197
1198   uid_count = tvb_get_guint8(tvb, offset);
1199   proto_tree_add_uint(tree, hf_artnet_tod_data_uid_count, tvb,
1200                       offset, 1, uid_count);
1201   offset += 1;
1202
1203   for( i = 0; i < uid_count; i++)
1204   {
1205     proto_tree_add_item(tree, hf_artnet_tod_data_tod, tvb,
1206                         offset, 6, FALSE);
1207     offset += 6;
1208   }
1209
1210   return offset;
1211 }
1212
1213 static guint
1214 dissect_artnet_tod_control(tvbuff_t *tvb, guint offset, proto_tree *tree)
1215 {
1216   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1217                       offset, 2, FALSE);
1218   offset += 2;
1219
1220   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1221                       offset, 8, FALSE);
1222   offset += 8;
1223
1224   proto_tree_add_item(tree, hf_artnet_tod_control_command, tvb,
1225                       offset, 1, FALSE);
1226   offset += 1;
1227
1228   proto_tree_add_item(tree, hf_artnet_tod_control_address, tvb,
1229                       offset, 1, FALSE);
1230   offset += 1;
1231
1232   return offset;
1233 }
1234
1235 static guint
1236 dissect_artnet_rdm(tvbuff_t *tvb, guint offset, proto_tree *tree,  packet_info *pinfo)
1237 {
1238   guint size;
1239   gboolean save_info;
1240   tvbuff_t *next_tvb = NULL;
1241
1242   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1243                       offset, 2, FALSE);
1244   offset += 2;
1245
1246   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1247                       offset, 8, FALSE);
1248   offset += 8;
1249
1250   proto_tree_add_item(tree, hf_artnet_rdm_command, tvb,
1251                       offset, 1, FALSE);
1252   offset += 1;
1253
1254   proto_tree_add_item(tree, hf_artnet_rdm_address, tvb,
1255                       offset, 1, FALSE);
1256   offset += 1;
1257
1258   size = tvb_reported_length_remaining(tvb, offset);
1259
1260   save_info=col_get_writable(pinfo->cinfo); 
1261   col_set_writable(pinfo->cinfo, FALSE);
1262
1263   if (!next_tvb)
1264     next_tvb = tvb_new_subset_remaining(tvb, offset);
1265  
1266   call_dissector(rdm_handle, next_tvb, pinfo, tree);
1267
1268   col_set_writable(pinfo->cinfo, save_info);
1269   
1270   size = tvb_reported_length_remaining(tvb, offset) - size;
1271
1272   return offset + size;
1273 }
1274
1275 static guint
1276 dissect_artnet_ip_prog(tvbuff_t *tvb, guint offset, proto_tree *tree) {
1277   guint8 command;
1278   proto_tree *flags_tree,*flags_item;
1279
1280   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1281                       offset, 2, FALSE);
1282   offset += 2;
1283
1284   command = tvb_get_guint8(tvb, offset);
1285   flags_item = proto_tree_add_uint(tree, hf_artnet_ip_prog_command, tvb,
1286                                    offset, 1, command);
1287
1288   flags_tree=proto_item_add_subtree(flags_item, ett_artnet);
1289   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_port, tvb, offset, 1, FALSE);
1290   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_sm, tvb, offset, 1, FALSE);
1291   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_ip, tvb, offset, 1, FALSE);
1292   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_reset, tvb, offset, 1, FALSE);
1293   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_unused, tvb, offset, 1, FALSE);
1294   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_enable, tvb, offset, 1, FALSE);
1295
1296   offset += 1;
1297
1298   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1299                       offset, 1, FALSE);
1300   offset += 1;
1301
1302   proto_tree_add_item(tree, hf_artnet_ip_prog_ip, tvb,
1303                       offset, 4, FALSE);
1304   offset += 4;
1305
1306   proto_tree_add_item(tree, hf_artnet_ip_prog_sm, tvb,
1307                       offset, 4, FALSE);
1308   offset += 4;
1309
1310   proto_tree_add_item(tree, hf_artnet_ip_prog_port, tvb,
1311                       offset, 2, FALSE);
1312   offset += 2;
1313
1314   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1315                       offset, 8, FALSE);
1316   offset += 8;
1317
1318   return offset;
1319 }
1320
1321 static guint
1322 dissect_artnet_ip_prog_reply(tvbuff_t *tvb, guint offset, proto_tree *tree)
1323 {
1324   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1325                       offset, 4, FALSE);
1326   offset += 4;
1327
1328   proto_tree_add_item(tree, hf_artnet_ip_prog_reply_ip, tvb,
1329                       offset, 4, FALSE);
1330   offset += 4;
1331
1332   proto_tree_add_item(tree, hf_artnet_ip_prog_reply_sm, tvb,
1333                       offset, 4, FALSE);
1334   offset += 4;
1335
1336   proto_tree_add_item(tree, hf_artnet_ip_prog_reply_port, tvb,
1337                       offset, 2, FALSE);
1338   offset += 2;
1339
1340   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1341                       offset, 8, FALSE);
1342   offset += 8;
1343
1344   return offset;
1345 }
1346
1347 static guint
1348 dissect_artnet_poll_server_reply(tvbuff_t *tvb, guint offset, proto_tree *tree)
1349 {
1350   /* no spec released for this packet at the moment */
1351   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1352                       offset, 182, FALSE);
1353   offset += 182;
1354
1355   return offset;
1356 }
1357
1358
1359 static void
1360 dissect_artnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1361   gint offset = 0;
1362   guint size;
1363   guint16 opcode;
1364   proto_tree *ti,*hi,*si,*artnet_tree=NULL,*artnet_header_tree=NULL;
1365
1366   /* Set the protocol column */
1367   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARTNET");
1368
1369   /* Clear out stuff in the info column */
1370   col_clear(pinfo->cinfo, COL_INFO);
1371
1372   if (tree) {
1373     ti = proto_tree_add_item(tree, proto_artnet, tvb, offset, -1, FALSE);
1374     artnet_tree = proto_item_add_subtree(ti, ett_artnet);
1375
1376     hi = proto_tree_add_item(artnet_tree,
1377                              hf_artnet_header,
1378                              tvb,
1379                              offset,
1380                              ARTNET_HEADER_LENGTH ,
1381                              FALSE);
1382
1383     artnet_header_tree = proto_item_add_subtree(hi, ett_artnet);
1384   }
1385
1386   if (check_col(pinfo->cinfo, COL_INFO)) {
1387     col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1388                     tvb_get_ptr(tvb, offset, 8));
1389   }
1390   if( tree ){
1391     proto_tree_add_item(artnet_header_tree, hf_artnet_header_id,
1392                         tvb, offset, 8, FALSE);
1393   }
1394   offset += 8;
1395
1396   opcode = tvb_get_letohs(tvb, offset);
1397   /* set the info column */
1398   if (check_col(pinfo->cinfo, COL_INFO)) {
1399     col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1400       val_to_str(opcode, artnet_opcode_vals, "Unknown (0x%04x)"));
1401   }
1402
1403   if( tree ){
1404     proto_tree_add_uint(artnet_header_tree, hf_artnet_header_opcode, tvb,
1405                         offset, 2, opcode);
1406   }
1407   offset += 2;
1408
1409   if( opcode != ARTNET_OP_POLL_REPLY && opcode != ARTNET_OP_POLL_SERVER_REPLY ) {
1410     if( tree ){
1411       proto_tree_add_item(artnet_header_tree, hf_artnet_header_protver, tvb,
1412                           offset, 2, FALSE);
1413
1414       proto_item_set_len(artnet_header_tree, ARTNET_HEADER_LENGTH+2 );
1415     }
1416     offset += 2;
1417   }
1418
1419   switch( opcode ) {
1420     case ARTNET_OP_POLL:
1421       if (tree) {
1422         hi = proto_tree_add_item(artnet_tree,
1423                                  hf_artnet_poll,
1424                                  tvb,
1425                                  offset,
1426                                  ARTNET_POLL_LENGTH,
1427                                  FALSE);
1428
1429         si = proto_item_add_subtree(hi, ett_artnet);
1430
1431         size = dissect_artnet_poll( tvb, offset, si );
1432         size -= offset;
1433
1434         proto_item_set_len(si, size);
1435       }
1436       break;
1437
1438     case ARTNET_OP_POLL_REPLY:
1439       if (tree) {
1440         hi = proto_tree_add_item(artnet_tree,
1441                                  hf_artnet_poll_reply,
1442                                  tvb,
1443                                  offset,
1444                                  ARTNET_POLL_REPLY_LENGTH,
1445                                  FALSE);
1446
1447         si = proto_item_add_subtree(hi, ett_artnet);
1448
1449         size = dissect_artnet_poll_reply( tvb, offset, si);
1450         size -= offset;
1451
1452         proto_item_set_len(si, size);
1453       }
1454       break;
1455
1456     case ARTNET_OP_OUTPUT:
1457       if (tree) {
1458         hi = proto_tree_add_item(artnet_tree,
1459                                  hf_artnet_output,
1460                                  tvb,
1461                                  offset,
1462                                  ARTNET_OUTPUT_LENGTH,
1463                                  FALSE);
1464
1465         si = proto_item_add_subtree(hi, ett_artnet);
1466
1467         size = dissect_artnet_output( tvb, offset, si );
1468         size -= offset;
1469
1470         proto_item_set_len(si, size);
1471       }
1472       break;
1473
1474     case ARTNET_OP_ADDRESS:
1475       if (tree) {
1476         hi = proto_tree_add_item(artnet_tree,
1477                                  hf_artnet_address,
1478                                  tvb,
1479                                  offset,
1480                                  ARTNET_POLL_REPLY_LENGTH,
1481                                  FALSE);
1482
1483         si = proto_item_add_subtree(hi, ett_artnet);
1484
1485         size = dissect_artnet_address( tvb, offset, si );
1486         size -= offset;
1487
1488         proto_item_set_len(si, size); 
1489       } 
1490       break;
1491
1492     case ARTNET_OP_INPUT:
1493       if (tree) {
1494         hi = proto_tree_add_item(artnet_tree,
1495                                  hf_artnet_input,
1496                                  tvb,
1497                                  offset,
1498                                  ARTNET_INPUT_LENGTH,
1499                                  FALSE);
1500
1501         si = proto_item_add_subtree(hi, ett_artnet);
1502         
1503         size = dissect_artnet_input( tvb, offset, si );
1504         size -= offset;
1505
1506         proto_item_set_len(si, size);
1507       }
1508       break;
1509
1510     case ARTNET_OP_VIDEO_SETUP:
1511       if (tree) {
1512         hi = proto_tree_add_item(artnet_tree,
1513                                  hf_artnet_input,
1514                                  tvb,
1515                                  offset,
1516                                  ARTNET_VIDEO_SETUP_LENGTH,
1517                                  FALSE);
1518
1519         si = proto_item_add_subtree(hi, ett_artnet);
1520         
1521         size = dissect_artnet_video_setup( tvb, offset, si );
1522         size -= offset;
1523
1524         proto_item_set_len(si, size); 
1525       }
1526       break;
1527
1528     case ARTNET_OP_VIDEO_PALETTE:
1529       if (tree) {
1530         hi = proto_tree_add_item(artnet_tree,
1531                                  hf_artnet_input,
1532                                  tvb,
1533                                  offset,
1534                                  ARTNET_VIDEO_PALETTE_LENGTH,
1535                                  FALSE);
1536
1537         si = proto_item_add_subtree(hi, ett_artnet);
1538
1539         size = dissect_artnet_video_palette( tvb, offset, si );
1540         size -= offset;
1541
1542         proto_item_set_len(si, size);
1543       }
1544       break;
1545
1546     case ARTNET_OP_VIDEO_DATA:
1547       if (tree) {
1548         hi = proto_tree_add_item(artnet_tree,
1549                                  hf_artnet_input,
1550                                  tvb,
1551                                  offset,
1552                                  ARTNET_VIDEO_DATA_LENGTH,
1553                                  FALSE);
1554
1555         si = proto_item_add_subtree(hi, ett_artnet);
1556
1557         size = dissect_artnet_video_data( tvb, offset, si );
1558         size -= offset;
1559
1560         proto_item_set_len(si, size);
1561       }
1562       break;
1563
1564     case ARTNET_OP_FIRMWARE_MASTER:
1565       if (tree) {
1566         hi = proto_tree_add_item(artnet_tree,
1567                                  hf_artnet_firmware_master,
1568                                  tvb,
1569                                  offset,
1570                                  ARTNET_FIRMWARE_MASTER_LENGTH,
1571                                  FALSE);
1572
1573         si = proto_item_add_subtree(hi, ett_artnet);
1574
1575         size = dissect_artnet_firmware_master( tvb, offset, si );
1576         size -= offset;
1577
1578         proto_item_set_len(si, size);
1579       }
1580       break;
1581
1582     case ARTNET_OP_FIRMWARE_REPLY:
1583       if (tree) {
1584         hi = proto_tree_add_item(artnet_tree,
1585                                  hf_artnet_firmware_reply,
1586                                  tvb,
1587                                  offset,
1588                                  ARTNET_FIRMWARE_REPLY_LENGTH,
1589                                  FALSE);
1590
1591         si = proto_item_add_subtree(hi, ett_artnet);
1592
1593         size = dissect_artnet_firmware_reply( tvb, offset, si );
1594         size -= offset;
1595
1596         proto_item_set_len(si, size);
1597       }
1598       break;
1599     
1600     case ARTNET_OP_TOD_REQUEST:
1601       if (tree) {
1602         hi = proto_tree_add_item(artnet_tree,
1603                                  hf_artnet_tod_request,
1604                                  tvb,
1605                                  offset,
1606                                  0,
1607                                  FALSE);
1608
1609         si = proto_item_add_subtree(hi, ett_artnet);
1610
1611         size = dissect_artnet_tod_request( tvb, offset, si );
1612         size -= offset;
1613
1614         proto_item_set_len(si, size);
1615       }
1616       break;
1617
1618     case ARTNET_OP_TOD_DATA:
1619       if (tree) {
1620         hi = proto_tree_add_item(artnet_tree,
1621                                  hf_artnet_tod_data,
1622                                  tvb,
1623                                  offset,
1624                                  0,
1625                                  FALSE);
1626
1627         si = proto_item_add_subtree(hi, ett_artnet );
1628
1629         size = dissect_artnet_tod_data( tvb, offset, si );
1630         size -= offset;
1631
1632         proto_item_set_len(si, size );
1633       }
1634       break;
1635
1636     case ARTNET_OP_TOD_CONTROL:
1637       if (tree){
1638         hi = proto_tree_add_item(artnet_tree,
1639                                  hf_artnet_tod_control,
1640                                  tvb,
1641                                  offset,
1642                                  0,
1643                                  FALSE );
1644         si = proto_item_add_subtree(hi, ett_artnet );
1645
1646         size = dissect_artnet_tod_control( tvb, offset, si );
1647         size -= offset;
1648
1649         proto_item_set_len(si, size );
1650       }
1651       break;
1652
1653     case ARTNET_OP_RDM:
1654       hi = proto_tree_add_item(artnet_tree,
1655                                  hf_artnet_rdm,
1656                                  tvb,
1657                                  offset,
1658                                  0,
1659                                  FALSE);
1660       si = proto_item_add_subtree(hi,ett_artnet);
1661
1662       size = dissect_artnet_rdm( tvb, offset, si, pinfo );
1663       size -= offset;
1664
1665       proto_item_set_len( si, size );
1666       break;
1667
1668     case ARTNET_OP_IP_PROG:
1669       if (tree) {
1670         hi = proto_tree_add_item(artnet_tree,
1671                                  hf_artnet_ip_prog,
1672                                  tvb,
1673                                  offset,
1674                                  0,
1675                                  FALSE);
1676         si = proto_item_add_subtree(hi, ett_artnet );
1677
1678         size = dissect_artnet_ip_prog( tvb, offset, si);
1679         size -= offset;
1680
1681         proto_item_set_len(si, size );
1682       }
1683       break;
1684
1685     case ARTNET_OP_IP_PROG_REPLY:
1686       if (tree) {
1687         hi = proto_tree_add_item(artnet_tree,
1688                                  hf_artnet_ip_prog_reply,
1689                                  tvb,
1690                                  offset,
1691                                  0,
1692                                  FALSE);
1693         si = proto_item_add_subtree(hi, ett_artnet );
1694
1695         size = dissect_artnet_ip_prog_reply( tvb, offset, si );
1696         size -= offset;
1697
1698         proto_item_set_len(si, size );
1699       }
1700       break;
1701
1702     case ARTNET_OP_POLL_SERVER_REPLY:
1703       if (tree) {
1704         hi = proto_tree_add_item(artnet_tree,
1705                                  hf_artnet_poll_server_reply,
1706                                  tvb,
1707                                  offset,
1708                                  0,
1709                                  FALSE );
1710         si = proto_item_add_subtree(hi, ett_artnet );
1711
1712         size = dissect_artnet_poll_server_reply( tvb, offset, si );
1713         size -= offset;
1714
1715         proto_item_set_len(si, size );
1716       }
1717       break;
1718
1719     default:
1720       if (tree) {
1721         proto_tree_add_text(artnet_tree, tvb, offset, -1,
1722           "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
1723       }
1724       break;
1725   }
1726
1727
1728
1729 }
1730
1731 void
1732 proto_register_artnet(void) {
1733   static hf_register_info hf[] = {
1734
1735     /* General */
1736
1737     { &hf_artnet_filler,
1738       { "filler",
1739         "artnet.filler",
1740         FT_BYTES, BASE_NONE, NULL, 0x0,
1741         NULL, HFILL }},
1742
1743     { &hf_artnet_spare,
1744       { "spare",
1745         "artnet.spare",
1746         FT_BYTES, BASE_NONE, NULL, 0x0,
1747         NULL, HFILL }},
1748
1749     /* header */
1750
1751     { &hf_artnet_header,
1752       { "Descriptor Header",
1753         "artnet.header",
1754         FT_NONE, BASE_NONE, NULL, 0,
1755         "Art-Net Descriptor Header", HFILL }},
1756
1757     { &hf_artnet_header_id,
1758       { "ID",
1759         "artnet.header.id",
1760         FT_STRING, BASE_NONE, NULL, 0x0,
1761         "ArtNET ID", HFILL }},
1762
1763     { &hf_artnet_header_opcode,
1764       { "Opcode",
1765         "artnet.header.opcode",
1766         FT_UINT16, BASE_HEX, VALS(artnet_opcode_vals), 0x0,
1767         "Art-Net message type", HFILL }},
1768
1769     { &hf_artnet_header_protver,
1770       { "ProVer",
1771         "artnet.header.protver",
1772         FT_UINT16, BASE_DEC, NULL, 0x0,
1773         "Protocol revision number", HFILL }},
1774
1775     /* ArtPoll */
1776
1777     { &hf_artnet_poll,
1778       { "ArtPoll packet",
1779         "artnet.poll",
1780         FT_NONE, BASE_NONE, NULL, 0,
1781         "Art-Net ArtPoll packet", HFILL }},
1782
1783     { &hf_artnet_poll_talktome,
1784       { "TalkToMe",
1785         "artnet.poll.talktome",
1786         FT_UINT8, BASE_HEX, NULL, 0x0,
1787         NULL, HFILL }},
1788
1789     { &hf_artnet_poll_talktome_reply_dest,
1790       { "Reply destination",
1791         "artnet.poll.talktome_reply_dest",
1792         FT_UINT8, BASE_HEX, NULL, 0x01,
1793         NULL, HFILL }},
1794
1795     { &hf_artnet_poll_talktome_reply_type,
1796       { "Reply type",
1797         "artnet.poll.talktome_reply_type",
1798         FT_UINT8, BASE_HEX, NULL, 0x02,
1799         NULL, HFILL }},
1800
1801     { &hf_artnet_poll_talktome_unused,
1802       { "unused",
1803         "artnet.poll.talktome_unused",
1804         FT_UINT8, BASE_HEX, NULL, 0xfc,
1805         NULL, HFILL }},
1806
1807     /* ArtPollReply */
1808
1809     { &hf_artnet_poll_reply,
1810       { "ArtPollReply packet",
1811         "artnet.poll_reply",
1812         FT_NONE, BASE_NONE, NULL, 0,
1813         "Art-Net ArtPollReply packet", HFILL }},
1814
1815     { &hf_artnet_poll_reply_ip_address,
1816       { "IP Address",
1817         "artnet.poll_reply.ip_address",
1818         FT_IPv4, BASE_NONE, NULL, 0x0,
1819         NULL, HFILL }},
1820
1821     { &hf_artnet_poll_reply_port_nr,
1822       { "Port number",
1823         "artnet.poll_reply.port_nr",
1824         FT_UINT16, BASE_DEC, NULL, 0x0,
1825         "Port Number", HFILL }},
1826
1827     { &hf_artnet_poll_reply_versinfo,
1828       { "Version Info",
1829         "artnet.poll_reply.versinfo",
1830         FT_UINT16, BASE_HEX, NULL, 0x0,
1831         "Version info", HFILL }},
1832
1833     { &hf_artnet_poll_reply_subswitch,
1834       { "SubSwitch",
1835         "artnet.poll_reply.subswitch",
1836         FT_UINT16, BASE_HEX, NULL, 0x0,
1837         "Subswitch version", HFILL }},
1838
1839     { &hf_artnet_poll_reply_oem,
1840       { "Oem",
1841         "artnet.poll_reply.oem",
1842         FT_UINT16, BASE_HEX, VALS(artnet_oem_code_vals), 0x0,
1843         "OEM", HFILL }},
1844
1845     { &hf_artnet_poll_reply_ubea_version,
1846       { "UBEA Version",
1847         "artnet.poll_reply.ubea_version",
1848         FT_UINT8, BASE_DEC, NULL, 0x0,
1849         "UBEA version number", HFILL }},
1850
1851     { &hf_artnet_poll_reply_status,
1852       { "Status",
1853         "artnet.poll_reply.status",
1854         FT_UINT8, BASE_HEX, NULL, 0x0,
1855         NULL, HFILL }},
1856
1857     { &hf_artnet_poll_reply_esta_man,
1858       { "ESTA Code",
1859         "artnet.poll_reply.esta_man",
1860         FT_UINT16, BASE_HEX, VALS(artnet_esta_man_vals), 0x0,
1861         NULL, HFILL }},
1862
1863     { &hf_artnet_poll_reply_short_name,
1864       { "Short Name",
1865         "artnet.poll_reply.short_name",
1866         FT_STRING, BASE_NONE, NULL, 0x0,
1867         NULL, HFILL }},
1868
1869     { &hf_artnet_poll_reply_long_name,
1870       { "Long Name",
1871         "artnet.poll_reply.long_name",
1872         FT_STRING, BASE_NONE, NULL, 0x0,
1873         NULL, HFILL }},
1874
1875     { &hf_artnet_poll_reply_node_report,
1876       { "Node Report",
1877         "artnet.poll_reply.node_report",
1878         FT_STRING, BASE_NONE, NULL, 0x0,
1879         NULL, HFILL }},
1880
1881     { &hf_artnet_poll_reply_port_info,
1882       { "Port Info",
1883         "artnet.poll_reply.port_info",
1884         FT_NONE, BASE_NONE, NULL, 0,
1885         NULL, HFILL }},
1886
1887     { &hf_artnet_poll_reply_num_ports,
1888       { "Number of Ports",
1889         "artnet.poll_reply.num_ports",
1890         FT_UINT16, BASE_DEC, NULL, 0x0,
1891         NULL, HFILL }},
1892
1893     { &hf_artnet_poll_reply_port_types,
1894       { "Port Types",
1895         "artnet.poll_reply.port_types",
1896         FT_NONE, BASE_NONE, NULL, 0,
1897         NULL, HFILL }},
1898
1899     { &hf_artnet_poll_reply_port_types_1,
1900       { "Type of Port 1",
1901         "artnet.poll_reply.port_types_1",
1902         FT_UINT8, BASE_HEX, NULL, 0x0,
1903         NULL, HFILL }},
1904
1905     { &hf_artnet_poll_reply_port_types_2,
1906       { "Type of Port 2",
1907         "artnet.poll_reply.port_types_2",
1908         FT_UINT8, BASE_HEX, NULL, 0x0,
1909         NULL, HFILL }},
1910
1911     { &hf_artnet_poll_reply_port_types_3,
1912       { "Type of Port 3",
1913         "artnet.poll_reply.port_types_3",
1914         FT_UINT8, BASE_HEX, NULL, 0x0,
1915         NULL, HFILL }},
1916
1917     { &hf_artnet_poll_reply_port_types_4,
1918       { "Type of Port 4",
1919         "artnet.poll_reply.port_types_4",
1920         FT_UINT8, BASE_HEX, NULL, 0x0,
1921         NULL, HFILL }},
1922
1923     { &hf_artnet_poll_reply_good_input,
1924       { "Input Status",
1925         "artnet.poll_reply.good_input",
1926         FT_NONE, BASE_NONE, NULL, 0,
1927         NULL, HFILL }},
1928
1929     { &hf_artnet_poll_reply_good_input_1,
1930       { "Input status of Port 1",
1931         "artnet.poll_reply.good_input_1",
1932         FT_UINT8, BASE_HEX, NULL, 0x0,
1933         NULL, HFILL }},
1934
1935     { &hf_artnet_poll_reply_good_input_2,
1936       { "Input status of Port 2",
1937         "artnet.poll_reply.good_input_2",
1938         FT_UINT8, BASE_HEX, NULL, 0x0,
1939         NULL, HFILL }},
1940
1941     { &hf_artnet_poll_reply_good_input_3,
1942       { "Input status of Port 3",
1943         "artnet.poll_reply.good_input_3",
1944         FT_UINT8, BASE_HEX, NULL, 0x0,
1945         NULL, HFILL }},
1946
1947     { &hf_artnet_poll_reply_good_input_4,
1948       { "Input status of Port 4",
1949         "artnet.poll_reply.good_input_4",
1950         FT_UINT8, BASE_HEX, NULL, 0x0,
1951         NULL, HFILL }},
1952
1953     { &hf_artnet_poll_reply_good_output,
1954       { "Output Status",
1955         "artnet.poll_reply.good_output",
1956         FT_NONE, BASE_NONE, NULL, 0,
1957         "Port output status", HFILL }},
1958
1959     { &hf_artnet_poll_reply_good_output_1,
1960       { "Output status of Port 1",
1961         "artnet.poll_reply.good_output_1",
1962         FT_UINT8, BASE_HEX, NULL, 0x0,
1963         NULL, HFILL }},
1964
1965     { &hf_artnet_poll_reply_good_output_2,
1966       { "Output status of Port 2",
1967         "artnet.poll_reply.good_output_2",
1968         FT_UINT8, BASE_HEX, NULL, 0x0,
1969         NULL, HFILL }},
1970
1971     { &hf_artnet_poll_reply_good_output_3,
1972       { "Output status of Port 3",
1973         "artnet.poll_reply.good_output_3",
1974         FT_UINT8, BASE_HEX, NULL, 0x0,
1975         NULL, HFILL }},
1976
1977     { &hf_artnet_poll_reply_good_output_4,
1978       { "Output status of Port 4",
1979         "artnet.poll_reply.good_output_4",
1980         FT_UINT8, BASE_HEX, NULL, 0x0,
1981         "Outpus status of Port 4", HFILL }},
1982
1983     { &hf_artnet_poll_reply_swin,
1984       { "Input Subswitch",
1985         "artnet.poll_reply.swin",
1986         FT_NONE, BASE_NONE, NULL, 0,
1987         NULL, HFILL }},
1988
1989     { &hf_artnet_poll_reply_swin_1,
1990       { "Input Subswitch of Port 1",
1991         "artnet.poll_reply.swin_1",
1992         FT_UINT8, BASE_HEX, NULL, 0x0,
1993         NULL, HFILL }},
1994
1995     { &hf_artnet_poll_reply_swin_2,
1996       { "Input Subswitch of Port 2",
1997         "artnet.poll_reply.swin_2",
1998         FT_UINT8, BASE_HEX, NULL, 0x0,
1999         NULL, HFILL }},
2000
2001     { &hf_artnet_poll_reply_swin_3,
2002       { "Input Subswitch of Port 3",
2003         "artnet.poll_reply.swin_3",
2004         FT_UINT8, BASE_HEX, NULL, 0x0,
2005         NULL, HFILL }},
2006
2007     { &hf_artnet_poll_reply_swin_4,
2008       { "Input Subswitch of Port 4",
2009         "artnet.poll_reply.swin_4",
2010         FT_UINT8, BASE_HEX, NULL, 0x0,
2011         NULL, HFILL }},
2012
2013     { &hf_artnet_poll_reply_swout,
2014       { "Output Subswitch",
2015         "artnet.poll_reply.swout",
2016         FT_NONE, BASE_NONE, NULL, 0,
2017         NULL, HFILL }},
2018
2019     { &hf_artnet_poll_reply_swout_1,
2020       { "Output Subswitch of Port 1",
2021         "artnet.poll_reply.swout_1",
2022         FT_UINT8, BASE_HEX, NULL, 0x0,
2023         NULL, HFILL }},
2024
2025     { &hf_artnet_poll_reply_swout_2,
2026       { "Output Subswitch of Port 2",
2027         "artnet.poll_reply.swout_2",
2028         FT_UINT8, BASE_HEX, NULL, 0x0,
2029         NULL, HFILL }},
2030
2031     { &hf_artnet_poll_reply_swout_3,
2032       { "Output Subswitch of Port 3",
2033         "artnet.poll_reply.swout_3",
2034         FT_UINT8, BASE_HEX, NULL, 0x0,
2035         NULL, HFILL }},
2036
2037     { &hf_artnet_poll_reply_swout_4,
2038       { "Output Subswitch of Port 4",
2039         "artnet.poll_reply.swout_4",
2040         FT_UINT8, BASE_HEX, NULL, 0x0,
2041         NULL, HFILL }},
2042
2043     { &hf_artnet_poll_reply_swvideo,
2044       { "SwVideo",
2045         "artnet.poll_reply.swvideo",
2046         FT_UINT8, BASE_HEX, NULL, 0x0,
2047         NULL, HFILL }},
2048
2049     { &hf_artnet_poll_reply_swmacro,
2050       { "SwMacro",
2051         "artnet.poll_reply.swmacro",
2052         FT_UINT8, BASE_HEX, NULL, 0x0,
2053         NULL, HFILL }},
2054
2055     { &hf_artnet_poll_reply_swremote,
2056       { "SwRemote",
2057         "artnet.poll_reply.swremote",
2058         FT_UINT8, BASE_HEX, NULL, 0x0,
2059         NULL, HFILL }},
2060
2061     { &hf_artnet_poll_reply_mac,
2062       { "MAC",
2063         "artnet.poll_reply.mac",
2064         FT_ETHER, BASE_NONE, NULL, 0x0,
2065         NULL, HFILL }},
2066
2067     /* ArtOutput */
2068
2069     { &hf_artnet_output,
2070       { "ArtDMX packet",
2071         "artnet.output",
2072         FT_NONE, BASE_NONE, NULL, 0,
2073         "Art-Net ArtDMX packet", HFILL }},
2074
2075     { &hf_artnet_output_sequence,
2076       { "Sequence",
2077         "artnet.output.sequence",
2078         FT_UINT8, BASE_DEC, NULL, 0x0,
2079         NULL, HFILL }},
2080
2081     { &hf_artnet_output_physical,
2082       { "Physical",
2083         "artnet.output.physical",
2084         FT_UINT8, BASE_DEC, NULL, 0x0,
2085         NULL, HFILL }},
2086
2087     { &hf_artnet_output_universe,
2088       { "Universe",
2089         "artnet.output.universe",
2090         FT_UINT16, BASE_DEC, NULL, 0x0,
2091         NULL, HFILL }},
2092
2093     { &hf_artnet_output_length,
2094       { "Length",
2095         "artnet.output.length",
2096         FT_UINT16, BASE_DEC, NULL, 0x0,
2097         NULL, HFILL }},
2098
2099     { &hf_artnet_output_data,
2100       { "DMX data",
2101         "artnet.output.data",
2102         FT_NONE, BASE_NONE, NULL, 0x0,
2103         "DMX Data", HFILL }},
2104
2105     { &hf_artnet_output_data_filter,
2106       { "DMX data filter",
2107         "artnet.output.data_filter",
2108         FT_BYTES, BASE_NONE, NULL, 0x0,
2109         "DMX Data Filter", HFILL }},
2110
2111     { &hf_artnet_output_dmx_data,
2112       { "DMX data",
2113         "artnet.output.dmx_data",
2114         FT_NONE, BASE_NONE, NULL, 0x0,
2115         "DMX Data", HFILL }},
2116
2117     /* ArtAddress */
2118
2119     { &hf_artnet_address,
2120       { "ArtAddress packet",
2121         "artnet.address",
2122         FT_NONE, BASE_NONE, NULL, 0,
2123         "Art-Net ArtAddress packet", HFILL }},
2124
2125     { &hf_artnet_address_short_name,
2126       { "Short Name",
2127         "artnet.address.short_name",
2128         FT_STRING, BASE_NONE, NULL, 0x0,
2129         NULL, HFILL }},
2130
2131     { &hf_artnet_address_long_name,
2132       { "Long Name",
2133         "artnet.address.long_name",
2134         FT_STRING, BASE_NONE, NULL, 0x0,
2135         NULL, HFILL }},
2136
2137     { &hf_artnet_address_swin,
2138       { "Input Subswitch",
2139         "artnet.address.swin",
2140         FT_NONE, BASE_NONE, NULL, 0,
2141         NULL, HFILL }},
2142
2143     { &hf_artnet_address_swin_1,
2144       { "Input Subswitch of Port 1",
2145         "artnet.address.swin_1",
2146         FT_UINT8, BASE_HEX, NULL, 0x0,
2147         NULL, HFILL }},
2148
2149     { &hf_artnet_address_swin_2,
2150       { "Input Subswitch of Port 2",
2151         "artnet.address.swin_2",
2152         FT_UINT8, BASE_HEX, NULL, 0x0,
2153         NULL, HFILL }},
2154
2155     { &hf_artnet_address_swin_3,
2156       { "Input Subswitch of Port 3",
2157         "artnet.address.swin_3",
2158         FT_UINT8, BASE_HEX, NULL, 0x0,
2159         NULL, HFILL }},
2160
2161     { &hf_artnet_address_swin_4,
2162       { "Input Subswitch of Port 4",
2163         "artnet.address.swin_4",
2164         FT_UINT8, BASE_HEX, NULL, 0x0,
2165         NULL, HFILL }},
2166
2167     { &hf_artnet_address_swout,
2168       { "Output Subswitch",
2169         "artnet.address.swout",
2170         FT_NONE, BASE_NONE, NULL, 0,
2171         NULL, HFILL }},
2172
2173     { &hf_artnet_address_swout_1,
2174       { "Output Subswitch of Port 1",
2175         "artnet.address.swout_1",
2176         FT_UINT8, BASE_HEX, NULL, 0x0,
2177         NULL, HFILL }},
2178
2179     { &hf_artnet_address_swout_2,
2180       { "Output Subswitch of Port 2",
2181         "artnet.address.swout_2",
2182         FT_UINT8, BASE_HEX, NULL, 0x0,
2183         NULL, HFILL }},
2184
2185     { &hf_artnet_address_swout_3,
2186       { "Output Subswitch of Port 3",
2187         "artnet.address.swout_3",
2188         FT_UINT8, BASE_HEX, NULL, 0x0,
2189         NULL, HFILL }},
2190
2191     { &hf_artnet_address_swout_4,
2192       { "Output Subswitch of Port 4",
2193         "artnet.address.swout_4",
2194         FT_UINT8, BASE_HEX, NULL, 0x0,
2195         NULL, HFILL }},
2196
2197     { &hf_artnet_address_subswitch,
2198       { "Subswitch",
2199         "artnet.address.subswitch",
2200         FT_UINT8, BASE_HEX, NULL, 0x0,
2201         NULL, HFILL }},
2202
2203     { &hf_artnet_address_swvideo,
2204       { "SwVideo",
2205         "artnet.address.swvideo",
2206         FT_UINT8, BASE_HEX, NULL, 0x0,
2207         NULL, HFILL }},
2208
2209     { &hf_artnet_address_command,
2210       { "Command",
2211         "artnet.address.command",
2212         FT_UINT8, BASE_HEX, VALS(artnet_address_command_vals), 0x0,
2213         NULL, HFILL }},
2214
2215     /* ArtInput */
2216
2217     { &hf_artnet_input,
2218       { "ArtInput packet",
2219         "artnet.input",
2220         FT_NONE, BASE_NONE, NULL, 0,
2221         "Art-Net ArtInput packet", HFILL }},
2222
2223     { &hf_artnet_input_num_ports,
2224       { "Number of Ports",
2225         "artnet.input.num_ports",
2226         FT_UINT16, BASE_DEC, NULL, 0x0,
2227         NULL, HFILL }},
2228
2229     { &hf_artnet_input_input,
2230       { "Port Status",
2231         "artnet.input.input",
2232         FT_NONE, BASE_NONE, NULL, 0,
2233         NULL, HFILL }},
2234
2235     { &hf_artnet_input_input_1,
2236       { "Status of Port 1",
2237         "artnet.input.input_1",
2238         FT_UINT8, BASE_HEX, NULL, 0x0,
2239         NULL, HFILL }},
2240
2241     { &hf_artnet_input_input_2,
2242       { "Status of Port 2",
2243         "artnet.input.input_2",
2244         FT_UINT8, BASE_HEX, NULL, 0x0,
2245         NULL, HFILL }},
2246
2247     { &hf_artnet_input_input_3,
2248       { "Status of Port 3",
2249         "artnet.input.input_3",
2250         FT_UINT8, BASE_HEX, NULL, 0x0,
2251         NULL, HFILL }},
2252
2253     { &hf_artnet_input_input_4,
2254       { "Status of Port 4",
2255         "artnet.input.input_4",
2256         FT_UINT8, BASE_HEX, NULL, 0x0,
2257         NULL, HFILL }},
2258
2259     /* ArtFirmwareMaster */
2260
2261     { &hf_artnet_firmware_master,
2262       { "ArtFirmwareMaster packet",
2263         "artnet.firmware_master",
2264         FT_NONE, BASE_NONE, NULL, 0,
2265         "Art-Net ArtFirmwareMaster packet", HFILL }},
2266
2267     { &hf_artnet_firmware_master_type,
2268       { "Type",
2269         "artnet.firmware_master.type",
2270         FT_UINT8, BASE_HEX, VALS(artnet_firmware_master_type_vals), 0x0,
2271         "Number of Ports", HFILL }},
2272
2273     { &hf_artnet_firmware_master_block_id,
2274       { "Block ID",
2275         "artnet.firmware_master.block_id",
2276         FT_UINT8, BASE_DEC, NULL, 0x0,
2277         NULL, HFILL }},
2278
2279     { &hf_artnet_firmware_master_length,
2280       { "Length",
2281         "artnet.firmware_master.length",
2282         FT_UINT32, BASE_DEC, NULL, 0x0,
2283         NULL, HFILL }},
2284
2285     { &hf_artnet_firmware_master_data,
2286       { "data",
2287         "artnet.firmware_master.data",
2288         FT_BYTES, BASE_NONE, NULL, 0x0,
2289         NULL, HFILL }},
2290
2291     /* ArtFirmwareReply */
2292
2293     { &hf_artnet_firmware_reply,
2294       { "ArtFirmwareReply packet",
2295         "artnet.firmware_reply",
2296         FT_NONE, BASE_NONE, NULL, 0,
2297         "Art-Net ArtFirmwareReply packet", HFILL }},
2298
2299     { &hf_artnet_firmware_reply_type,
2300       { "Type",
2301         "artnet.firmware_reply.type",
2302         FT_UINT8, BASE_HEX, VALS(artnet_firmware_reply_type_vals), 0x0,
2303         "Number of Ports", HFILL }},
2304
2305     /* ArtVideoSetup */
2306
2307     { &hf_artnet_video_setup,
2308       { "ArtVideoSetup packet",
2309         "artnet.video_setup",
2310         FT_NONE, BASE_NONE, NULL, 0,
2311         "ArtNET ArtVideoSetup packet", HFILL }},
2312
2313     { &hf_artnet_video_setup_control,
2314       { "control",
2315         "artnet.video_setup.control",
2316         FT_UINT8, BASE_HEX, NULL, 0x0,
2317         NULL, HFILL }},
2318
2319     { &hf_artnet_video_setup_font_height,
2320       { "Font Height",
2321         "artnet.video_setup.font_height",
2322         FT_UINT8, BASE_DEC, NULL, 0x0,
2323         NULL, HFILL }},
2324
2325     { &hf_artnet_video_setup_first_font,
2326       { "First Font",
2327         "artnet.video_setup.first_font",
2328         FT_UINT8, BASE_DEC, NULL, 0x0,
2329         NULL, HFILL }},
2330
2331     { &hf_artnet_video_setup_last_font,
2332       { "Last Font",
2333         "artnet.video_setup.last_font",
2334         FT_UINT8, BASE_DEC, NULL, 0x0,
2335         NULL, HFILL }},
2336
2337     { &hf_artnet_video_setup_win_font_name,
2338       { "Windows Font Name",
2339         "artnet.video_setup.win_font_name",
2340         FT_STRING, BASE_NONE, NULL, 0x0,
2341         NULL, HFILL }},
2342
2343     { &hf_artnet_video_setup_font_data,
2344       { "Font data",
2345         "artnet.video_setup.font_data",
2346         FT_BYTES, BASE_NONE, NULL, 0x0,
2347         "Font Date", HFILL }},
2348
2349     /* ArtVideoPalette */
2350
2351     { &hf_artnet_video_palette,
2352       { "ArtVideoPalette packet",
2353         "artnet.video_palette",
2354         FT_NONE, BASE_NONE, NULL, 0,
2355         "Art-Net ArtVideoPalette packet", HFILL }},
2356
2357     { &hf_artnet_video_palette_colour_red,
2358       { "Colour Red",
2359         "artnet.video_palette.colour_red",
2360         FT_BYTES, BASE_NONE, NULL, 0x0,
2361         NULL, HFILL }},
2362
2363     { &hf_artnet_video_palette_colour_green,
2364       { "Colour Green",
2365         "artnet.video_palette.colour_green",
2366         FT_BYTES, BASE_NONE, NULL, 0x0,
2367         NULL, HFILL }},
2368
2369     { &hf_artnet_video_palette_colour_blue,
2370       { "Colour Blue",
2371         "artnet.video_palette.colour_blue",
2372         FT_BYTES, BASE_NONE, NULL, 0x0,
2373         NULL, HFILL }},
2374
2375     /* ArtVideoData */
2376
2377     { &hf_artnet_video_data,
2378       { "ArtVideoData packet",
2379         "artnet.video_data",
2380         FT_NONE, BASE_NONE, NULL, 0,
2381         "Art-Net ArtVideoData packet", HFILL }},
2382
2383     { &hf_artnet_video_data_pos_x,
2384       { "PosX",
2385         "artnet.video_data.pos_x",
2386         FT_UINT8, BASE_DEC, NULL, 0x0,
2387         NULL, HFILL }},
2388
2389     { &hf_artnet_video_data_pos_y,
2390       { "PosY",
2391         "artnet.video_data.pos_y",
2392         FT_UINT8, BASE_DEC, NULL, 0x0,
2393         NULL, HFILL }},
2394
2395     { &hf_artnet_video_data_len_x,
2396       { "LenX",
2397         "artnet.video_data.len_x",
2398         FT_UINT8, BASE_DEC, NULL, 0x0,
2399         NULL, HFILL }},
2400
2401     { &hf_artnet_video_data_len_y,
2402       { "LenY",
2403         "artnet.video_data.len_y",
2404         FT_UINT8, BASE_DEC, NULL, 0x0,
2405         NULL, HFILL }},
2406
2407     { &hf_artnet_video_data_data,
2408       { "Video Data",
2409         "artnet.video_data.data",
2410         FT_BYTES, BASE_NONE, NULL, 0x0,
2411         NULL, HFILL }},
2412
2413     /* ArtTodRequest */
2414     { &hf_artnet_tod_request,
2415       { "ArtTodRequest packet",
2416         "artnet.tod_request",
2417         FT_NONE, BASE_NONE, NULL, 0,
2418         "Art-Net ArtTodRequest packet", HFILL }},
2419
2420     { &hf_artnet_tod_request_command,
2421       { "Command",
2422         "artnet.tod_request.command",
2423         FT_UINT8, BASE_HEX, VALS(artnet_tod_request_command_vals), 0x0,
2424         NULL, HFILL }},
2425
2426     { &hf_artnet_tod_request_ad_count,
2427       { "Address Count",
2428         "artnet.tod_request.ad_count",
2429         FT_UINT8, BASE_DEC, NULL, 0x0,
2430         NULL, HFILL }},
2431
2432     { &hf_artnet_tod_request_address,
2433       { "Address",
2434         "artnet.tod_request.address",
2435         FT_BYTES, BASE_NONE, NULL, 0x0,
2436         NULL, HFILL }},
2437
2438     /* ArtTodData */
2439     { &hf_artnet_tod_data,
2440       { "ArtTodData packet",
2441         "artnet.tod_data",
2442         FT_NONE, BASE_NONE, NULL, 0,
2443         "Art-Net ArtTodData packet", HFILL }},
2444
2445     { &hf_artnet_tod_data_port,
2446       { "Port",
2447         "artnet.tod_data.port",
2448         FT_UINT8, BASE_DEC, NULL, 0x0,
2449         NULL, HFILL }},
2450
2451     { &hf_artnet_tod_data_command_response,
2452       { "Command Response",
2453         "artnet.tod_data.command_response",
2454         FT_UINT8, BASE_HEX, VALS(artnet_tod_data_command_vals), 0x0,
2455         NULL, HFILL }},
2456
2457     { &hf_artnet_tod_data_address,
2458       { "Address",
2459         "artnet.tod_data.address",
2460         FT_UINT8, BASE_HEX, NULL, 0x0,
2461         NULL, HFILL }},
2462
2463     { &hf_artnet_tod_data_uid_total,
2464       { "UID Total",
2465         "artnet.tod_data.uid_total",
2466         FT_UINT16, BASE_DEC, NULL, 0x0,
2467         NULL, HFILL }},
2468
2469     { &hf_artnet_tod_data_block_count,
2470       { "Block Count",
2471         "artnet.tod_data.block_count",
2472         FT_UINT8, BASE_DEC, NULL, 0x0,
2473         NULL, HFILL }},
2474
2475     { &hf_artnet_tod_data_uid_count,
2476       { "UID Count",
2477         "artnet.tod_data.uid_count",
2478         FT_UINT8, BASE_DEC, NULL, 0x0,
2479         NULL, HFILL }},
2480
2481     { &hf_artnet_tod_data_tod,
2482       { "TOD",
2483         "artnet.tod_data.tod",
2484         FT_BYTES, BASE_NONE, NULL, 0x0,
2485         NULL, HFILL }},
2486
2487     /* ArtTodControl */
2488     { &hf_artnet_tod_control,
2489       { "ArtTodControl packet",
2490         "artner.tod_control",
2491         FT_NONE, BASE_NONE, NULL, 0,
2492         "Art-Net ArtTodControl packet", HFILL }},
2493
2494     { &hf_artnet_tod_control_command,
2495       { "Command",
2496         "artnet.tod_control.command",
2497         FT_UINT8, BASE_HEX, VALS(artnet_tod_control_command_vals), 0x0,
2498         NULL, HFILL }},
2499
2500     { &hf_artnet_tod_control_address,
2501       { "Address",
2502         "artnet.tod_request.address",
2503         FT_UINT8, BASE_HEX, NULL, 0x0,
2504         NULL, HFILL }},
2505
2506     /* ArtRdm */
2507     { &hf_artnet_rdm,
2508       { "ArtRdm packet",
2509         "artnet.rdm",
2510         FT_NONE, BASE_NONE, NULL, 0,
2511         "Art-Net ArtRdm packet", HFILL }},
2512
2513     { &hf_artnet_rdm_command,
2514       { "Command",
2515         "artnet.rdm.command",
2516         FT_UINT8, BASE_HEX, VALS(artnet_rdm_command_vals), 0x0,
2517         NULL, HFILL }},
2518
2519     { &hf_artnet_rdm_address,
2520       { "Address",
2521         "artnet.rdm.address",
2522         FT_UINT8, BASE_HEX, NULL, 0x0,
2523         NULL, HFILL }},
2524
2525     /* ArtIpProg */
2526     { &hf_artnet_ip_prog,
2527       { "ArtIpProg packet",
2528         "artnet.ip_prog",
2529         FT_NONE, BASE_NONE, NULL, 0,
2530         "ArtNET ArtIpProg packet", HFILL }},
2531
2532     { &hf_artnet_ip_prog_command,
2533       { "Command",
2534         "artnet.ip_prog.command",
2535         FT_UINT8, BASE_HEX, NULL, 0x0,
2536         NULL, HFILL }},
2537
2538     { &hf_artnet_ip_prog_command_prog_port,
2539       { "Program Port",
2540         "artnet.ip_prog.command_prog_port",
2541         FT_UINT8, BASE_HEX, NULL, 0x01,
2542         NULL, HFILL }},
2543
2544     { &hf_artnet_ip_prog_command_prog_sm,
2545       { "Program Subnet Mask",
2546         "artnet.ip_prog.command_prog_sm",
2547         FT_UINT8, BASE_HEX, NULL, 0x02,
2548         NULL, HFILL }},
2549
2550     { &hf_artnet_ip_prog_command_prog_ip,
2551       { "Program IP",
2552         "artnet.ip_prog.command_prog_ip",
2553         FT_UINT8, BASE_HEX, NULL, 0x04,
2554         NULL, HFILL }},
2555
2556     { &hf_artnet_ip_prog_command_reset,
2557       { "Reset parameters",
2558         "artnet.ip_prog.command_reset",
2559         FT_UINT8, BASE_HEX, NULL, 0x08,
2560         NULL, HFILL }},
2561
2562     { &hf_artnet_ip_prog_command_unused,
2563       { "Unused",
2564         "artnet.ip_prog.command_unused",
2565         FT_UINT8, BASE_HEX, NULL, 0x70,
2566         NULL, HFILL }},
2567
2568     { &hf_artnet_ip_prog_command_prog_enable,
2569       { "Enable Programming",
2570         "artnet.ip_prog.command_prog_enable",
2571         FT_UINT8, BASE_HEX, NULL, 0x80,
2572         NULL, HFILL }},
2573
2574     { &hf_artnet_ip_prog_ip,
2575       { "IP Address",
2576         "artnet.ip_prog.ip",
2577         FT_IPv4, BASE_NONE, NULL, 0x0,
2578         NULL, HFILL }},
2579
2580     { &hf_artnet_ip_prog_sm,
2581       { "Subnet mask",
2582         "artnet.ip_prog.sm",
2583         FT_IPv4, BASE_NONE, NULL, 0x0,
2584         "IP Subnet mask", HFILL }},
2585
2586     { &hf_artnet_ip_prog_port,
2587       { "Port",
2588         "artnet.ip_prog.port",
2589         FT_UINT16, BASE_DEC, NULL, 0x0,
2590         NULL, HFILL }},
2591
2592     /* ArtIpProgReply */
2593     { &hf_artnet_ip_prog_reply,
2594       { "ArtIpProgReplay packet",
2595         "artnet.ip_prog_reply",
2596         FT_NONE, BASE_NONE, NULL, 0,
2597         "Art-Net ArtIpProgReply packet", HFILL }},
2598
2599     { &hf_artnet_ip_prog_reply_ip,
2600       { "IP Address",
2601         "artnet.ip_prog_reply.ip",
2602         FT_IPv4, BASE_NONE, NULL, 0x0,
2603         NULL, HFILL }},
2604
2605     { &hf_artnet_ip_prog_reply_sm,
2606       { "Subnet mask",
2607         "artnet.ip_prog_reply.sm",
2608         FT_IPv4, BASE_NONE, NULL, 0x0,
2609         "IP Subnet mask", HFILL }},
2610
2611     { &hf_artnet_ip_prog_reply_port,
2612       { "Port",
2613         "artnet.ip_prog_reply.port",
2614         FT_UINT16, BASE_DEC, NULL, 0x0,
2615         NULL, HFILL }},
2616
2617     /* ArtPollServerReply */
2618     { &hf_artnet_poll_server_reply,
2619       { "ArtPollServerReply packet",
2620         "artnet.poll_server_reply",
2621         FT_NONE, BASE_NONE, NULL, 0,
2622         "Art-Net ArtPollServerReply packet", HFILL }}
2623
2624   };
2625
2626   static gint *ett[] = {
2627     &ett_artnet,
2628   };
2629
2630   module_t *artnet_module;
2631
2632   static enum_val_t disp_chan_val_types[] = {
2633      { "pro", "Percent", 0 },
2634      { "hex", "Hexadecimal", 1 },
2635      { "dec", "Decimal", 2 },
2636      { NULL, NULL, 0 }
2637   };
2638
2639   static enum_val_t disp_chan_nr_types[] = {
2640      { "hex", "Hexadecimal", 0 },
2641      { "dec", "Decimal", 1 },
2642      { NULL, NULL, 0 }
2643   };
2644
2645   static enum_val_t col_count[] = {
2646      { "6", "6", 6 },
2647      { "10", "10", 10 },
2648      { "12", "12", 12 },
2649      { "16", "16", 16 },
2650      { "24", "24", 24 },
2651      { NULL, NULL, 0 }
2652   };
2653
2654   proto_artnet = proto_register_protocol("Art-Net",
2655                                        "ARTNET","artnet");
2656   proto_register_field_array(proto_artnet,hf,array_length(hf));
2657   proto_register_subtree_array(ett,array_length(ett));
2658
2659   artnet_module = prefs_register_protocol(proto_artnet,
2660                                         proto_reg_handoff_artnet);
2661   prefs_register_uint_preference(artnet_module, "udp_port",
2662                                  "UDP Port",
2663                                  "The UDP port on which "
2664                                  "Art-Net "
2665                                  "packets will be sent",
2666                                  10,&global_udp_port_artnet);
2667
2668   prefs_register_enum_preference(artnet_module, "dmx_disp_chan_val_type",
2669             "DMX Display channel value type", 
2670             "The way DMX values are displayed", 
2671                                  &global_disp_chan_val_type,
2672                                  disp_chan_val_types, FALSE);
2673
2674   prefs_register_enum_preference(artnet_module, "dmx_disp_chan_nr_type",
2675             "DMX Display channel nr. type",
2676             "The way DMX channel numbers are displayed",
2677                                  &global_disp_chan_nr_type,
2678                                  disp_chan_nr_types, FALSE);
2679
2680   prefs_register_enum_preference(artnet_module, "dmx_disp_col_count",
2681             "DMX Display Column Count",
2682             "The number of columns for the DMX display",
2683                                  &global_disp_col_count,
2684                                  col_count, FALSE);
2685 }
2686
2687 /* The registration hand-off routing */
2688
2689 void
2690 proto_reg_handoff_artnet(void) {
2691   static gboolean artnet_initialized = FALSE;
2692   static dissector_handle_t artnet_handle;
2693   static guint udp_port_artnet;
2694
2695   if(!artnet_initialized) {
2696     artnet_handle = create_dissector_handle(dissect_artnet,proto_artnet);
2697     rdm_handle = find_dissector("rdm");
2698     artnet_initialized = TRUE;
2699   } else {
2700     dissector_delete("udp.port",udp_port_artnet,artnet_handle);
2701   }
2702
2703   udp_port_artnet = global_udp_port_artnet;
2704   
2705   dissector_add("udp.port",global_udp_port_artnet,artnet_handle);
2706 }