name change
[obnox/wireshark/wip.git] / plugins / artnet / 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 guint udp_port_artnet = UDP_PORT_ARTNET;
483 static guint global_disp_chan_val_type = 0;
484 static guint global_disp_col_count = 16;
485 static guint global_disp_chan_nr_type = 0;
486
487 /* A static handle for the ip dissector */
488 static dissector_handle_t ip_handle;
489 static dissector_handle_t rdm_handle;
490
491 static guint
492 dissect_artnet_poll(tvbuff_t *tvb, guint offset, proto_tree *tree)
493 {
494   guint8 talktome;
495   proto_tree *flags_tree, *flags_item;
496
497   talktome = tvb_get_guint8(tvb, offset);
498   flags_item = proto_tree_add_uint(tree, hf_artnet_poll_talktome, tvb,
499                                    offset, 1, talktome);
500
501   flags_tree=proto_item_add_subtree(flags_item, ett_artnet);
502   proto_tree_add_item(flags_tree, hf_artnet_poll_talktome_reply_dest, tvb, offset, 1, FALSE);
503   proto_tree_add_item(flags_tree, hf_artnet_poll_talktome_reply_type, tvb, offset, 1, FALSE);
504   proto_tree_add_item(flags_tree, hf_artnet_poll_talktome_unused, tvb, offset, 1, FALSE);
505
506   offset += 1;
507
508   proto_tree_add_item(tree, hf_artnet_filler, tvb,
509                       offset, 1, FALSE);
510   offset += 1;
511
512   return offset;
513 }
514
515 static guint
516 dissect_artnet_poll_reply(tvbuff_t *tvb, guint offset, proto_tree *tree)
517 {
518   proto_tree *hi,*si,*ti;
519   guint8 swin,swout,swvideo,swmacro,swremote;
520   guint8 port_types,good_input,good_output;
521   guint16 num_ports;
522
523   proto_tree_add_item(tree, hf_artnet_poll_reply_ip_address, tvb,
524                       offset, 4, FALSE);
525   offset += 4;
526
527   proto_tree_add_item(tree, hf_artnet_poll_reply_port_nr, tvb,
528                       offset, 2, TRUE);
529   offset += 2;
530
531   proto_tree_add_item(tree, hf_artnet_poll_reply_versinfo, tvb,
532                       offset, 2, FALSE);
533   offset += 2;
534
535   proto_tree_add_item(tree, hf_artnet_poll_reply_subswitch, tvb,
536                       offset, 2, FALSE);
537   offset += 2;
538
539   proto_tree_add_item(tree, hf_artnet_poll_reply_oem, tvb,
540                       offset, 2, FALSE);
541   offset += 2;
542
543   proto_tree_add_item(tree, hf_artnet_poll_reply_ubea_version, tvb,
544                       offset, 1, FALSE);
545   offset += 1;
546
547   proto_tree_add_item(tree, hf_artnet_poll_reply_status, tvb,
548                       offset, 1, FALSE);
549   offset += 1;
550
551   proto_tree_add_item(tree, hf_artnet_poll_reply_esta_man, tvb,
552                       offset, 2, TRUE);
553   offset += 2;
554
555   proto_tree_add_item(tree, hf_artnet_poll_reply_short_name,
556                       tvb, offset, 18, FALSE);
557   offset += 18;
558
559   proto_tree_add_item(tree, hf_artnet_poll_reply_long_name,
560                       tvb, offset, 64, FALSE);
561   offset += 64;
562
563   proto_tree_add_item(tree, hf_artnet_poll_reply_node_report,
564                       tvb, offset, 64, FALSE);
565   offset += 64;
566
567
568   hi = proto_tree_add_item(tree,
569                            hf_artnet_poll_reply_port_info,
570                            tvb,
571                            offset,
572                            ARTNET_POLL_REPLY_PORT_INFO_LENGTH,
573                            FALSE);
574
575   si = proto_item_add_subtree(hi, ett_artnet);
576
577   num_ports = tvb_get_ntohs(tvb, offset);
578   proto_tree_add_uint(si, hf_artnet_poll_reply_num_ports, tvb,
579                       offset, 2, num_ports);
580   offset += 2;
581
582   hi = proto_tree_add_item(si,
583                            hf_artnet_poll_reply_port_types,
584                            tvb,
585                            offset,
586                            ARTNET_POLL_REPLY_PORT_TYPES_LENGTH,
587                            FALSE);
588
589   ti = proto_item_add_subtree(hi, ett_artnet);
590
591   port_types = tvb_get_guint8(tvb, offset);
592   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_1, tvb,
593                       offset, 1, port_types);
594   offset += 1;
595
596   port_types = tvb_get_guint8(tvb, offset);
597   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_2, tvb,
598                       offset, 1, port_types);
599   offset += 1;
600
601   port_types = tvb_get_guint8(tvb, offset);
602   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_3, tvb,
603                       offset, 1, port_types);
604   offset += 1;
605
606   port_types = tvb_get_guint8(tvb, offset);
607   proto_tree_add_uint(ti, hf_artnet_poll_reply_port_types_4, tvb,
608                       offset, 1, port_types);
609   offset += 1;
610
611   hi = proto_tree_add_item(si,
612                            hf_artnet_poll_reply_good_input,
613                            tvb,
614                            offset,
615                            ARTNET_POLL_REPLY_GOOD_INPUT_LENGTH,
616                            FALSE);
617
618   ti = proto_item_add_subtree(hi, ett_artnet);
619
620   good_input = tvb_get_guint8(tvb, offset);
621   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_1, tvb,
622                       offset, 1, good_input);
623   offset += 1;
624
625   good_input = tvb_get_guint8(tvb, offset);
626   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_2, tvb,
627                       offset, 1, good_input);
628   offset += 1;
629
630   good_input = tvb_get_guint8(tvb, offset);
631   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_3, tvb,
632                       offset, 1, good_input);
633   offset += 1;
634
635   good_input = tvb_get_guint8(tvb, offset);
636   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_input_4, tvb,
637                       offset, 1, good_input);
638   offset += 1;
639
640   hi = proto_tree_add_item(si,
641                            hf_artnet_poll_reply_good_output,
642                            tvb,
643                            offset,
644                            ARTNET_POLL_REPLY_GOOD_OUTPUT_LENGTH,
645                            FALSE);
646
647   ti = proto_item_add_subtree(hi, ett_artnet);
648
649   good_output = tvb_get_guint8(tvb, offset);
650   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_1, tvb,
651                       offset, 1, good_output);
652   offset += 1;
653
654   good_output = tvb_get_guint8(tvb, offset);
655   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_2, tvb,
656                       offset, 1, good_output);
657   offset += 1;
658
659   good_output = tvb_get_guint8(tvb, offset);
660   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_3, tvb,
661                       offset, 1, good_output);
662   offset += 1;
663
664   good_output = tvb_get_guint8(tvb, offset);
665   proto_tree_add_uint(ti, hf_artnet_poll_reply_good_output_4, tvb,
666                       offset, 1, good_output);
667   offset += 1;
668
669   hi = proto_tree_add_item(si,
670                            hf_artnet_poll_reply_swin,
671                            tvb,
672                            offset,
673                            ARTNET_POLL_REPLY_SWIN_LENGTH,
674                            FALSE);
675
676   ti = proto_item_add_subtree(hi, ett_artnet);
677
678   swin = tvb_get_guint8(tvb, offset);
679   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_1, tvb,
680                       offset, 1, swin);
681   offset += 1;
682
683   swin = tvb_get_guint8(tvb, offset);
684   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_2, tvb,
685                       offset, 1, swin);
686   offset += 1;
687
688   swin = tvb_get_guint8(tvb, offset);
689   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_3, tvb,
690                       offset, 1, swin);
691   offset += 1;
692
693   swin = tvb_get_guint8(tvb, offset);
694   proto_tree_add_uint(ti, hf_artnet_poll_reply_swin_4, tvb,
695                       offset, 1, swin);
696   offset += 1;
697
698   hi = proto_tree_add_item(si,
699                            hf_artnet_poll_reply_swout,
700                            tvb,
701                            offset,
702                            ARTNET_POLL_REPLY_SWOUT_LENGTH,
703                            FALSE);
704
705   ti = proto_item_add_subtree(hi, ett_artnet);
706
707   swout = tvb_get_guint8(tvb, offset);
708   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_1, tvb,
709                       offset, 1, swout);
710   offset += 1;
711
712   swout = tvb_get_guint8(tvb, offset);
713   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_2, tvb,
714                       offset, 1, swout);
715   offset += 1;
716
717   swout = tvb_get_guint8(tvb, offset);
718   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_3, tvb,
719                       offset, 1, swout);
720   offset += 1;
721
722   swout = tvb_get_guint8(tvb, offset);
723   proto_tree_add_uint(ti, hf_artnet_poll_reply_swout_4, tvb,
724                       offset, 1, swout);
725   offset += 1;
726
727   swvideo = tvb_get_guint8(tvb, offset);
728   proto_tree_add_uint(tree, hf_artnet_poll_reply_swvideo, tvb,
729                       offset, 1, swvideo);
730   offset += 1;
731
732   swmacro = tvb_get_guint8(tvb, offset);
733   proto_tree_add_uint(tree, hf_artnet_poll_reply_swmacro, tvb,
734                       offset, 1, swmacro);
735   offset += 1;
736
737   swremote = tvb_get_guint8(tvb, offset);
738   proto_tree_add_uint(tree, hf_artnet_poll_reply_swremote, tvb,
739                       offset, 1, swremote);
740   offset += 1;
741
742   proto_tree_add_item(tree, hf_artnet_spare, tvb,
743                       offset, 4, FALSE);
744   offset += 4;
745
746   proto_tree_add_item(tree, hf_artnet_poll_reply_mac,
747                         tvb, offset, 6, FALSE);
748
749   offset += 6;
750
751   return offset;
752 }
753
754 static guint
755 dissect_artnet_output(tvbuff_t *tvb, guint offset, proto_tree *tree)
756 {
757   proto_tree *hi,*si;
758   guint16 length,r,c,row_count;
759   guint8 v;
760   static char string[255];
761   char* ptr;
762   const char* chan_format[] = {
763     "%2u ",
764     "%02x ",
765     "%3u "
766   };
767   const char* string_format[] = {
768     "%03x: %s",
769     "%3u: %s"
770   };
771
772   proto_tree_add_item(tree, hf_artnet_output_sequence, tvb,
773                       offset, 1, FALSE);
774   offset += 1;
775
776   proto_tree_add_item(tree, hf_artnet_output_physical, tvb,
777                       offset, 1, FALSE);
778   offset += 1;
779
780   proto_tree_add_item(tree, hf_artnet_output_universe, tvb,
781                       offset, 2, TRUE);
782   offset += 2;
783
784   length = tvb_get_ntohs(tvb, offset);
785   proto_tree_add_uint(tree, hf_artnet_output_length, tvb,
786                       offset, 2, length);
787   offset += 2;
788
789   hi = proto_tree_add_item(tree,
790                            hf_artnet_output_data,
791                            tvb,
792                            offset,
793                            length,
794                            FALSE);
795                                                                                                                 
796   si = proto_item_add_subtree(hi, ett_artnet);
797
798   row_count = (length/global_disp_col_count) + ((length%global_disp_col_count) == 0 ? 0 : 1);
799   ptr = string;
800   for (r=0; r < row_count;r++) {
801     for (c=0;(c < global_disp_col_count) && (((r*global_disp_col_count)+c) < length);c++) {
802       if ((c % (global_disp_col_count/2)) == 0) {
803         sprintf(ptr, " ");
804         ptr++;
805       }
806
807       v = tvb_get_guint8(tvb, (offset+(r*global_disp_col_count)+c));
808       if (global_disp_chan_val_type == 0) {
809         v = (v * 100) / 255;
810         if (v == 100) {
811           sprintf(ptr, "FL ");
812         } else {
813           sprintf(ptr, chan_format[global_disp_chan_val_type], v);
814         }
815       } else {
816         sprintf(ptr, chan_format[global_disp_chan_val_type], v);
817       }
818       ptr += strlen(ptr);
819     }
820     
821     proto_tree_add_none_format(si,hf_artnet_output_dmx_data, tvb,
822                                offset+(r*global_disp_col_count), c, 
823                                string_format[global_disp_chan_nr_type], (r*global_disp_col_count)+1, string);
824     ptr = string;
825   }
826
827   /* Add the real type hidden */
828   proto_tree_add_item_hidden(si, hf_artnet_output_data_filter, tvb,
829                       offset, length, FALSE );
830   offset += length;
831
832   return offset;
833 }
834
835 static guint
836 dissect_artnet_address(tvbuff_t *tvb, guint offset, proto_tree *tree) {
837   proto_tree *hi,*si,*ti;
838   guint8 swin,swout,swvideo,command;
839
840   proto_tree_add_item(tree, hf_artnet_filler, tvb,
841                       offset, 2, FALSE);
842   offset += 2;
843
844   proto_tree_add_item(tree, hf_artnet_address_short_name,
845                       tvb, offset, 18, FALSE);
846   offset += 18;
847
848   proto_tree_add_item(tree, hf_artnet_address_long_name,
849                       tvb, offset, 64, FALSE);
850   offset += 64;
851
852   hi = proto_tree_add_item(tree,
853                            hf_artnet_address_swin,
854                            tvb,
855                            offset,
856                            ARTNET_ADDRESS_SWIN_LENGTH,
857                            FALSE);
858
859   ti = proto_item_add_subtree(hi, ett_artnet);
860
861   swin = tvb_get_guint8(tvb, offset);
862   proto_tree_add_uint(ti, hf_artnet_address_swin_1, tvb,
863                       offset, 1, swin);
864   offset += 1;
865
866   swin = tvb_get_guint8(tvb, offset);
867   proto_tree_add_uint(ti, hf_artnet_address_swin_2, 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_3, 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_4, tvb,
878                       offset, 1, swin);
879   offset += 1;
880
881   hi = proto_tree_add_item(tree,
882                            hf_artnet_address_swout,
883                            tvb,
884                            offset,
885                            ARTNET_ADDRESS_SWOUT_LENGTH,
886                            FALSE);
887
888   si = proto_item_add_subtree(hi, ett_artnet);
889
890   swout = tvb_get_guint8(tvb, offset);
891   proto_tree_add_uint(si, hf_artnet_address_swout_1, tvb,
892                       offset, 1, swout);
893   offset += 1;
894
895   swout = tvb_get_guint8(tvb, offset);
896   proto_tree_add_uint(si, hf_artnet_address_swout_2, 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_3, 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_4, tvb,
907                       offset, 1, swout);
908   offset += 1;
909
910   swvideo = tvb_get_guint8(tvb, offset);
911   proto_tree_add_uint(tree, hf_artnet_address_swvideo, tvb,
912                       offset, 1, swvideo);
913   offset += 1;
914
915   command = tvb_get_guint8(tvb, offset);
916   proto_tree_add_uint(tree, hf_artnet_address_command, tvb,
917                       offset, 1, command);
918
919   offset += 1;
920
921   return offset;
922 }
923
924 static guint
925 dissect_artnet_input(tvbuff_t *tvb, guint offset, proto_tree *tree) {
926   proto_tree *hi,*si;
927   guint16 num_ports;
928   guint8 input;
929
930   proto_tree_add_item(tree, hf_artnet_filler, tvb,
931                       offset, 2, FALSE);
932   offset += 2;
933
934   num_ports = tvb_get_letohs(tvb, offset);
935   proto_tree_add_uint(tree, hf_artnet_input_num_ports, tvb,
936                       offset, 2, num_ports);
937   offset += 2;
938
939   hi = proto_tree_add_item(tree,
940                            hf_artnet_input_input,
941                            tvb,
942                            offset,
943                            ARTNET_INPUT_INPUT_LENGTH,
944                            FALSE);
945
946   si = proto_item_add_subtree(hi, ett_artnet);
947
948   input = tvb_get_guint8(tvb, offset);
949   proto_tree_add_uint(si, hf_artnet_input_input_1, tvb,
950                       offset, 1, input);
951   offset += 1;
952
953   input = tvb_get_guint8(tvb, offset);
954   proto_tree_add_uint(si, hf_artnet_input_input_2, 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_3, 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_4, tvb,
965                       offset, 1, input);
966   offset += 1;
967
968   return offset;
969 }
970
971 static guint
972 dissect_artnet_video_setup(tvbuff_t *tvb, guint offset, proto_tree *tree ) {
973   guint32 size;
974   guint8 control,font_height, last_font,first_font;
975
976   proto_tree_add_item(tree, hf_artnet_filler, tvb,
977                       offset, 4, FALSE);
978   offset += 4;
979
980   control = tvb_get_guint8(tvb, offset);
981   proto_tree_add_uint(tree, hf_artnet_video_setup_control, tvb,
982                       offset, 1, control);
983   offset += 1;
984
985   font_height = tvb_get_guint8(tvb, offset);
986   proto_tree_add_uint(tree, hf_artnet_video_setup_font_height, tvb,
987                       offset, 1, font_height);
988   offset += 1;
989
990   first_font = tvb_get_guint8(tvb, offset);
991   proto_tree_add_uint(tree, hf_artnet_video_setup_first_font, tvb,
992                       offset, 1, first_font);
993   offset += 1;
994
995   last_font = tvb_get_guint8(tvb, offset);
996   proto_tree_add_uint(tree, hf_artnet_video_setup_last_font, tvb,
997                       offset, 1, last_font);
998   offset += 1;
999
1000   proto_tree_add_item(tree, hf_artnet_video_setup_win_font_name,
1001                       tvb, offset, 64, FALSE);
1002   offset += 64;
1003
1004   size = last_font * font_height;
1005
1006   proto_tree_add_item(tree, hf_artnet_video_setup_font_data, tvb,
1007                       offset, size, FALSE );
1008
1009   offset += size;
1010
1011   return offset;
1012 }
1013
1014 static guint
1015 dissect_artnet_video_palette(tvbuff_t *tvb, guint offset, proto_tree *tree)
1016 {
1017   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1018                       offset, 2, FALSE);
1019   offset += 2;
1020
1021   proto_tree_add_item(tree, hf_artnet_video_palette_colour_red, tvb,
1022                       offset, 17, FALSE );
1023   offset += 17;
1024
1025   proto_tree_add_item(tree, hf_artnet_video_palette_colour_green, tvb,
1026                       offset, 17, FALSE );
1027   offset += 17;
1028
1029   proto_tree_add_item(tree, hf_artnet_video_palette_colour_blue, tvb,
1030                       offset, 17, FALSE );
1031   offset += 17;
1032
1033   return offset;
1034 }
1035
1036 static guint
1037 dissect_artnet_video_data(tvbuff_t *tvb, guint offset, proto_tree *tree) {
1038   guint8 len_x, len_y;
1039   guint32 size;
1040
1041   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1042                       offset, 2, FALSE);
1043   offset += 2;
1044
1045   proto_tree_add_item(tree, hf_artnet_video_data_pos_x, tvb,
1046                       offset, 1, FALSE);
1047   offset += 1;
1048
1049   proto_tree_add_item(tree, hf_artnet_video_data_pos_y, tvb,
1050                       offset, 1, FALSE);
1051   offset += 1;
1052
1053   len_x = tvb_get_guint8(tvb, offset);
1054   proto_tree_add_uint(tree, hf_artnet_video_data_len_x, tvb,
1055                       offset, 1, len_x);
1056   offset += 1;
1057
1058   len_y = tvb_get_guint8(tvb, offset);
1059   proto_tree_add_uint(tree, hf_artnet_video_data_len_y, tvb,
1060                       offset, 1, len_y);
1061   offset += 1;
1062
1063   size = len_x * len_y * 2;
1064
1065   proto_tree_add_item(tree, hf_artnet_video_data_data, tvb,
1066                       offset, size, FALSE );
1067
1068   offset += size;
1069
1070   return offset;
1071 }
1072
1073 static guint
1074 dissect_artnet_firmware_master(tvbuff_t *tvb, guint offset, proto_tree *tree ) {
1075   guint8 type,block_id;
1076   guint32 length;
1077
1078   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1079                       offset, 2, FALSE);
1080   offset += 2;
1081
1082   type = tvb_get_guint8(tvb, offset);
1083   proto_tree_add_uint(tree, hf_artnet_firmware_master_type, tvb,
1084                       offset, 1, type);
1085   offset += 1;
1086
1087   block_id = tvb_get_guint8(tvb, offset);
1088   proto_tree_add_uint(tree, hf_artnet_firmware_master_block_id, tvb,
1089                       offset, 1, block_id);
1090   offset += 1;
1091
1092   length = tvb_get_ntohl(tvb, offset);
1093   proto_tree_add_uint(tree, hf_artnet_firmware_master_length, tvb,
1094                       offset, 4, length);
1095   offset += 4;
1096
1097   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1098                       offset, 20, FALSE );
1099
1100   offset += 20;
1101
1102   proto_tree_add_item(tree, hf_artnet_firmware_master_data, tvb,
1103                       offset, 1024, FALSE );
1104
1105   offset += 1024;
1106
1107   return offset;
1108 }
1109
1110 static guint
1111 dissect_artnet_firmware_reply(tvbuff_t *tvb, guint offset, proto_tree *tree) {
1112   guint8 type;
1113
1114   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1115                       offset, 2, FALSE);
1116   offset += 2;
1117
1118   type = tvb_get_guint8(tvb, offset);
1119   proto_tree_add_uint(tree, hf_artnet_firmware_reply_type, tvb,
1120                       offset, 1, type);
1121   offset += 1;
1122
1123   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1124                       offset, 21, FALSE );
1125
1126   offset += 21;
1127
1128   return offset;
1129 }
1130
1131 static guint
1132 dissect_artnet_tod_request(tvbuff_t *tvb, guint offset, proto_tree *tree)
1133 {
1134   guint8 ad_count;
1135
1136   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1137                       offset, 2, FALSE);
1138   offset += 2;
1139
1140   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1141                       offset, 8, FALSE);
1142   offset += 8;
1143
1144   proto_tree_add_item(tree, hf_artnet_tod_request_command, tvb,
1145                       offset, 1, FALSE);
1146   offset += 1;
1147
1148   ad_count = tvb_get_guint8(tvb, offset);
1149   proto_tree_add_uint(tree, hf_artnet_tod_request_ad_count, tvb,
1150                       offset, 1, ad_count);
1151   offset += 1;
1152
1153   proto_tree_add_item(tree, hf_artnet_tod_request_address, tvb,
1154                       offset, ad_count, FALSE);
1155   offset += ad_count;
1156
1157   return offset;
1158 }
1159
1160 static guint
1161 dissect_artnet_tod_data(tvbuff_t *tvb, guint offset, proto_tree *tree)
1162 {
1163   guint8 i,uid_count;
1164
1165   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1166                       offset, 1, FALSE);
1167   offset += 1;
1168
1169   proto_tree_add_item(tree, hf_artnet_tod_data_port, tvb,
1170                       offset, 1, FALSE);
1171   offset += 1;
1172
1173   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1174                       offset, 8, FALSE);
1175   offset += 8;
1176
1177   proto_tree_add_item(tree, hf_artnet_tod_data_command_response, tvb,
1178                       offset, 1, FALSE);
1179   offset += 1;
1180
1181   proto_tree_add_item(tree, hf_artnet_tod_data_address, tvb,
1182                       offset, 1, FALSE);
1183   offset += 1;
1184
1185   proto_tree_add_item(tree, hf_artnet_tod_data_uid_total, tvb,
1186                       offset, 2, FALSE);
1187   offset += 2;
1188
1189   proto_tree_add_item(tree, hf_artnet_tod_data_block_count, tvb,
1190                       offset, 1, FALSE);
1191   offset += 1;
1192
1193   uid_count = tvb_get_guint8(tvb, offset);
1194   proto_tree_add_uint(tree, hf_artnet_tod_data_uid_count, tvb,
1195                       offset, 1, uid_count);
1196   offset += 1;
1197
1198   for( i = 0; i < uid_count; i++)
1199   {
1200     proto_tree_add_item(tree, hf_artnet_tod_data_tod, tvb,
1201                         offset, 6, FALSE);
1202     offset += 6;
1203   }
1204
1205   return offset;
1206 }
1207
1208 static guint
1209 dissect_artnet_tod_control(tvbuff_t *tvb, guint offset, proto_tree *tree)
1210 {
1211   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1212                       offset, 2, FALSE);
1213   offset += 2;
1214
1215   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1216                       offset, 8, FALSE);
1217   offset += 8;
1218
1219   proto_tree_add_item(tree, hf_artnet_tod_control_command, tvb,
1220                       offset, 1, FALSE);
1221   offset += 1;
1222
1223   proto_tree_add_item(tree, hf_artnet_tod_control_address, tvb,
1224                       offset, 1, FALSE);
1225   offset += 1;
1226
1227   return offset;
1228 }
1229
1230 static guint
1231 dissect_artnet_rdm(tvbuff_t *tvb, guint offset, proto_tree *tree,  packet_info *pinfo)
1232 {
1233   guint size;
1234   gboolean save_info;
1235   tvbuff_t *next_tvb = NULL;
1236
1237   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1238                       offset, 2, FALSE);
1239   offset += 2;
1240
1241   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1242                       offset, 8, FALSE);
1243   offset += 8;
1244
1245   proto_tree_add_item(tree, hf_artnet_rdm_command, tvb,
1246                       offset, 1, FALSE);
1247   offset += 1;
1248
1249   proto_tree_add_item(tree, hf_artnet_rdm_address, tvb,
1250                       offset, 1, FALSE);
1251   offset += 1;
1252
1253   size = tvb_reported_length_remaining(tvb, offset);
1254
1255   save_info=col_get_writable(pinfo->cinfo); 
1256   col_set_writable(pinfo->cinfo, FALSE);
1257
1258   if (!next_tvb)
1259     next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1260  
1261   call_dissector(rdm_handle, next_tvb, pinfo, tree);
1262
1263   col_set_writable(pinfo->cinfo, save_info);
1264   
1265   size = tvb_reported_length_remaining(tvb, offset) - size;
1266
1267   return offset + size;
1268 }
1269
1270 static guint
1271 dissect_artnet_ip_prog(tvbuff_t *tvb, guint offset, proto_tree *tree) {
1272   guint8 command;
1273   proto_tree *flags_tree,*flags_item;
1274
1275   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1276                       offset, 2, FALSE);
1277   offset += 2;
1278
1279   command = tvb_get_guint8(tvb, offset);
1280   flags_item = proto_tree_add_uint(tree, hf_artnet_ip_prog_command, tvb,
1281                                    offset, 1, command);
1282
1283   flags_tree=proto_item_add_subtree(flags_item, ett_artnet);
1284   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_port, tvb, offset, 1, FALSE);
1285   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_sm, tvb, offset, 1, FALSE);
1286   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_ip, tvb, offset, 1, FALSE);
1287   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_reset, tvb, offset, 1, FALSE);
1288   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_unused, tvb, offset, 1, FALSE);
1289   proto_tree_add_item(flags_tree, hf_artnet_ip_prog_command_prog_enable, tvb, offset, 1, FALSE);
1290
1291   offset += 1;
1292
1293   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1294                       offset, 1, FALSE);
1295   offset += 1;
1296
1297   proto_tree_add_item(tree, hf_artnet_ip_prog_ip, tvb,
1298                       offset, 4, FALSE);
1299   offset += 4;
1300
1301   proto_tree_add_item(tree, hf_artnet_ip_prog_sm, tvb,
1302                       offset, 4, FALSE);
1303   offset += 4;
1304
1305   proto_tree_add_item(tree, hf_artnet_ip_prog_port, tvb,
1306                       offset, 2, FALSE);
1307   offset += 2;
1308
1309   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1310                       offset, 8, FALSE);
1311   offset += 8;
1312
1313   return offset;
1314 }
1315
1316 static guint
1317 dissect_artnet_ip_prog_reply(tvbuff_t *tvb, guint offset, proto_tree *tree)
1318 {
1319   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1320                       offset, 4, FALSE);
1321   offset += 4;
1322
1323   proto_tree_add_item(tree, hf_artnet_ip_prog_reply_ip, tvb,
1324                       offset, 4, FALSE);
1325   offset += 4;
1326
1327   proto_tree_add_item(tree, hf_artnet_ip_prog_reply_sm, tvb,
1328                       offset, 4, FALSE);
1329   offset += 4;
1330
1331   proto_tree_add_item(tree, hf_artnet_ip_prog_reply_port, tvb,
1332                       offset, 2, FALSE);
1333   offset += 2;
1334
1335   proto_tree_add_item(tree, hf_artnet_spare, tvb,
1336                       offset, 8, FALSE);
1337   offset += 8;
1338
1339   return offset;
1340 }
1341
1342 static guint
1343 dissect_artnet_poll_server_reply(tvbuff_t *tvb, guint offset, proto_tree *tree)
1344 {
1345   /* no spec released for this packet at the moment */
1346   proto_tree_add_item(tree, hf_artnet_filler, tvb,
1347                       offset, 182, FALSE);
1348   offset += 182;
1349
1350   return offset;
1351 }
1352
1353
1354 static void
1355 dissect_artnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
1356   gint offset = 0;
1357   guint size;
1358   guint16 opcode;
1359   proto_tree *ti,*hi,*si,*artnet_tree=NULL,*artnet_header_tree=NULL;
1360
1361   /* Set the protocol column */
1362   if(check_col(pinfo->cinfo,COL_PROTOCOL)){
1363     col_set_str(pinfo->cinfo,COL_PROTOCOL,"ARTNET");
1364   }
1365
1366   /* Clear out stuff in the info column */
1367   if(check_col(pinfo->cinfo,COL_INFO)){
1368     col_clear(pinfo->cinfo,COL_INFO);
1369   }
1370
1371   if (tree) {
1372     ti = proto_tree_add_item(tree, proto_artnet, tvb, offset, -1, FALSE);
1373     artnet_tree = proto_item_add_subtree(ti, ett_artnet);
1374
1375     hi = proto_tree_add_item(artnet_tree,
1376                              hf_artnet_header,
1377                              tvb,
1378                              offset,
1379                              ARTNET_HEADER_LENGTH ,
1380                              FALSE);
1381
1382     artnet_header_tree = proto_item_add_subtree(hi, ett_artnet);
1383   }
1384
1385   if (check_col(pinfo->cinfo, COL_INFO)) {
1386     col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1387                     tvb_get_ptr(tvb, offset, 8));
1388   }
1389   if( tree ){
1390     proto_tree_add_item(artnet_header_tree, hf_artnet_header_id,
1391                         tvb, offset, 8, FALSE);
1392   }
1393   offset += 8;
1394
1395   opcode = tvb_get_letohs(tvb, offset);
1396   /* set the info column */
1397   if (check_col(pinfo->cinfo, COL_INFO)) {
1398     col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1399       val_to_str(opcode, artnet_opcode_vals, "Unknown (0x%04x)"));
1400   }
1401
1402   if( tree ){
1403     proto_tree_add_uint(artnet_header_tree, hf_artnet_header_opcode, tvb,
1404                         offset, 2, opcode);
1405   }
1406   offset += 2;
1407
1408   if( opcode != ARTNET_OP_POLL_REPLY && opcode != ARTNET_OP_POLL_SERVER_REPLY ) {
1409     if( tree ){
1410       proto_tree_add_item(artnet_header_tree, hf_artnet_header_protver, tvb,
1411                           offset, 2, FALSE);
1412
1413       proto_item_set_len(artnet_header_tree, ARTNET_HEADER_LENGTH+2 );
1414     }
1415     offset += 2;
1416   }
1417
1418   switch( opcode ) {
1419     case ARTNET_OP_POLL:
1420       if (tree) {
1421         hi = proto_tree_add_item(artnet_tree,
1422                                  hf_artnet_poll,
1423                                  tvb,
1424                                  offset,
1425                                  ARTNET_POLL_LENGTH,
1426                                  FALSE);
1427
1428         si = proto_item_add_subtree(hi, ett_artnet);
1429
1430         size = dissect_artnet_poll( tvb, offset, si );
1431         size -= offset;
1432
1433         proto_item_set_len(si, size);
1434       }
1435       break;
1436
1437     case ARTNET_OP_POLL_REPLY:
1438       if (tree) {
1439         hi = proto_tree_add_item(artnet_tree,
1440                                  hf_artnet_poll_reply,
1441                                  tvb,
1442                                  offset,
1443                                  ARTNET_POLL_REPLY_LENGTH,
1444                                  FALSE);
1445
1446         si = proto_item_add_subtree(hi, ett_artnet);
1447
1448         size = dissect_artnet_poll_reply( tvb, offset, si);
1449         size -= offset;
1450
1451         proto_item_set_len(si, size);
1452       }
1453       break;
1454
1455     case ARTNET_OP_OUTPUT:
1456       if (tree) {
1457         hi = proto_tree_add_item(artnet_tree,
1458                                  hf_artnet_output,
1459                                  tvb,
1460                                  offset,
1461                                  ARTNET_OUTPUT_LENGTH,
1462                                  FALSE);
1463
1464         si = proto_item_add_subtree(hi, ett_artnet);
1465
1466         size = dissect_artnet_output( tvb, offset, si );
1467         size -= offset;
1468
1469         proto_item_set_len(si, size);
1470       }
1471       break;
1472
1473     case ARTNET_OP_ADDRESS:
1474       if (tree) {
1475         hi = proto_tree_add_item(artnet_tree,
1476                                  hf_artnet_address,
1477                                  tvb,
1478                                  offset,
1479                                  ARTNET_POLL_REPLY_LENGTH,
1480                                  FALSE);
1481
1482         si = proto_item_add_subtree(hi, ett_artnet);
1483
1484         size = dissect_artnet_address( tvb, offset, si );
1485         size -= offset;
1486
1487         proto_item_set_len(si, size); 
1488       } 
1489       break;
1490
1491     case ARTNET_OP_INPUT:
1492       if (tree) {
1493         hi = proto_tree_add_item(artnet_tree,
1494                                  hf_artnet_input,
1495                                  tvb,
1496                                  offset,
1497                                  ARTNET_INPUT_LENGTH,
1498                                  FALSE);
1499
1500         si = proto_item_add_subtree(hi, ett_artnet);
1501         
1502         size = dissect_artnet_input( tvb, offset, si );
1503         size -= offset;
1504
1505         proto_item_set_len(si, size);
1506       }
1507       break;
1508
1509     case ARTNET_OP_VIDEO_SETUP:
1510       if (tree) {
1511         hi = proto_tree_add_item(artnet_tree,
1512                                  hf_artnet_input,
1513                                  tvb,
1514                                  offset,
1515                                  ARTNET_VIDEO_SETUP_LENGTH,
1516                                  FALSE);
1517
1518         si = proto_item_add_subtree(hi, ett_artnet);
1519         
1520         size = dissect_artnet_video_setup( tvb, offset, si );
1521         size -= offset;
1522
1523         proto_item_set_len(si, size); 
1524       }
1525       break;
1526
1527     case ARTNET_OP_VIDEO_PALETTE:
1528       if (tree) {
1529         hi = proto_tree_add_item(artnet_tree,
1530                                  hf_artnet_input,
1531                                  tvb,
1532                                  offset,
1533                                  ARTNET_VIDEO_PALETTE_LENGTH,
1534                                  FALSE);
1535
1536         si = proto_item_add_subtree(hi, ett_artnet);
1537
1538         size = dissect_artnet_video_palette( tvb, offset, si );
1539         size -= offset;
1540
1541         proto_item_set_len(si, size);
1542       }
1543       break;
1544
1545     case ARTNET_OP_VIDEO_DATA:
1546       if (tree) {
1547         hi = proto_tree_add_item(artnet_tree,
1548                                  hf_artnet_input,
1549                                  tvb,
1550                                  offset,
1551                                  ARTNET_VIDEO_DATA_LENGTH,
1552                                  FALSE);
1553
1554         si = proto_item_add_subtree(hi, ett_artnet);
1555
1556         size = dissect_artnet_video_data( tvb, offset, si );
1557         size -= offset;
1558
1559         proto_item_set_len(si, size);
1560       }
1561       break;
1562
1563     case ARTNET_OP_FIRMWARE_MASTER:
1564       if (tree) {
1565         hi = proto_tree_add_item(artnet_tree,
1566                                  hf_artnet_firmware_master,
1567                                  tvb,
1568                                  offset,
1569                                  ARTNET_FIRMWARE_MASTER_LENGTH,
1570                                  FALSE);
1571
1572         si = proto_item_add_subtree(hi, ett_artnet);
1573
1574         size = dissect_artnet_firmware_master( tvb, offset, si );
1575         size -= offset;
1576
1577         proto_item_set_len(si, size);
1578       }
1579       break;
1580
1581     case ARTNET_OP_FIRMWARE_REPLY:
1582       if (tree) {
1583         hi = proto_tree_add_item(artnet_tree,
1584                                  hf_artnet_firmware_reply,
1585                                  tvb,
1586                                  offset,
1587                                  ARTNET_FIRMWARE_REPLY_LENGTH,
1588                                  FALSE);
1589
1590         si = proto_item_add_subtree(hi, ett_artnet);
1591
1592         size = dissect_artnet_firmware_reply( tvb, offset, si );
1593         size -= offset;
1594
1595         proto_item_set_len(si, size);
1596       }
1597       break;
1598     
1599     case ARTNET_OP_TOD_REQUEST:
1600       if (tree) {
1601         hi = proto_tree_add_item(artnet_tree,
1602                                  hf_artnet_tod_request,
1603                                  tvb,
1604                                  offset,
1605                                  0,
1606                                  FALSE);
1607
1608         si = proto_item_add_subtree(hi, ett_artnet);
1609
1610         size = dissect_artnet_tod_request( tvb, offset, si );
1611         size -= offset;
1612
1613         proto_item_set_len(si, size);
1614       }
1615       break;
1616
1617     case ARTNET_OP_TOD_DATA:
1618       if (tree) {
1619         hi = proto_tree_add_item(artnet_tree,
1620                                  hf_artnet_tod_data,
1621                                  tvb,
1622                                  offset,
1623                                  0,
1624                                  FALSE);
1625
1626         si = proto_item_add_subtree(hi, ett_artnet );
1627
1628         size = dissect_artnet_tod_data( tvb, offset, si );
1629         size -= offset;
1630
1631         proto_item_set_len(si, size );
1632       }
1633       break;
1634
1635     case ARTNET_OP_TOD_CONTROL:
1636       if (tree){
1637         hi = proto_tree_add_item(artnet_tree,
1638                                  hf_artnet_tod_control,
1639                                  tvb,
1640                                  offset,
1641                                  0,
1642                                  FALSE );
1643         si = proto_item_add_subtree(hi, ett_artnet );
1644
1645         size = dissect_artnet_tod_control( tvb, offset, si );
1646         size -= offset;
1647
1648         proto_item_set_len(si, size );
1649       }
1650       break;
1651
1652     case ARTNET_OP_RDM:
1653       if (tree) {
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       }
1667       break;
1668
1669     case ARTNET_OP_IP_PROG:
1670       if (tree) {
1671         hi = proto_tree_add_item(artnet_tree,
1672                                  hf_artnet_ip_prog,
1673                                  tvb,
1674                                  offset,
1675                                  0,
1676                                  FALSE);
1677         si = proto_item_add_subtree(hi, ett_artnet );
1678
1679         size = dissect_artnet_ip_prog( tvb, offset, si);
1680         size -= offset;
1681
1682         proto_item_set_len(si, size );
1683       }
1684       break;
1685
1686     case ARTNET_OP_IP_PROG_REPLY:
1687       if (tree) {
1688         hi = proto_tree_add_item(artnet_tree,
1689                                  hf_artnet_ip_prog_reply,
1690                                  tvb,
1691                                  offset,
1692                                  0,
1693                                  FALSE);
1694         si = proto_item_add_subtree(hi, ett_artnet );
1695
1696         size = dissect_artnet_ip_prog_reply( tvb, offset, si );
1697         size -= offset;
1698
1699         proto_item_set_len(si, size );
1700       }
1701       break;
1702
1703     case ARTNET_OP_POLL_SERVER_REPLY:
1704       if (tree) {
1705         hi = proto_tree_add_item(artnet_tree,
1706                                  hf_artnet_poll_server_reply,
1707                                  tvb,
1708                                  offset,
1709                                  0,
1710                                  FALSE );
1711         si = proto_item_add_subtree(hi, ett_artnet );
1712
1713         size = dissect_artnet_poll_server_reply( tvb, offset, si );
1714         size -= offset;
1715
1716         proto_item_set_len(si, size );
1717       }
1718       break;
1719
1720     default:
1721       if (tree) {
1722         proto_tree_add_text(artnet_tree, tvb, offset, -1,
1723           "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
1724       }
1725       break;
1726   }
1727
1728
1729
1730 }
1731
1732 void
1733 proto_register_artnet(void) {
1734   static hf_register_info hf[] = {
1735
1736     /* General */
1737
1738     { &hf_artnet_filler,
1739       { "filler",
1740         "artnet.filler",
1741         FT_BYTES, BASE_HEX, NULL, 0x0,
1742         "filler", HFILL }},
1743
1744     { &hf_artnet_spare,
1745       { "spare",
1746         "artnet.spare",
1747         FT_BYTES, BASE_HEX, NULL, 0x0,
1748         "spare", HFILL }},
1749
1750     /* header */
1751
1752     { &hf_artnet_header,
1753       { "Descriptor Header",
1754         "artnet.header",
1755         FT_NONE, BASE_NONE, NULL, 0,
1756         "Art-Net Descriptor Header", HFILL }},
1757
1758     { &hf_artnet_header_id,
1759       { "ID",
1760         "artnet.header.id",
1761         FT_STRING, BASE_DEC, NULL, 0x0,
1762         "ArtNET ID", HFILL }},
1763
1764     { &hf_artnet_header_opcode,
1765       { "Opcode",
1766         "artnet.header.opcode",
1767         FT_UINT16, BASE_HEX, VALS(artnet_opcode_vals), 0x0,
1768         "Art-Net message type", HFILL }},
1769
1770     { &hf_artnet_header_protver,
1771       { "ProVer",
1772         "artnet.header.protver",
1773         FT_UINT16, BASE_DEC, NULL, 0x0,
1774         "Protcol revision number", HFILL }},
1775
1776     /* ArtPoll */
1777
1778     { &hf_artnet_poll,
1779       { "ArtPoll packet",
1780         "artnet.poll",
1781         FT_NONE, BASE_NONE, NULL, 0,
1782         "Art-Net ArtPoll packet", HFILL }},
1783
1784     { &hf_artnet_poll_talktome,
1785       { "TalkToMe",
1786         "artnet.poll.talktome",
1787         FT_UINT8, BASE_HEX, NULL, 0x0,
1788         "TalkToMe", HFILL }},
1789
1790     { &hf_artnet_poll_talktome_reply_dest,
1791       { "Reply destination",
1792         "artnet.poll.talktome_reply_dest",
1793         FT_UINT8, BASE_HEX, NULL, 0x01,
1794         "Reply destination", HFILL }},
1795
1796     { &hf_artnet_poll_talktome_reply_type,
1797       { "Reply type",
1798         "artnet.poll.talktome_reply_type",
1799         FT_UINT8, BASE_HEX, NULL, 0x02,
1800         "Reply type", HFILL }},
1801
1802     { &hf_artnet_poll_talktome_unused,
1803       { "unused",
1804         "artnet.poll.talktome_unused",
1805         FT_UINT8, BASE_HEX, NULL, 0xfc,
1806         "unused", HFILL }},
1807
1808     /* ArtPollReply */
1809
1810     { &hf_artnet_poll_reply,
1811       { "ArtPollReply packet",
1812         "artnet.poll_reply",
1813         FT_NONE, BASE_NONE, NULL, 0,
1814         "Art-Net ArtPollReply packet", HFILL }},
1815
1816     { &hf_artnet_poll_reply_ip_address,
1817       { "IP Address",
1818         "artnet.poll_reply.ip_address",
1819         FT_IPv4, BASE_DEC, NULL, 0x0,
1820         "IP Address", HFILL }},
1821
1822     { &hf_artnet_poll_reply_port_nr,
1823       { "Port number",
1824         "artnet.poll_reply.port_nr",
1825         FT_UINT16, BASE_DEC, NULL, 0x0,
1826         "Port Number", HFILL }},
1827
1828     { &hf_artnet_poll_reply_versinfo,
1829       { "Version Info",
1830         "artnet.poll_reply.versinfo",
1831         FT_UINT16, BASE_HEX, NULL, 0x0,
1832         "Version info", HFILL }},
1833
1834     { &hf_artnet_poll_reply_subswitch,
1835       { "SubSwitch",
1836         "artnet.poll_reply.subswitch",
1837         FT_UINT16, BASE_HEX, NULL, 0x0,
1838         "Subswitch version", HFILL }},
1839
1840     { &hf_artnet_poll_reply_oem,
1841       { "Oem",
1842         "artnet.poll_reply.oem",
1843         FT_UINT16, BASE_HEX, VALS(artnet_oem_code_vals), 0x0,
1844         "OEM", HFILL }},
1845
1846     { &hf_artnet_poll_reply_ubea_version,
1847       { "UBEA Version",
1848         "artnet.poll_reply.ubea_version",
1849         FT_UINT8, BASE_DEC, NULL, 0x0,
1850         "UBEA version number", HFILL }},
1851
1852     { &hf_artnet_poll_reply_status,
1853       { "Status",
1854         "artnet.poll_reply.status",
1855         FT_UINT8, BASE_HEX, NULL, 0x0,
1856         "Status", HFILL }},
1857
1858     { &hf_artnet_poll_reply_esta_man,
1859       { "ESTA Code",
1860         "artnet.poll_reply.esta_man",
1861         FT_UINT16, BASE_HEX, VALS(artnet_esta_man_vals), 0x0,
1862         "ESTA Code", HFILL }},
1863
1864     { &hf_artnet_poll_reply_short_name,
1865       { "Short Name",
1866         "artnet.poll_reply.short_name",
1867         FT_STRING, BASE_DEC, NULL, 0x0,
1868         "Short Name", HFILL }},
1869
1870     { &hf_artnet_poll_reply_long_name,
1871       { "Long Name",
1872         "artnet.poll_reply.long_name",
1873         FT_STRING, BASE_DEC, NULL, 0x0,
1874         "Long Name", HFILL }},
1875
1876     { &hf_artnet_poll_reply_node_report,
1877       { "Node Report",
1878         "artnet.poll_reply.node_report",
1879         FT_STRING, BASE_DEC, NULL, 0x0,
1880         "Node Report", HFILL }},
1881
1882     { &hf_artnet_poll_reply_port_info,
1883       { "Port Info",
1884         "artnet.poll_reply.port_info",
1885         FT_NONE, BASE_NONE, NULL, 0,
1886         "Port Info", HFILL }},
1887
1888     { &hf_artnet_poll_reply_num_ports,
1889       { "Number of Ports",
1890         "artnet.poll_reply.num_ports",
1891         FT_UINT16, BASE_DEC, NULL, 0x0,
1892         "Number of Ports", HFILL }},
1893
1894     { &hf_artnet_poll_reply_port_types,
1895       { "Port Types",
1896         "artnet.poll_reply.port_types",
1897         FT_NONE, BASE_NONE, NULL, 0,
1898         "Port Types", HFILL }},
1899
1900     { &hf_artnet_poll_reply_port_types_1,
1901       { "Type of Port 1",
1902         "artnet.poll_reply.port_types_1",
1903         FT_UINT8, BASE_HEX, NULL, 0x0,
1904         "Type of Port 1", HFILL }},
1905
1906     { &hf_artnet_poll_reply_port_types_2,
1907       { "Type of Port 2",
1908         "artnet.poll_reply.port_types_2",
1909         FT_UINT8, BASE_HEX, NULL, 0x0,
1910         "Type of Port 2", HFILL }},
1911
1912     { &hf_artnet_poll_reply_port_types_3,
1913       { "Type of Port 3",
1914         "artnet.poll_reply.port_types_3",
1915         FT_UINT8, BASE_HEX, NULL, 0x0,
1916         "Type of Port 3", HFILL }},
1917
1918     { &hf_artnet_poll_reply_port_types_4,
1919       { "Type of Port 4",
1920         "artnet.poll_reply.port_types_4",
1921         FT_UINT8, BASE_HEX, NULL, 0x0,
1922         "Type of Port 4", HFILL }},
1923
1924     { &hf_artnet_poll_reply_good_input,
1925       { "Input Status",
1926         "artnet.poll_reply.good_input",
1927         FT_NONE, BASE_NONE, NULL, 0,
1928         "Input Status", HFILL }},
1929
1930     { &hf_artnet_poll_reply_good_input_1,
1931       { "Input status of Port 1",
1932         "artnet.poll_reply.good_input_1",
1933         FT_UINT8, BASE_HEX, NULL, 0x0,
1934         "Input status of Port 1", HFILL }},
1935
1936     { &hf_artnet_poll_reply_good_input_2,
1937       { "Input status of Port 2",
1938         "artnet.poll_reply.good_input_2",
1939         FT_UINT8, BASE_HEX, NULL, 0x0,
1940         "Input status of Port 2", HFILL }},
1941
1942     { &hf_artnet_poll_reply_good_input_3,
1943       { "Input status of Port 3",
1944         "artnet.poll_reply.good_input_3",
1945         FT_UINT8, BASE_HEX, NULL, 0x0,
1946         "Input status of Port 3", HFILL }},
1947
1948     { &hf_artnet_poll_reply_good_input_4,
1949       { "Input status of Port 4",
1950         "artnet.poll_reply.good_input_4",
1951         FT_UINT8, BASE_HEX, NULL, 0x0,
1952         "Input status of Port 4", HFILL }},
1953
1954     { &hf_artnet_poll_reply_good_output,
1955       { "Output Status",
1956         "artnet.poll_reply.good_output",
1957         FT_NONE, BASE_NONE, NULL, 0,
1958         "Port output status", HFILL }},
1959
1960     { &hf_artnet_poll_reply_good_output_1,
1961       { "Output status of Port 1",
1962         "artnet.poll_reply.good_output_1",
1963         FT_UINT8, BASE_HEX, NULL, 0x0,
1964         "Output status of Port 1", HFILL }},
1965
1966     { &hf_artnet_poll_reply_good_output_2,
1967       { "Output status of Port 2",
1968         "artnet.poll_reply.good_output_2",
1969         FT_UINT8, BASE_HEX, NULL, 0x0,
1970         "Output status of Port 2", HFILL }},
1971
1972     { &hf_artnet_poll_reply_good_output_3,
1973       { "Output status of Port 3",
1974         "artnet.poll_reply.good_output_3",
1975         FT_UINT8, BASE_HEX, NULL, 0x0,
1976         "Output status of Port 3", HFILL }},
1977
1978     { &hf_artnet_poll_reply_good_output_4,
1979       { "Output status of Port 4",
1980         "artnet.poll_reply.good_output_4",
1981         FT_UINT8, BASE_HEX, NULL, 0x0,
1982         "Outpus status of Port 4", HFILL }},
1983
1984     { &hf_artnet_poll_reply_swin,
1985       { "Input Subswitch",
1986         "artnet.poll_reply.swin",
1987         FT_NONE, BASE_NONE, NULL, 0,
1988         "Input Subswitch", HFILL }},
1989
1990     { &hf_artnet_poll_reply_swin_1,
1991       { "Input Subswitch of Port 1",
1992         "artnet.poll_reply.swin_1",
1993         FT_UINT8, BASE_HEX, NULL, 0x0,
1994         "Input Subswitch of Port 1", HFILL }},
1995
1996     { &hf_artnet_poll_reply_swin_2,
1997       { "Input Subswitch of Port 2",
1998         "artnet.poll_reply.swin_2",
1999         FT_UINT8, BASE_HEX, NULL, 0x0,
2000         "Input Subswitch of Port 2", HFILL }},
2001
2002     { &hf_artnet_poll_reply_swin_3,
2003       { "Input Subswitch of Port 3",
2004         "artnet.poll_reply.swin_3",
2005         FT_UINT8, BASE_HEX, NULL, 0x0,
2006         "Input Subswitch of Port 3", HFILL }},
2007
2008     { &hf_artnet_poll_reply_swin_4,
2009       { "Input Subswitch of Port 4",
2010         "artnet.poll_reply.swin_4",
2011         FT_UINT8, BASE_HEX, NULL, 0x0,
2012         "Input Subswitch of Port 4", HFILL }},
2013
2014     { &hf_artnet_poll_reply_swout,
2015       { "Output Subswitch",
2016         "artnet.poll_reply.swout",
2017         FT_NONE, BASE_NONE, NULL, 0,
2018         "Output Subswitch", HFILL }},
2019
2020     { &hf_artnet_poll_reply_swout_1,
2021       { "Output Subswitch of Port 1",
2022         "artnet.poll_reply.swout_1",
2023         FT_UINT8, BASE_HEX, NULL, 0x0,
2024         "Output Subswitch of Port 1", HFILL }},
2025
2026     { &hf_artnet_poll_reply_swout_2,
2027       { "Output Subswitch of Port 2",
2028         "artnet.poll_reply.swout_2",
2029         FT_UINT8, BASE_HEX, NULL, 0x0,
2030         "Output Subswitch of Port 2", HFILL }},
2031
2032     { &hf_artnet_poll_reply_swout_3,
2033       { "Output Subswitch of Port 3",
2034         "artnet.poll_reply.swout_3",
2035         FT_UINT8, BASE_HEX, NULL, 0x0,
2036         "Output Subswitch of Port 3", HFILL }},
2037
2038     { &hf_artnet_poll_reply_swout_4,
2039       { "Output Subswitch of Port 4",
2040         "artnet.poll_reply.swout_4",
2041         FT_UINT8, BASE_HEX, NULL, 0x0,
2042         "Ouput Subswitch of Port 4", HFILL }},
2043
2044     { &hf_artnet_poll_reply_swvideo,
2045       { "SwVideo",
2046         "artnet.poll_reply.swvideo",
2047         FT_UINT8, BASE_HEX, NULL, 0x0,
2048         "SwVideo", HFILL }},
2049
2050     { &hf_artnet_poll_reply_swmacro,
2051       { "SwMacro",
2052         "artnet.poll_reply.swmacro",
2053         FT_UINT8, BASE_HEX, NULL, 0x0,
2054         "SwMacro", HFILL }},
2055
2056     { &hf_artnet_poll_reply_swremote,
2057       { "SwRemote",
2058         "artnet.poll_reply.swremote",
2059         FT_UINT8, BASE_HEX, NULL, 0x0,
2060         "SwRemote", HFILL }},
2061
2062     { &hf_artnet_poll_reply_mac,
2063       { "MAC",
2064         "artnet.poll_reply.mac",
2065         FT_ETHER, BASE_HEX, NULL, 0x0,
2066         "MAC", HFILL }},
2067
2068     /* ArtOutput */
2069
2070     { &hf_artnet_output,
2071       { "ArtDMX packet",
2072         "artnet.output",
2073         FT_NONE, BASE_NONE, NULL, 0,
2074         "Art-Net ArtDMX packet", HFILL }},
2075
2076     { &hf_artnet_output_sequence,
2077       { "Sequence",
2078         "artnet.output.sequence",
2079         FT_UINT8, BASE_DEC, NULL, 0x0,
2080         "Sequence", HFILL }},
2081
2082     { &hf_artnet_output_physical,
2083       { "Physical",
2084         "artnet.output.physical",
2085         FT_UINT8, BASE_DEC, NULL, 0x0,
2086         "Physical", HFILL }},
2087
2088     { &hf_artnet_output_universe,
2089       { "Universe",
2090         "artnet.output.universe",
2091         FT_UINT16, BASE_DEC, NULL, 0x0,
2092         "Universe", HFILL }},
2093
2094     { &hf_artnet_output_length,
2095       { "Length",
2096         "artnet.output.length",
2097         FT_UINT16, BASE_DEC, NULL, 0x0,
2098         "Length", HFILL }},
2099
2100     { &hf_artnet_output_data,
2101       { "DMX data",
2102         "artnet.output.data",
2103         FT_NONE, BASE_DEC, NULL, 0x0,
2104         "DMX Data", HFILL }},
2105
2106     { &hf_artnet_output_data_filter,
2107       { "DMX data filter",
2108         "artnet.output.data_filter",
2109         FT_BYTES, BASE_DEC, NULL, 0x0,
2110         "DMX Data Filter", HFILL }},
2111
2112     { &hf_artnet_output_dmx_data,
2113       { "DMX data",
2114         "artnet.output.dmx_data",
2115         FT_NONE, BASE_DEC, NULL, 0x0,
2116         "DMX Data", HFILL }},
2117
2118     /* ArtAddress */
2119
2120     { &hf_artnet_address,
2121       { "ArtAddress packet",
2122         "artnet.address",
2123         FT_NONE, BASE_NONE, NULL, 0,
2124         "Art-Net ArtAddress packet", HFILL }},
2125
2126     { &hf_artnet_address_short_name,
2127       { "Short Name",
2128         "artnet.address.short_name",
2129         FT_STRING, BASE_DEC, NULL, 0x0,
2130         "Short Name", HFILL }},
2131
2132     { &hf_artnet_address_long_name,
2133       { "Long Name",
2134         "artnet.address.long_name",
2135         FT_STRING, BASE_DEC, NULL, 0x0,
2136         "Long Name", HFILL }},
2137
2138     { &hf_artnet_address_swin,
2139       { "Input Subswitch",
2140         "artnet.address.swin",
2141         FT_NONE, BASE_NONE, NULL, 0,
2142         "Input Subswitch", HFILL }},
2143
2144     { &hf_artnet_address_swin_1,
2145       { "Input Subswitch of Port 1",
2146         "artnet.address.swin_1",
2147         FT_UINT8, BASE_HEX, NULL, 0x0,
2148         "Input Subswitch of Port 1", HFILL }},
2149
2150     { &hf_artnet_address_swin_2,
2151       { "Input Subswitch of Port 2",
2152         "artnet.address.swin_2",
2153         FT_UINT8, BASE_HEX, NULL, 0x0,
2154         "Input Subswitch of Port 2", HFILL }},
2155
2156     { &hf_artnet_address_swin_3,
2157       { "Input Subswitch of Port 3",
2158         "artnet.address.swin_3",
2159         FT_UINT8, BASE_HEX, NULL, 0x0,
2160         "Input Subswitch of Port 3", HFILL }},
2161
2162     { &hf_artnet_address_swin_4,
2163       { "Input Subswitch of Port 4",
2164         "artnet.address.swin_4",
2165         FT_UINT8, BASE_HEX, NULL, 0x0,
2166         "Input Subswitch of Port 4", HFILL }},
2167
2168     { &hf_artnet_address_swout,
2169       { "Output Subswitch",
2170         "artnet.address.swout",
2171         FT_NONE, BASE_NONE, NULL, 0,
2172         "Output Subswitch", HFILL }},
2173
2174     { &hf_artnet_address_swout_1,
2175       { "Output Subswitch of Port 1",
2176         "artnet.address.swout_1",
2177         FT_UINT8, BASE_HEX, NULL, 0x0,
2178         "Output Subswitch of Port 1", HFILL }},
2179
2180     { &hf_artnet_address_swout_2,
2181       { "Output Subswitch of Port 2",
2182         "artnet.address.swout_2",
2183         FT_UINT8, BASE_HEX, NULL, 0x0,
2184         "Output Subswitch of Port 2", HFILL }},
2185
2186     { &hf_artnet_address_swout_3,
2187       { "Output Subswitch of Port 3",
2188         "artnet.address.swout_3",
2189         FT_UINT8, BASE_HEX, NULL, 0x0,
2190         "Output Subswitch of Port 3", HFILL }},
2191
2192     { &hf_artnet_address_swout_4,
2193       { "Output Subswitch of Port 4",
2194         "artnet.address.swout_4",
2195         FT_UINT8, BASE_HEX, NULL, 0x0,
2196         "Ouput Subswitch of Port 4", HFILL }},
2197
2198     { &hf_artnet_address_subswitch,
2199       { "Subswitch",
2200         "artnet.address.subswitch",
2201         FT_UINT8, BASE_HEX, NULL, 0x0,
2202         "Subswitch", HFILL }},
2203
2204     { &hf_artnet_address_swvideo,
2205       { "SwVideo",
2206         "artnet.address.swvideo",
2207         FT_UINT8, BASE_HEX, NULL, 0x0,
2208         "SwVideo", HFILL }},
2209
2210     { &hf_artnet_address_command,
2211       { "Command",
2212         "artnet.address.command",
2213         FT_UINT8, BASE_HEX, VALS(artnet_address_command_vals), 0x0,
2214         "Command", HFILL }},
2215
2216     /* ArtInput */
2217
2218     { &hf_artnet_input,
2219       { "ArtInput packet",
2220         "artnet.input",
2221         FT_NONE, BASE_NONE, NULL, 0,
2222         "Art-Net ArtInput packet", HFILL }},
2223
2224     { &hf_artnet_input_num_ports,
2225       { "Number of Ports",
2226         "artnet.input.num_ports",
2227         FT_UINT16, BASE_DEC, NULL, 0x0,
2228         "Number of Ports", HFILL }},
2229
2230     { &hf_artnet_input_input,
2231       { "Port Status",
2232         "artnet.input.input",
2233         FT_NONE, BASE_NONE, NULL, 0,
2234         "Port Status", HFILL }},
2235
2236     { &hf_artnet_input_input_1,
2237       { "Status of Port 1",
2238         "artnet.input.input_1",
2239         FT_UINT8, BASE_HEX, NULL, 0x0,
2240         "Status of Port 1", HFILL }},
2241
2242     { &hf_artnet_input_input_2,
2243       { "Status of Port 2",
2244         "artnet.input.input_2",
2245         FT_UINT8, BASE_HEX, NULL, 0x0,
2246         "Status of Port 2", HFILL }},
2247
2248     { &hf_artnet_input_input_3,
2249       { "Status of Port 3",
2250         "artnet.input.input_3",
2251         FT_UINT8, BASE_HEX, NULL, 0x0,
2252         "Status of Port 3", HFILL }},
2253
2254     { &hf_artnet_input_input_4,
2255       { "Status of Port 4",
2256         "artnet.input.input_4",
2257         FT_UINT8, BASE_HEX, NULL, 0x0,
2258         "Status of Port 4", HFILL }},
2259
2260     /* ArtFirmwareMaster */
2261
2262     { &hf_artnet_firmware_master,
2263       { "ArtFirmwareMaster packet",
2264         "artnet.firmware_master",
2265         FT_NONE, BASE_NONE, NULL, 0,
2266         "Art-Net ArtFirmwareMaster packet", HFILL }},
2267
2268     { &hf_artnet_firmware_master_type,
2269       { "Type",
2270         "artnet.firmware_master.type",
2271         FT_UINT8, BASE_HEX, VALS(artnet_firmware_master_type_vals), 0x0,
2272         "Number of Ports", HFILL }},
2273
2274     { &hf_artnet_firmware_master_block_id,
2275       { "Block ID",
2276         "artnet.firmware_master.block_id",
2277         FT_UINT8, BASE_DEC, NULL, 0x0,
2278         "Block ID", HFILL }},
2279
2280     { &hf_artnet_firmware_master_length,
2281       { "Lentgh",
2282         "artnet.firmware_master.length",
2283         FT_UINT32, BASE_DEC, NULL, 0x0,
2284         "Length", HFILL }},
2285
2286     { &hf_artnet_firmware_master_data,
2287       { "data",
2288         "artnet.firmware_master.data",
2289         FT_BYTES, BASE_HEX, NULL, 0x0,
2290         "data", HFILL }},
2291
2292     /* ArtFirmwareReply */
2293
2294     { &hf_artnet_firmware_reply,
2295       { "ArtFirmwareReply packet",
2296         "artnet.firmware_reply",
2297         FT_NONE, BASE_NONE, NULL, 0,
2298         "Art-Net ArtFirmwareReply packet", HFILL }},
2299
2300     { &hf_artnet_firmware_reply_type,
2301       { "Type",
2302         "artnet.firmware_reply.type",
2303         FT_UINT8, BASE_HEX, VALS(artnet_firmware_reply_type_vals), 0x0,
2304         "Number of Ports", HFILL }},
2305
2306     /* ArtVideoSetup */
2307
2308     { &hf_artnet_video_setup,
2309       { "ArtVideoSetup packet",
2310         "artnet.video_setup",
2311         FT_NONE, BASE_NONE, NULL, 0,
2312         "ArtNET ArtVideoSetup packet", HFILL }},
2313
2314     { &hf_artnet_video_setup_control,
2315       { "control",
2316         "artnet.video_setup.control",
2317         FT_UINT8, BASE_HEX, NULL, 0x0,
2318         "control", HFILL }},
2319
2320     { &hf_artnet_video_setup_font_height,
2321       { "Font Height",
2322         "artnet.video_setup.font_height",
2323         FT_UINT8, BASE_DEC, NULL, 0x0,
2324         "Font Height", HFILL }},
2325
2326     { &hf_artnet_video_setup_first_font,
2327       { "First Font",
2328         "artnet.video_setup.first_font",
2329         FT_UINT8, BASE_DEC, NULL, 0x0,
2330         "First Font", HFILL }},
2331
2332     { &hf_artnet_video_setup_last_font,
2333       { "Last Font",
2334         "artnet.video_setup.last_font",
2335         FT_UINT8, BASE_DEC, NULL, 0x0,
2336         "Last Font", HFILL }},
2337
2338     { &hf_artnet_video_setup_win_font_name,
2339       { "Windows Font Name",
2340         "artnet.video_setup.win_font_name",
2341         FT_STRING, BASE_DEC, NULL, 0x0,
2342         "Windows Font Name", HFILL }},
2343
2344     { &hf_artnet_video_setup_font_data,
2345       { "Font data",
2346         "artnet.video_setup.font_data",
2347         FT_BYTES, BASE_HEX, NULL, 0x0,
2348         "Font Date", HFILL }},
2349
2350     /* ArtVideoPalette */
2351
2352     { &hf_artnet_video_palette,
2353       { "ArtVideoPalette packet",
2354         "artnet.video_palette",
2355         FT_NONE, BASE_NONE, NULL, 0,
2356         "Art-Net ArtVideoPalette packet", HFILL }},
2357
2358     { &hf_artnet_video_palette_colour_red,
2359       { "Colour Red",
2360         "artnet.video_palette.colour_red",
2361         FT_BYTES, BASE_HEX, NULL, 0x0,
2362         "Colour Red", HFILL }},
2363
2364     { &hf_artnet_video_palette_colour_green,
2365       { "Colour Green",
2366         "artnet.video_palette.colour_green",
2367         FT_BYTES, BASE_HEX, NULL, 0x0,
2368         "Colour Green", HFILL }},
2369
2370     { &hf_artnet_video_palette_colour_blue,
2371       { "Colour Blue",
2372         "artnet.video_palette.colour_blue",
2373         FT_BYTES, BASE_HEX, NULL, 0x0,
2374         "Colour Blue", HFILL }},
2375
2376     /* ArtVideoData */
2377
2378     { &hf_artnet_video_data,
2379       { "ArtVideoData packet",
2380         "artnet.video_data",
2381         FT_NONE, BASE_NONE, NULL, 0,
2382         "Art-Net ArtVideoData packet", HFILL }},
2383
2384     { &hf_artnet_video_data_pos_x,
2385       { "PosX",
2386         "artnet.video_data.pos_x",
2387         FT_UINT8, BASE_DEC, NULL, 0x0,
2388         "PosX", HFILL }},
2389
2390     { &hf_artnet_video_data_pos_y,
2391       { "PosY",
2392         "artnet.video_data.pos_y",
2393         FT_UINT8, BASE_DEC, NULL, 0x0,
2394         "PosY", HFILL }},
2395
2396     { &hf_artnet_video_data_len_x,
2397       { "LenX",
2398         "artnet.video_data.len_x",
2399         FT_UINT8, BASE_DEC, NULL, 0x0,
2400         "LenX", HFILL }},
2401
2402     { &hf_artnet_video_data_len_y,
2403       { "LenY",
2404         "artnet.video_data.len_y",
2405         FT_UINT8, BASE_DEC, NULL, 0x0,
2406         "LenY", HFILL }},
2407
2408     { &hf_artnet_video_data_data,
2409       { "Video Data",
2410         "artnet.video_data.data",
2411         FT_BYTES, BASE_HEX, NULL, 0x0,
2412         "Video Data", HFILL }},
2413
2414     /* ArtTodRequest */
2415     { &hf_artnet_tod_request,
2416       { "ArtTodRequest packet",
2417         "artnet.tod_request",
2418         FT_NONE, BASE_NONE, NULL, 0,
2419         "Art-Net ArtTodRequest packet", HFILL }},
2420
2421     { &hf_artnet_tod_request_command,
2422       { "Command",
2423         "artnet.tod_request.command",
2424         FT_UINT8, BASE_HEX, VALS(artnet_tod_request_command_vals), 0x0,
2425         "Command", HFILL }},
2426
2427     { &hf_artnet_tod_request_ad_count,
2428       { "Address Count",
2429         "artnet.tod_request.ad_count",
2430         FT_UINT8, BASE_DEC, NULL, 0x0,
2431         "Address Count", HFILL }},
2432
2433     { &hf_artnet_tod_request_address,
2434       { "Address",
2435         "artnet.tod_request.address",
2436         FT_BYTES, BASE_HEX, NULL, 0x0,
2437         "Address", HFILL }},
2438
2439     /* ArtTodData */
2440     { &hf_artnet_tod_data,
2441       { "ArtTodData packet",
2442         "artnet.tod_data",
2443         FT_NONE, BASE_NONE, NULL, 0,
2444         "Art-Net ArtTodData packet", HFILL }},
2445
2446     { &hf_artnet_tod_data_port,
2447       { "Port",
2448         "artnet.tod_data.port",
2449         FT_UINT8, BASE_DEC, NULL, 0x0,
2450         "Port", HFILL }},
2451
2452     { &hf_artnet_tod_data_command_response,
2453       { "Command Response",
2454         "artnet.tod_data.command_response",
2455         FT_UINT8, BASE_HEX, VALS(artnet_tod_data_command_vals), 0x0,
2456         "Command Response", HFILL }},
2457
2458     { &hf_artnet_tod_data_address,
2459       { "Address",
2460         "artnet.tod_data.address",
2461         FT_UINT8, BASE_HEX, NULL, 0x0,
2462         "Address", HFILL }},
2463
2464     { &hf_artnet_tod_data_uid_total,
2465       { "UID Total",
2466         "artnet.tod_data.uid_total",
2467         FT_UINT16, BASE_DEC, NULL, 0x0,
2468         "UID Total", HFILL }},
2469
2470     { &hf_artnet_tod_data_block_count,
2471       { "Block Count",
2472         "artnet.tod_data.block_count",
2473         FT_UINT8, BASE_DEC, NULL, 0x0,
2474         "Block Count", HFILL }},
2475
2476     { &hf_artnet_tod_data_uid_count,
2477       { "UID Count",
2478         "artnet.tod_data.uid_count",
2479         FT_UINT8, BASE_DEC, NULL, 0x0,
2480         "UID Count", HFILL }},
2481
2482     { &hf_artnet_tod_data_tod,
2483       { "TOD",
2484         "artnet.tod_data.tod",
2485         FT_BYTES, BASE_HEX, NULL, 0x0,
2486         "TOD", HFILL }},
2487
2488     /* ArtTodControl */
2489     { &hf_artnet_tod_control,
2490       { "ArtTodControl packet",
2491         "artner.tod_control",
2492         FT_NONE, BASE_NONE, NULL, 0,
2493         "Art-Net ArtTodControl packet", HFILL }},
2494
2495     { &hf_artnet_tod_control_command,
2496       { "Command",
2497         "artnet.tod_control.command",
2498         FT_UINT8, BASE_HEX, VALS(artnet_tod_control_command_vals), 0x0,
2499         "Command", HFILL }},
2500
2501     { &hf_artnet_tod_control_address,
2502       { "Address",
2503         "artnet.tod_request.address",
2504         FT_UINT8, BASE_HEX, NULL, 0x0,
2505         "Address", HFILL }},
2506
2507     /* ArtRdm */
2508     { &hf_artnet_rdm,
2509       { "ArtRdm packet",
2510         "artnet.rdm",
2511         FT_NONE, BASE_NONE, NULL, 0,
2512         "Art-Net ArtRdm packet", HFILL }},
2513
2514     { &hf_artnet_rdm_command,
2515       { "Command",
2516         "artnet.rdm.command",
2517         FT_UINT8, BASE_HEX, VALS(artnet_rdm_command_vals), 0x0,
2518         "Command", HFILL }},
2519
2520     { &hf_artnet_rdm_address,
2521       { "Address",
2522         "artnet.rdm.address",
2523         FT_UINT8, BASE_HEX, NULL, 0x0,
2524         "Address", HFILL }},
2525
2526     /* ArtIpProg */
2527     { &hf_artnet_ip_prog,
2528       { "ArtIpProg packet",
2529         "artnet.ip_prog",
2530         FT_NONE, BASE_NONE, NULL, 0,
2531         "ArtNET ArtIpProg packet", HFILL }},
2532
2533     { &hf_artnet_ip_prog_command,
2534       { "Command",
2535         "artnet.ip_prog.command",
2536         FT_UINT8, BASE_HEX, NULL, 0x0,
2537         "Command", HFILL }},
2538
2539     { &hf_artnet_ip_prog_command_prog_port,
2540       { "Program Port",
2541         "artnet.ip_prog.command_prog_port",
2542         FT_UINT8, BASE_HEX, NULL, 0x01,
2543         "Program Port", HFILL }},
2544
2545     { &hf_artnet_ip_prog_command_prog_sm,
2546       { "Program Subnet Mask",
2547         "artnet.ip_prog.command_prog_sm",
2548         FT_UINT8, BASE_HEX, NULL, 0x02,
2549         "Program Subnet Mask", HFILL }},
2550
2551     { &hf_artnet_ip_prog_command_prog_ip,
2552       { "Program IP",
2553         "artnet.ip_prog.command_prog_ip",
2554         FT_UINT8, BASE_HEX, NULL, 0x04,
2555         "Program IP", HFILL }},
2556
2557     { &hf_artnet_ip_prog_command_reset,
2558       { "Reset parameters",
2559         "artnet.ip_prog.command_reset",
2560         FT_UINT8, BASE_HEX, NULL, 0x08,
2561         "Reset parameters", HFILL }},
2562
2563     { &hf_artnet_ip_prog_command_unused,
2564       { "Unused",
2565         "artnet.ip_prog.command_unused",
2566         FT_UINT8, BASE_HEX, NULL, 0x70,
2567         "Unused", HFILL }},
2568
2569     { &hf_artnet_ip_prog_command_prog_enable,
2570       { "Enable Programming",
2571         "artnet.ip_prog.command_prog_enable",
2572         FT_UINT8, BASE_HEX, NULL, 0x80,
2573         "Enable Programming", HFILL }},
2574
2575     { &hf_artnet_ip_prog_ip,
2576       { "IP Address",
2577         "artnet.ip_prog.ip",
2578         FT_IPv4, BASE_DEC, NULL, 0x0,
2579         "IP Address", HFILL }},
2580
2581     { &hf_artnet_ip_prog_sm,
2582       { "Subnet mask",
2583         "artnet.ip_prog.sm",
2584         FT_IPv4, BASE_DEC, NULL, 0x0,
2585         "IP Subnet mask", HFILL }},
2586
2587     { &hf_artnet_ip_prog_port,
2588       { "Port",
2589         "artnet.ip_prog.port",
2590         FT_UINT16, BASE_DEC, NULL, 0x0,
2591         "Port", HFILL }},
2592
2593     /* ArtIpProgReply */
2594     { &hf_artnet_ip_prog_reply,
2595       { "ArtIpProgReplay packet",
2596         "artnet.ip_prog_reply",
2597         FT_NONE, BASE_NONE, NULL, 0,
2598         "Art-Net ArtIpProgReply packet", HFILL }},
2599
2600     { &hf_artnet_ip_prog_reply_ip,
2601       { "IP Address",
2602         "artnet.ip_prog_reply.ip",
2603         FT_IPv4, BASE_DEC, NULL, 0x0,
2604         "IP Address", HFILL }},
2605
2606     { &hf_artnet_ip_prog_reply_sm,
2607       { "Subnet mask",
2608         "artnet.ip_prog_reply.sm",
2609         FT_IPv4, BASE_DEC, NULL, 0x0,
2610         "IP Subnet mask", HFILL }},
2611
2612     { &hf_artnet_ip_prog_reply_port,
2613       { "Port",
2614         "artnet.ip_prog_reply.port",
2615         FT_UINT16, BASE_DEC, NULL, 0x0,
2616         "Port", HFILL }},
2617
2618     /* ArtPollServerReply */
2619     { &hf_artnet_poll_server_reply,
2620       { "ArtPollServerReply packet",
2621         "artnet.poll_server_reply",
2622         FT_NONE, BASE_NONE, NULL, 0,
2623         "Art-Net ArtPollServerReply packet", HFILL }}
2624
2625   };
2626
2627   static gint *ett[] = {
2628     &ett_artnet,
2629   };
2630
2631   module_t *artnet_module;
2632
2633   static enum_val_t disp_chan_val_types[] = {
2634      { "pro", "Percent", 0 },
2635      { "hex", "Hexadecimal", 1 },
2636      { "dec", "Decimal", 2 },
2637      { NULL, NULL, 0 }
2638   };
2639
2640   static enum_val_t disp_chan_nr_types[] = {
2641      { "hex", "Hexadecimal", 0 },
2642      { "dec", "Decimal", 1 },
2643      { NULL, NULL, 0 }
2644   };
2645
2646   static enum_val_t col_count[] = {
2647      { "6", "6", 6 },
2648      { "10", "10", 10 },
2649      { "12", "12", 12 },
2650      { "16", "16", 16 },
2651      { "24", "24", 24 },
2652      { NULL, NULL, 0 }
2653   };
2654
2655   proto_artnet = proto_register_protocol("Art-Net",
2656                                        "ARTNET","artnet");
2657   proto_register_field_array(proto_artnet,hf,array_length(hf));
2658   proto_register_subtree_array(ett,array_length(ett));
2659
2660   artnet_module = prefs_register_protocol(proto_artnet,
2661                                         proto_reg_handoff_artnet);
2662   prefs_register_uint_preference(artnet_module, "udp_port",
2663                                  "UDP Port",
2664                                  "The UDP port on which "
2665                                  "Art-Net "
2666                                  "packets will be sent",
2667                                  10,&global_udp_port_artnet);
2668
2669   prefs_register_enum_preference(artnet_module, "dmx_disp_chan_val_type",
2670             "DMX Display channel value type", 
2671             "The way DMX values are displayed", 
2672                                  &global_disp_chan_val_type,
2673                                  disp_chan_val_types, FALSE);
2674
2675   prefs_register_enum_preference(artnet_module, "dmx_disp_chan_nr_type",
2676             "DMX Display channel nr. type",
2677             "The way DMX channel numbers are displayed",
2678                                  &global_disp_chan_nr_type,
2679                                  disp_chan_nr_types, FALSE);
2680
2681   prefs_register_enum_preference(artnet_module, "dmx_disp_col_count",
2682             "DMX Display Column Count",
2683             "The number of columns for the DMX display",
2684                                  &global_disp_col_count,
2685                                  col_count, FALSE);
2686 }
2687
2688 /* The registration hand-off routing */
2689
2690 void
2691 proto_reg_handoff_artnet(void) {
2692   static int artnet_initialized = FALSE;
2693   static dissector_handle_t artnet_handle;
2694
2695   ip_handle = find_dissector("ip");
2696   rdm_handle = find_dissector("rdm");
2697
2698
2699   if(!artnet_initialized) {
2700     artnet_handle = create_dissector_handle(dissect_artnet,proto_artnet);
2701     artnet_initialized = TRUE;
2702   } else {
2703     dissector_delete("udp.port",udp_port_artnet,artnet_handle);
2704   }
2705
2706   udp_port_artnet = global_udp_port_artnet;
2707   
2708   dissector_add("udp.port",global_udp_port_artnet,artnet_handle);
2709 }