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