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