From Kovarththanan Rajaratnam via bug 3548:
[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(tvb, offset, -1, -1);
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   if(check_col(pinfo->cinfo,COL_PROTOCOL)){
1368     col_set_str(pinfo->cinfo,COL_PROTOCOL,"ARTNET");
1369   }
1370
1371   /* Clear out stuff in the info column */
1372   if(check_col(pinfo->cinfo,COL_INFO)){
1373     col_clear(pinfo->cinfo,COL_INFO);
1374   }
1375
1376   if (tree) {
1377     ti = proto_tree_add_item(tree, proto_artnet, tvb, offset, -1, FALSE);
1378     artnet_tree = proto_item_add_subtree(ti, ett_artnet);
1379
1380     hi = proto_tree_add_item(artnet_tree,
1381                              hf_artnet_header,
1382                              tvb,
1383                              offset,
1384                              ARTNET_HEADER_LENGTH ,
1385                              FALSE);
1386
1387     artnet_header_tree = proto_item_add_subtree(hi, ett_artnet);
1388   }
1389
1390   if (check_col(pinfo->cinfo, COL_INFO)) {
1391     col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
1392                     tvb_get_ptr(tvb, offset, 8));
1393   }
1394   if( tree ){
1395     proto_tree_add_item(artnet_header_tree, hf_artnet_header_id,
1396                         tvb, offset, 8, FALSE);
1397   }
1398   offset += 8;
1399
1400   opcode = tvb_get_letohs(tvb, offset);
1401   /* set the info column */
1402   if (check_col(pinfo->cinfo, COL_INFO)) {
1403     col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
1404       val_to_str(opcode, artnet_opcode_vals, "Unknown (0x%04x)"));
1405   }
1406
1407   if( tree ){
1408     proto_tree_add_uint(artnet_header_tree, hf_artnet_header_opcode, tvb,
1409                         offset, 2, opcode);
1410   }
1411   offset += 2;
1412
1413   if( opcode != ARTNET_OP_POLL_REPLY && opcode != ARTNET_OP_POLL_SERVER_REPLY ) {
1414     if( tree ){
1415       proto_tree_add_item(artnet_header_tree, hf_artnet_header_protver, tvb,
1416                           offset, 2, FALSE);
1417
1418       proto_item_set_len(artnet_header_tree, ARTNET_HEADER_LENGTH+2 );
1419     }
1420     offset += 2;
1421   }
1422
1423   switch( opcode ) {
1424     case ARTNET_OP_POLL:
1425       if (tree) {
1426         hi = proto_tree_add_item(artnet_tree,
1427                                  hf_artnet_poll,
1428                                  tvb,
1429                                  offset,
1430                                  ARTNET_POLL_LENGTH,
1431                                  FALSE);
1432
1433         si = proto_item_add_subtree(hi, ett_artnet);
1434
1435         size = dissect_artnet_poll( tvb, offset, si );
1436         size -= offset;
1437
1438         proto_item_set_len(si, size);
1439       }
1440       break;
1441
1442     case ARTNET_OP_POLL_REPLY:
1443       if (tree) {
1444         hi = proto_tree_add_item(artnet_tree,
1445                                  hf_artnet_poll_reply,
1446                                  tvb,
1447                                  offset,
1448                                  ARTNET_POLL_REPLY_LENGTH,
1449                                  FALSE);
1450
1451         si = proto_item_add_subtree(hi, ett_artnet);
1452
1453         size = dissect_artnet_poll_reply( tvb, offset, si);
1454         size -= offset;
1455
1456         proto_item_set_len(si, size);
1457       }
1458       break;
1459
1460     case ARTNET_OP_OUTPUT:
1461       if (tree) {
1462         hi = proto_tree_add_item(artnet_tree,
1463                                  hf_artnet_output,
1464                                  tvb,
1465                                  offset,
1466                                  ARTNET_OUTPUT_LENGTH,
1467                                  FALSE);
1468
1469         si = proto_item_add_subtree(hi, ett_artnet);
1470
1471         size = dissect_artnet_output( tvb, offset, si );
1472         size -= offset;
1473
1474         proto_item_set_len(si, size);
1475       }
1476       break;
1477
1478     case ARTNET_OP_ADDRESS:
1479       if (tree) {
1480         hi = proto_tree_add_item(artnet_tree,
1481                                  hf_artnet_address,
1482                                  tvb,
1483                                  offset,
1484                                  ARTNET_POLL_REPLY_LENGTH,
1485                                  FALSE);
1486
1487         si = proto_item_add_subtree(hi, ett_artnet);
1488
1489         size = dissect_artnet_address( tvb, offset, si );
1490         size -= offset;
1491
1492         proto_item_set_len(si, size); 
1493       } 
1494       break;
1495
1496     case ARTNET_OP_INPUT:
1497       if (tree) {
1498         hi = proto_tree_add_item(artnet_tree,
1499                                  hf_artnet_input,
1500                                  tvb,
1501                                  offset,
1502                                  ARTNET_INPUT_LENGTH,
1503                                  FALSE);
1504
1505         si = proto_item_add_subtree(hi, ett_artnet);
1506         
1507         size = dissect_artnet_input( tvb, offset, si );
1508         size -= offset;
1509
1510         proto_item_set_len(si, size);
1511       }
1512       break;
1513
1514     case ARTNET_OP_VIDEO_SETUP:
1515       if (tree) {
1516         hi = proto_tree_add_item(artnet_tree,
1517                                  hf_artnet_input,
1518                                  tvb,
1519                                  offset,
1520                                  ARTNET_VIDEO_SETUP_LENGTH,
1521                                  FALSE);
1522
1523         si = proto_item_add_subtree(hi, ett_artnet);
1524         
1525         size = dissect_artnet_video_setup( tvb, offset, si );
1526         size -= offset;
1527
1528         proto_item_set_len(si, size); 
1529       }
1530       break;
1531
1532     case ARTNET_OP_VIDEO_PALETTE:
1533       if (tree) {
1534         hi = proto_tree_add_item(artnet_tree,
1535                                  hf_artnet_input,
1536                                  tvb,
1537                                  offset,
1538                                  ARTNET_VIDEO_PALETTE_LENGTH,
1539                                  FALSE);
1540
1541         si = proto_item_add_subtree(hi, ett_artnet);
1542
1543         size = dissect_artnet_video_palette( tvb, offset, si );
1544         size -= offset;
1545
1546         proto_item_set_len(si, size);
1547       }
1548       break;
1549
1550     case ARTNET_OP_VIDEO_DATA:
1551       if (tree) {
1552         hi = proto_tree_add_item(artnet_tree,
1553                                  hf_artnet_input,
1554                                  tvb,
1555                                  offset,
1556                                  ARTNET_VIDEO_DATA_LENGTH,
1557                                  FALSE);
1558
1559         si = proto_item_add_subtree(hi, ett_artnet);
1560
1561         size = dissect_artnet_video_data( tvb, offset, si );
1562         size -= offset;
1563
1564         proto_item_set_len(si, size);
1565       }
1566       break;
1567
1568     case ARTNET_OP_FIRMWARE_MASTER:
1569       if (tree) {
1570         hi = proto_tree_add_item(artnet_tree,
1571                                  hf_artnet_firmware_master,
1572                                  tvb,
1573                                  offset,
1574                                  ARTNET_FIRMWARE_MASTER_LENGTH,
1575                                  FALSE);
1576
1577         si = proto_item_add_subtree(hi, ett_artnet);
1578
1579         size = dissect_artnet_firmware_master( tvb, offset, si );
1580         size -= offset;
1581
1582         proto_item_set_len(si, size);
1583       }
1584       break;
1585
1586     case ARTNET_OP_FIRMWARE_REPLY:
1587       if (tree) {
1588         hi = proto_tree_add_item(artnet_tree,
1589                                  hf_artnet_firmware_reply,
1590                                  tvb,
1591                                  offset,
1592                                  ARTNET_FIRMWARE_REPLY_LENGTH,
1593                                  FALSE);
1594
1595         si = proto_item_add_subtree(hi, ett_artnet);
1596
1597         size = dissect_artnet_firmware_reply( tvb, offset, si );
1598         size -= offset;
1599
1600         proto_item_set_len(si, size);
1601       }
1602       break;
1603     
1604     case ARTNET_OP_TOD_REQUEST:
1605       if (tree) {
1606         hi = proto_tree_add_item(artnet_tree,
1607                                  hf_artnet_tod_request,
1608                                  tvb,
1609                                  offset,
1610                                  0,
1611                                  FALSE);
1612
1613         si = proto_item_add_subtree(hi, ett_artnet);
1614
1615         size = dissect_artnet_tod_request( tvb, offset, si );
1616         size -= offset;
1617
1618         proto_item_set_len(si, size);
1619       }
1620       break;
1621
1622     case ARTNET_OP_TOD_DATA:
1623       if (tree) {
1624         hi = proto_tree_add_item(artnet_tree,
1625                                  hf_artnet_tod_data,
1626                                  tvb,
1627                                  offset,
1628                                  0,
1629                                  FALSE);
1630
1631         si = proto_item_add_subtree(hi, ett_artnet );
1632
1633         size = dissect_artnet_tod_data( tvb, offset, si );
1634         size -= offset;
1635
1636         proto_item_set_len(si, size );
1637       }
1638       break;
1639
1640     case ARTNET_OP_TOD_CONTROL:
1641       if (tree){
1642         hi = proto_tree_add_item(artnet_tree,
1643                                  hf_artnet_tod_control,
1644                                  tvb,
1645                                  offset,
1646                                  0,
1647                                  FALSE );
1648         si = proto_item_add_subtree(hi, ett_artnet );
1649
1650         size = dissect_artnet_tod_control( tvb, offset, si );
1651         size -= offset;
1652
1653         proto_item_set_len(si, size );
1654       }
1655       break;
1656
1657     case ARTNET_OP_RDM:
1658       if (tree) {
1659         hi = proto_tree_add_item(artnet_tree,
1660                                  hf_artnet_rdm,
1661                                  tvb,
1662                                  offset,
1663                                  0,
1664                                  FALSE);
1665         si = proto_item_add_subtree(hi,ett_artnet);
1666
1667         size = dissect_artnet_rdm( tvb, offset, si, pinfo );
1668         size -= offset;
1669
1670         proto_item_set_len( si, size );
1671       }
1672       break;
1673
1674     case ARTNET_OP_IP_PROG:
1675       if (tree) {
1676         hi = proto_tree_add_item(artnet_tree,
1677                                  hf_artnet_ip_prog,
1678                                  tvb,
1679                                  offset,
1680                                  0,
1681                                  FALSE);
1682         si = proto_item_add_subtree(hi, ett_artnet );
1683
1684         size = dissect_artnet_ip_prog( tvb, offset, si);
1685         size -= offset;
1686
1687         proto_item_set_len(si, size );
1688       }
1689       break;
1690
1691     case ARTNET_OP_IP_PROG_REPLY:
1692       if (tree) {
1693         hi = proto_tree_add_item(artnet_tree,
1694                                  hf_artnet_ip_prog_reply,
1695                                  tvb,
1696                                  offset,
1697                                  0,
1698                                  FALSE);
1699         si = proto_item_add_subtree(hi, ett_artnet );
1700
1701         size = dissect_artnet_ip_prog_reply( tvb, offset, si );
1702         size -= offset;
1703
1704         proto_item_set_len(si, size );
1705       }
1706       break;
1707
1708     case ARTNET_OP_POLL_SERVER_REPLY:
1709       if (tree) {
1710         hi = proto_tree_add_item(artnet_tree,
1711                                  hf_artnet_poll_server_reply,
1712                                  tvb,
1713                                  offset,
1714                                  0,
1715                                  FALSE );
1716         si = proto_item_add_subtree(hi, ett_artnet );
1717
1718         size = dissect_artnet_poll_server_reply( tvb, offset, si );
1719         size -= offset;
1720
1721         proto_item_set_len(si, size );
1722       }
1723       break;
1724
1725     default:
1726       if (tree) {
1727         proto_tree_add_text(artnet_tree, tvb, offset, -1,
1728           "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
1729       }
1730       break;
1731   }
1732
1733
1734
1735 }
1736
1737 void
1738 proto_register_artnet(void) {
1739   static hf_register_info hf[] = {
1740
1741     /* General */
1742
1743     { &hf_artnet_filler,
1744       { "filler",
1745         "artnet.filler",
1746         FT_BYTES, BASE_NONE, NULL, 0x0,
1747         NULL, HFILL }},
1748
1749     { &hf_artnet_spare,
1750       { "spare",
1751         "artnet.spare",
1752         FT_BYTES, BASE_NONE, NULL, 0x0,
1753         NULL, HFILL }},
1754
1755     /* header */
1756
1757     { &hf_artnet_header,
1758       { "Descriptor Header",
1759         "artnet.header",
1760         FT_NONE, BASE_NONE, NULL, 0,
1761         "Art-Net Descriptor Header", HFILL }},
1762
1763     { &hf_artnet_header_id,
1764       { "ID",
1765         "artnet.header.id",
1766         FT_STRING, BASE_NONE, NULL, 0x0,
1767         "ArtNET ID", HFILL }},
1768
1769     { &hf_artnet_header_opcode,
1770       { "Opcode",
1771         "artnet.header.opcode",
1772         FT_UINT16, BASE_HEX, VALS(artnet_opcode_vals), 0x0,
1773         "Art-Net message type", HFILL }},
1774
1775     { &hf_artnet_header_protver,
1776       { "ProVer",
1777         "artnet.header.protver",
1778         FT_UINT16, BASE_DEC, NULL, 0x0,
1779         "Protocol revision number", HFILL }},
1780
1781     /* ArtPoll */
1782
1783     { &hf_artnet_poll,
1784       { "ArtPoll packet",
1785         "artnet.poll",
1786         FT_NONE, BASE_NONE, NULL, 0,
1787         "Art-Net ArtPoll packet", HFILL }},
1788
1789     { &hf_artnet_poll_talktome,
1790       { "TalkToMe",
1791         "artnet.poll.talktome",
1792         FT_UINT8, BASE_HEX, NULL, 0x0,
1793         NULL, HFILL }},
1794
1795     { &hf_artnet_poll_talktome_reply_dest,
1796       { "Reply destination",
1797         "artnet.poll.talktome_reply_dest",
1798         FT_UINT8, BASE_HEX, NULL, 0x01,
1799         NULL, HFILL }},
1800
1801     { &hf_artnet_poll_talktome_reply_type,
1802       { "Reply type",
1803         "artnet.poll.talktome_reply_type",
1804         FT_UINT8, BASE_HEX, NULL, 0x02,
1805         NULL, HFILL }},
1806
1807     { &hf_artnet_poll_talktome_unused,
1808       { "unused",
1809         "artnet.poll.talktome_unused",
1810         FT_UINT8, BASE_HEX, NULL, 0xfc,
1811         NULL, HFILL }},
1812
1813     /* ArtPollReply */
1814
1815     { &hf_artnet_poll_reply,
1816       { "ArtPollReply packet",
1817         "artnet.poll_reply",
1818         FT_NONE, BASE_NONE, NULL, 0,
1819         "Art-Net ArtPollReply packet", HFILL }},
1820
1821     { &hf_artnet_poll_reply_ip_address,
1822       { "IP Address",
1823         "artnet.poll_reply.ip_address",
1824         FT_IPv4, BASE_NONE, NULL, 0x0,
1825         NULL, HFILL }},
1826
1827     { &hf_artnet_poll_reply_port_nr,
1828       { "Port number",
1829         "artnet.poll_reply.port_nr",
1830         FT_UINT16, BASE_DEC, NULL, 0x0,
1831         "Port Number", HFILL }},
1832
1833     { &hf_artnet_poll_reply_versinfo,
1834       { "Version Info",
1835         "artnet.poll_reply.versinfo",
1836         FT_UINT16, BASE_HEX, NULL, 0x0,
1837         "Version info", HFILL }},
1838
1839     { &hf_artnet_poll_reply_subswitch,
1840       { "SubSwitch",
1841         "artnet.poll_reply.subswitch",
1842         FT_UINT16, BASE_HEX, NULL, 0x0,
1843         "Subswitch version", HFILL }},
1844
1845     { &hf_artnet_poll_reply_oem,
1846       { "Oem",
1847         "artnet.poll_reply.oem",
1848         FT_UINT16, BASE_HEX, VALS(artnet_oem_code_vals), 0x0,
1849         "OEM", HFILL }},
1850
1851     { &hf_artnet_poll_reply_ubea_version,
1852       { "UBEA Version",
1853         "artnet.poll_reply.ubea_version",
1854         FT_UINT8, BASE_DEC, NULL, 0x0,
1855         "UBEA version number", HFILL }},
1856
1857     { &hf_artnet_poll_reply_status,
1858       { "Status",
1859         "artnet.poll_reply.status",
1860         FT_UINT8, BASE_HEX, NULL, 0x0,
1861         NULL, HFILL }},
1862
1863     { &hf_artnet_poll_reply_esta_man,
1864       { "ESTA Code",
1865         "artnet.poll_reply.esta_man",
1866         FT_UINT16, BASE_HEX, VALS(artnet_esta_man_vals), 0x0,
1867         NULL, HFILL }},
1868
1869     { &hf_artnet_poll_reply_short_name,
1870       { "Short Name",
1871         "artnet.poll_reply.short_name",
1872         FT_STRING, BASE_NONE, NULL, 0x0,
1873         NULL, HFILL }},
1874
1875     { &hf_artnet_poll_reply_long_name,
1876       { "Long Name",
1877         "artnet.poll_reply.long_name",
1878         FT_STRING, BASE_NONE, NULL, 0x0,
1879         NULL, HFILL }},
1880
1881     { &hf_artnet_poll_reply_node_report,
1882       { "Node Report",
1883         "artnet.poll_reply.node_report",
1884         FT_STRING, BASE_NONE, NULL, 0x0,
1885         NULL, HFILL }},
1886
1887     { &hf_artnet_poll_reply_port_info,
1888       { "Port Info",
1889         "artnet.poll_reply.port_info",
1890         FT_NONE, BASE_NONE, NULL, 0,
1891         NULL, HFILL }},
1892
1893     { &hf_artnet_poll_reply_num_ports,
1894       { "Number of Ports",
1895         "artnet.poll_reply.num_ports",
1896         FT_UINT16, BASE_DEC, NULL, 0x0,
1897         NULL, HFILL }},
1898
1899     { &hf_artnet_poll_reply_port_types,
1900       { "Port Types",
1901         "artnet.poll_reply.port_types",
1902         FT_NONE, BASE_NONE, NULL, 0,
1903         NULL, HFILL }},
1904
1905     { &hf_artnet_poll_reply_port_types_1,
1906       { "Type of Port 1",
1907         "artnet.poll_reply.port_types_1",
1908         FT_UINT8, BASE_HEX, NULL, 0x0,
1909         NULL, HFILL }},
1910
1911     { &hf_artnet_poll_reply_port_types_2,
1912       { "Type of Port 2",
1913         "artnet.poll_reply.port_types_2",
1914         FT_UINT8, BASE_HEX, NULL, 0x0,
1915         NULL, HFILL }},
1916
1917     { &hf_artnet_poll_reply_port_types_3,
1918       { "Type of Port 3",
1919         "artnet.poll_reply.port_types_3",
1920         FT_UINT8, BASE_HEX, NULL, 0x0,
1921         NULL, HFILL }},
1922
1923     { &hf_artnet_poll_reply_port_types_4,
1924       { "Type of Port 4",
1925         "artnet.poll_reply.port_types_4",
1926         FT_UINT8, BASE_HEX, NULL, 0x0,
1927         NULL, HFILL }},
1928
1929     { &hf_artnet_poll_reply_good_input,
1930       { "Input Status",
1931         "artnet.poll_reply.good_input",
1932         FT_NONE, BASE_NONE, NULL, 0,
1933         NULL, HFILL }},
1934
1935     { &hf_artnet_poll_reply_good_input_1,
1936       { "Input status of Port 1",
1937         "artnet.poll_reply.good_input_1",
1938         FT_UINT8, BASE_HEX, NULL, 0x0,
1939         NULL, HFILL }},
1940
1941     { &hf_artnet_poll_reply_good_input_2,
1942       { "Input status of Port 2",
1943         "artnet.poll_reply.good_input_2",
1944         FT_UINT8, BASE_HEX, NULL, 0x0,
1945         NULL, HFILL }},
1946
1947     { &hf_artnet_poll_reply_good_input_3,
1948       { "Input status of Port 3",
1949         "artnet.poll_reply.good_input_3",
1950         FT_UINT8, BASE_HEX, NULL, 0x0,
1951         NULL, HFILL }},
1952
1953     { &hf_artnet_poll_reply_good_input_4,
1954       { "Input status of Port 4",
1955         "artnet.poll_reply.good_input_4",
1956         FT_UINT8, BASE_HEX, NULL, 0x0,
1957         NULL, HFILL }},
1958
1959     { &hf_artnet_poll_reply_good_output,
1960       { "Output Status",
1961         "artnet.poll_reply.good_output",
1962         FT_NONE, BASE_NONE, NULL, 0,
1963         "Port output status", HFILL }},
1964
1965     { &hf_artnet_poll_reply_good_output_1,
1966       { "Output status of Port 1",
1967         "artnet.poll_reply.good_output_1",
1968         FT_UINT8, BASE_HEX, NULL, 0x0,
1969         NULL, HFILL }},
1970
1971     { &hf_artnet_poll_reply_good_output_2,
1972       { "Output status of Port 2",
1973         "artnet.poll_reply.good_output_2",
1974         FT_UINT8, BASE_HEX, NULL, 0x0,
1975         NULL, HFILL }},
1976
1977     { &hf_artnet_poll_reply_good_output_3,
1978       { "Output status of Port 3",
1979         "artnet.poll_reply.good_output_3",
1980         FT_UINT8, BASE_HEX, NULL, 0x0,
1981         NULL, HFILL }},
1982
1983     { &hf_artnet_poll_reply_good_output_4,
1984       { "Output status of Port 4",
1985         "artnet.poll_reply.good_output_4",
1986         FT_UINT8, BASE_HEX, NULL, 0x0,
1987         "Outpus status of Port 4", HFILL }},
1988
1989     { &hf_artnet_poll_reply_swin,
1990       { "Input Subswitch",
1991         "artnet.poll_reply.swin",
1992         FT_NONE, BASE_NONE, NULL, 0,
1993         NULL, HFILL }},
1994
1995     { &hf_artnet_poll_reply_swin_1,
1996       { "Input Subswitch of Port 1",
1997         "artnet.poll_reply.swin_1",
1998         FT_UINT8, BASE_HEX, NULL, 0x0,
1999         NULL, HFILL }},
2000
2001     { &hf_artnet_poll_reply_swin_2,
2002       { "Input Subswitch of Port 2",
2003         "artnet.poll_reply.swin_2",
2004         FT_UINT8, BASE_HEX, NULL, 0x0,
2005         NULL, HFILL }},
2006
2007     { &hf_artnet_poll_reply_swin_3,
2008       { "Input Subswitch of Port 3",
2009         "artnet.poll_reply.swin_3",
2010         FT_UINT8, BASE_HEX, NULL, 0x0,
2011         NULL, HFILL }},
2012
2013     { &hf_artnet_poll_reply_swin_4,
2014       { "Input Subswitch of Port 4",
2015         "artnet.poll_reply.swin_4",
2016         FT_UINT8, BASE_HEX, NULL, 0x0,
2017         NULL, HFILL }},
2018
2019     { &hf_artnet_poll_reply_swout,
2020       { "Output Subswitch",
2021         "artnet.poll_reply.swout",
2022         FT_NONE, BASE_NONE, NULL, 0,
2023         NULL, HFILL }},
2024
2025     { &hf_artnet_poll_reply_swout_1,
2026       { "Output Subswitch of Port 1",
2027         "artnet.poll_reply.swout_1",
2028         FT_UINT8, BASE_HEX, NULL, 0x0,
2029         NULL, HFILL }},
2030
2031     { &hf_artnet_poll_reply_swout_2,
2032       { "Output Subswitch of Port 2",
2033         "artnet.poll_reply.swout_2",
2034         FT_UINT8, BASE_HEX, NULL, 0x0,
2035         NULL, HFILL }},
2036
2037     { &hf_artnet_poll_reply_swout_3,
2038       { "Output Subswitch of Port 3",
2039         "artnet.poll_reply.swout_3",
2040         FT_UINT8, BASE_HEX, NULL, 0x0,
2041         NULL, HFILL }},
2042
2043     { &hf_artnet_poll_reply_swout_4,
2044       { "Output Subswitch of Port 4",
2045         "artnet.poll_reply.swout_4",
2046         FT_UINT8, BASE_HEX, NULL, 0x0,
2047         NULL, HFILL }},
2048
2049     { &hf_artnet_poll_reply_swvideo,
2050       { "SwVideo",
2051         "artnet.poll_reply.swvideo",
2052         FT_UINT8, BASE_HEX, NULL, 0x0,
2053         NULL, HFILL }},
2054
2055     { &hf_artnet_poll_reply_swmacro,
2056       { "SwMacro",
2057         "artnet.poll_reply.swmacro",
2058         FT_UINT8, BASE_HEX, NULL, 0x0,
2059         NULL, HFILL }},
2060
2061     { &hf_artnet_poll_reply_swremote,
2062       { "SwRemote",
2063         "artnet.poll_reply.swremote",
2064         FT_UINT8, BASE_HEX, NULL, 0x0,
2065         NULL, HFILL }},
2066
2067     { &hf_artnet_poll_reply_mac,
2068       { "MAC",
2069         "artnet.poll_reply.mac",
2070         FT_ETHER, BASE_HEX, NULL, 0x0,
2071         NULL, HFILL }},
2072
2073     /* ArtOutput */
2074
2075     { &hf_artnet_output,
2076       { "ArtDMX packet",
2077         "artnet.output",
2078         FT_NONE, BASE_NONE, NULL, 0,
2079         "Art-Net ArtDMX packet", HFILL }},
2080
2081     { &hf_artnet_output_sequence,
2082       { "Sequence",
2083         "artnet.output.sequence",
2084         FT_UINT8, BASE_DEC, NULL, 0x0,
2085         NULL, HFILL }},
2086
2087     { &hf_artnet_output_physical,
2088       { "Physical",
2089         "artnet.output.physical",
2090         FT_UINT8, BASE_DEC, NULL, 0x0,
2091         NULL, HFILL }},
2092
2093     { &hf_artnet_output_universe,
2094       { "Universe",
2095         "artnet.output.universe",
2096         FT_UINT16, BASE_DEC, NULL, 0x0,
2097         NULL, HFILL }},
2098
2099     { &hf_artnet_output_length,
2100       { "Length",
2101         "artnet.output.length",
2102         FT_UINT16, BASE_DEC, NULL, 0x0,
2103         NULL, HFILL }},
2104
2105     { &hf_artnet_output_data,
2106       { "DMX data",
2107         "artnet.output.data",
2108         FT_NONE, BASE_NONE, NULL, 0x0,
2109         "DMX Data", HFILL }},
2110
2111     { &hf_artnet_output_data_filter,
2112       { "DMX data filter",
2113         "artnet.output.data_filter",
2114         FT_BYTES, BASE_NONE, NULL, 0x0,
2115         "DMX Data Filter", HFILL }},
2116
2117     { &hf_artnet_output_dmx_data,
2118       { "DMX data",
2119         "artnet.output.dmx_data",
2120         FT_NONE, BASE_NONE, NULL, 0x0,
2121         "DMX Data", HFILL }},
2122
2123     /* ArtAddress */
2124
2125     { &hf_artnet_address,
2126       { "ArtAddress packet",
2127         "artnet.address",
2128         FT_NONE, BASE_NONE, NULL, 0,
2129         "Art-Net ArtAddress packet", HFILL }},
2130
2131     { &hf_artnet_address_short_name,
2132       { "Short Name",
2133         "artnet.address.short_name",
2134         FT_STRING, BASE_NONE, NULL, 0x0,
2135         NULL, HFILL }},
2136
2137     { &hf_artnet_address_long_name,
2138       { "Long Name",
2139         "artnet.address.long_name",
2140         FT_STRING, BASE_NONE, NULL, 0x0,
2141         NULL, HFILL }},
2142
2143     { &hf_artnet_address_swin,
2144       { "Input Subswitch",
2145         "artnet.address.swin",
2146         FT_NONE, BASE_NONE, NULL, 0,
2147         NULL, HFILL }},
2148
2149     { &hf_artnet_address_swin_1,
2150       { "Input Subswitch of Port 1",
2151         "artnet.address.swin_1",
2152         FT_UINT8, BASE_HEX, NULL, 0x0,
2153         NULL, HFILL }},
2154
2155     { &hf_artnet_address_swin_2,
2156       { "Input Subswitch of Port 2",
2157         "artnet.address.swin_2",
2158         FT_UINT8, BASE_HEX, NULL, 0x0,
2159         NULL, HFILL }},
2160
2161     { &hf_artnet_address_swin_3,
2162       { "Input Subswitch of Port 3",
2163         "artnet.address.swin_3",
2164         FT_UINT8, BASE_HEX, NULL, 0x0,
2165         NULL, HFILL }},
2166
2167     { &hf_artnet_address_swin_4,
2168       { "Input Subswitch of Port 4",
2169         "artnet.address.swin_4",
2170         FT_UINT8, BASE_HEX, NULL, 0x0,
2171         NULL, HFILL }},
2172
2173     { &hf_artnet_address_swout,
2174       { "Output Subswitch",
2175         "artnet.address.swout",
2176         FT_NONE, BASE_NONE, NULL, 0,
2177         NULL, HFILL }},
2178
2179     { &hf_artnet_address_swout_1,
2180       { "Output Subswitch of Port 1",
2181         "artnet.address.swout_1",
2182         FT_UINT8, BASE_HEX, NULL, 0x0,
2183         NULL, HFILL }},
2184
2185     { &hf_artnet_address_swout_2,
2186       { "Output Subswitch of Port 2",
2187         "artnet.address.swout_2",
2188         FT_UINT8, BASE_HEX, NULL, 0x0,
2189         NULL, HFILL }},
2190
2191     { &hf_artnet_address_swout_3,
2192       { "Output Subswitch of Port 3",
2193         "artnet.address.swout_3",
2194         FT_UINT8, BASE_HEX, NULL, 0x0,
2195         NULL, HFILL }},
2196
2197     { &hf_artnet_address_swout_4,
2198       { "Output Subswitch of Port 4",
2199         "artnet.address.swout_4",
2200         FT_UINT8, BASE_HEX, NULL, 0x0,
2201         NULL, HFILL }},
2202
2203     { &hf_artnet_address_subswitch,
2204       { "Subswitch",
2205         "artnet.address.subswitch",
2206         FT_UINT8, BASE_HEX, NULL, 0x0,
2207         NULL, HFILL }},
2208
2209     { &hf_artnet_address_swvideo,
2210       { "SwVideo",
2211         "artnet.address.swvideo",
2212         FT_UINT8, BASE_HEX, NULL, 0x0,
2213         NULL, HFILL }},
2214
2215     { &hf_artnet_address_command,
2216       { "Command",
2217         "artnet.address.command",
2218         FT_UINT8, BASE_HEX, VALS(artnet_address_command_vals), 0x0,
2219         NULL, HFILL }},
2220
2221     /* ArtInput */
2222
2223     { &hf_artnet_input,
2224       { "ArtInput packet",
2225         "artnet.input",
2226         FT_NONE, BASE_NONE, NULL, 0,
2227         "Art-Net ArtInput packet", HFILL }},
2228
2229     { &hf_artnet_input_num_ports,
2230       { "Number of Ports",
2231         "artnet.input.num_ports",
2232         FT_UINT16, BASE_DEC, NULL, 0x0,
2233         NULL, HFILL }},
2234
2235     { &hf_artnet_input_input,
2236       { "Port Status",
2237         "artnet.input.input",
2238         FT_NONE, BASE_NONE, NULL, 0,
2239         NULL, HFILL }},
2240
2241     { &hf_artnet_input_input_1,
2242       { "Status of Port 1",
2243         "artnet.input.input_1",
2244         FT_UINT8, BASE_HEX, NULL, 0x0,
2245         NULL, HFILL }},
2246
2247     { &hf_artnet_input_input_2,
2248       { "Status of Port 2",
2249         "artnet.input.input_2",
2250         FT_UINT8, BASE_HEX, NULL, 0x0,
2251         NULL, HFILL }},
2252
2253     { &hf_artnet_input_input_3,
2254       { "Status of Port 3",
2255         "artnet.input.input_3",
2256         FT_UINT8, BASE_HEX, NULL, 0x0,
2257         NULL, HFILL }},
2258
2259     { &hf_artnet_input_input_4,
2260       { "Status of Port 4",
2261         "artnet.input.input_4",
2262         FT_UINT8, BASE_HEX, NULL, 0x0,
2263         NULL, HFILL }},
2264
2265     /* ArtFirmwareMaster */
2266
2267     { &hf_artnet_firmware_master,
2268       { "ArtFirmwareMaster packet",
2269         "artnet.firmware_master",
2270         FT_NONE, BASE_NONE, NULL, 0,
2271         "Art-Net ArtFirmwareMaster packet", HFILL }},
2272
2273     { &hf_artnet_firmware_master_type,
2274       { "Type",
2275         "artnet.firmware_master.type",
2276         FT_UINT8, BASE_HEX, VALS(artnet_firmware_master_type_vals), 0x0,
2277         "Number of Ports", HFILL }},
2278
2279     { &hf_artnet_firmware_master_block_id,
2280       { "Block ID",
2281         "artnet.firmware_master.block_id",
2282         FT_UINT8, BASE_DEC, NULL, 0x0,
2283         NULL, HFILL }},
2284
2285     { &hf_artnet_firmware_master_length,
2286       { "Length",
2287         "artnet.firmware_master.length",
2288         FT_UINT32, BASE_DEC, NULL, 0x0,
2289         NULL, HFILL }},
2290
2291     { &hf_artnet_firmware_master_data,
2292       { "data",
2293         "artnet.firmware_master.data",
2294         FT_BYTES, BASE_NONE, NULL, 0x0,
2295         NULL, HFILL }},
2296
2297     /* ArtFirmwareReply */
2298
2299     { &hf_artnet_firmware_reply,
2300       { "ArtFirmwareReply packet",
2301         "artnet.firmware_reply",
2302         FT_NONE, BASE_NONE, NULL, 0,
2303         "Art-Net ArtFirmwareReply packet", HFILL }},
2304
2305     { &hf_artnet_firmware_reply_type,
2306       { "Type",
2307         "artnet.firmware_reply.type",
2308         FT_UINT8, BASE_HEX, VALS(artnet_firmware_reply_type_vals), 0x0,
2309         "Number of Ports", HFILL }},
2310
2311     /* ArtVideoSetup */
2312
2313     { &hf_artnet_video_setup,
2314       { "ArtVideoSetup packet",
2315         "artnet.video_setup",
2316         FT_NONE, BASE_NONE, NULL, 0,
2317         "ArtNET ArtVideoSetup packet", HFILL }},
2318
2319     { &hf_artnet_video_setup_control,
2320       { "control",
2321         "artnet.video_setup.control",
2322         FT_UINT8, BASE_HEX, NULL, 0x0,
2323         NULL, HFILL }},
2324
2325     { &hf_artnet_video_setup_font_height,
2326       { "Font Height",
2327         "artnet.video_setup.font_height",
2328         FT_UINT8, BASE_DEC, NULL, 0x0,
2329         NULL, HFILL }},
2330
2331     { &hf_artnet_video_setup_first_font,
2332       { "First Font",
2333         "artnet.video_setup.first_font",
2334         FT_UINT8, BASE_DEC, NULL, 0x0,
2335         NULL, HFILL }},
2336
2337     { &hf_artnet_video_setup_last_font,
2338       { "Last Font",
2339         "artnet.video_setup.last_font",
2340         FT_UINT8, BASE_DEC, NULL, 0x0,
2341         NULL, HFILL }},
2342
2343     { &hf_artnet_video_setup_win_font_name,
2344       { "Windows Font Name",
2345         "artnet.video_setup.win_font_name",
2346         FT_STRING, BASE_NONE, NULL, 0x0,
2347         NULL, HFILL }},
2348
2349     { &hf_artnet_video_setup_font_data,
2350       { "Font data",
2351         "artnet.video_setup.font_data",
2352         FT_BYTES, BASE_NONE, NULL, 0x0,
2353         "Font Date", HFILL }},
2354
2355     /* ArtVideoPalette */
2356
2357     { &hf_artnet_video_palette,
2358       { "ArtVideoPalette packet",
2359         "artnet.video_palette",
2360         FT_NONE, BASE_NONE, NULL, 0,
2361         "Art-Net ArtVideoPalette packet", HFILL }},
2362
2363     { &hf_artnet_video_palette_colour_red,
2364       { "Colour Red",
2365         "artnet.video_palette.colour_red",
2366         FT_BYTES, BASE_NONE, NULL, 0x0,
2367         NULL, HFILL }},
2368
2369     { &hf_artnet_video_palette_colour_green,
2370       { "Colour Green",
2371         "artnet.video_palette.colour_green",
2372         FT_BYTES, BASE_NONE, NULL, 0x0,
2373         NULL, HFILL }},
2374
2375     { &hf_artnet_video_palette_colour_blue,
2376       { "Colour Blue",
2377         "artnet.video_palette.colour_blue",
2378         FT_BYTES, BASE_NONE, NULL, 0x0,
2379         NULL, HFILL }},
2380
2381     /* ArtVideoData */
2382
2383     { &hf_artnet_video_data,
2384       { "ArtVideoData packet",
2385         "artnet.video_data",
2386         FT_NONE, BASE_NONE, NULL, 0,
2387         "Art-Net ArtVideoData packet", HFILL }},
2388
2389     { &hf_artnet_video_data_pos_x,
2390       { "PosX",
2391         "artnet.video_data.pos_x",
2392         FT_UINT8, BASE_DEC, NULL, 0x0,
2393         NULL, HFILL }},
2394
2395     { &hf_artnet_video_data_pos_y,
2396       { "PosY",
2397         "artnet.video_data.pos_y",
2398         FT_UINT8, BASE_DEC, NULL, 0x0,
2399         NULL, HFILL }},
2400
2401     { &hf_artnet_video_data_len_x,
2402       { "LenX",
2403         "artnet.video_data.len_x",
2404         FT_UINT8, BASE_DEC, NULL, 0x0,
2405         NULL, HFILL }},
2406
2407     { &hf_artnet_video_data_len_y,
2408       { "LenY",
2409         "artnet.video_data.len_y",
2410         FT_UINT8, BASE_DEC, NULL, 0x0,
2411         NULL, HFILL }},
2412
2413     { &hf_artnet_video_data_data,
2414       { "Video Data",
2415         "artnet.video_data.data",
2416         FT_BYTES, BASE_NONE, NULL, 0x0,
2417         NULL, HFILL }},
2418
2419     /* ArtTodRequest */
2420     { &hf_artnet_tod_request,
2421       { "ArtTodRequest packet",
2422         "artnet.tod_request",
2423         FT_NONE, BASE_NONE, NULL, 0,
2424         "Art-Net ArtTodRequest packet", HFILL }},
2425
2426     { &hf_artnet_tod_request_command,
2427       { "Command",
2428         "artnet.tod_request.command",
2429         FT_UINT8, BASE_HEX, VALS(artnet_tod_request_command_vals), 0x0,
2430         NULL, HFILL }},
2431
2432     { &hf_artnet_tod_request_ad_count,
2433       { "Address Count",
2434         "artnet.tod_request.ad_count",
2435         FT_UINT8, BASE_DEC, NULL, 0x0,
2436         NULL, HFILL }},
2437
2438     { &hf_artnet_tod_request_address,
2439       { "Address",
2440         "artnet.tod_request.address",
2441         FT_BYTES, BASE_NONE, NULL, 0x0,
2442         NULL, HFILL }},
2443
2444     /* ArtTodData */
2445     { &hf_artnet_tod_data,
2446       { "ArtTodData packet",
2447         "artnet.tod_data",
2448         FT_NONE, BASE_NONE, NULL, 0,
2449         "Art-Net ArtTodData packet", HFILL }},
2450
2451     { &hf_artnet_tod_data_port,
2452       { "Port",
2453         "artnet.tod_data.port",
2454         FT_UINT8, BASE_DEC, NULL, 0x0,
2455         NULL, HFILL }},
2456
2457     { &hf_artnet_tod_data_command_response,
2458       { "Command Response",
2459         "artnet.tod_data.command_response",
2460         FT_UINT8, BASE_HEX, VALS(artnet_tod_data_command_vals), 0x0,
2461         NULL, HFILL }},
2462
2463     { &hf_artnet_tod_data_address,
2464       { "Address",
2465         "artnet.tod_data.address",
2466         FT_UINT8, BASE_HEX, NULL, 0x0,
2467         NULL, HFILL }},
2468
2469     { &hf_artnet_tod_data_uid_total,
2470       { "UID Total",
2471         "artnet.tod_data.uid_total",
2472         FT_UINT16, BASE_DEC, NULL, 0x0,
2473         NULL, HFILL }},
2474
2475     { &hf_artnet_tod_data_block_count,
2476       { "Block Count",
2477         "artnet.tod_data.block_count",
2478         FT_UINT8, BASE_DEC, NULL, 0x0,
2479         NULL, HFILL }},
2480
2481     { &hf_artnet_tod_data_uid_count,
2482       { "UID Count",
2483         "artnet.tod_data.uid_count",
2484         FT_UINT8, BASE_DEC, NULL, 0x0,
2485         NULL, HFILL }},
2486
2487     { &hf_artnet_tod_data_tod,
2488       { "TOD",
2489         "artnet.tod_data.tod",
2490         FT_BYTES, BASE_NONE, NULL, 0x0,
2491         NULL, HFILL }},
2492
2493     /* ArtTodControl */
2494     { &hf_artnet_tod_control,
2495       { "ArtTodControl packet",
2496         "artner.tod_control",
2497         FT_NONE, BASE_NONE, NULL, 0,
2498         "Art-Net ArtTodControl packet", HFILL }},
2499
2500     { &hf_artnet_tod_control_command,
2501       { "Command",
2502         "artnet.tod_control.command",
2503         FT_UINT8, BASE_HEX, VALS(artnet_tod_control_command_vals), 0x0,
2504         NULL, HFILL }},
2505
2506     { &hf_artnet_tod_control_address,
2507       { "Address",
2508         "artnet.tod_request.address",
2509         FT_UINT8, BASE_HEX, NULL, 0x0,
2510         NULL, HFILL }},
2511
2512     /* ArtRdm */
2513     { &hf_artnet_rdm,
2514       { "ArtRdm packet",
2515         "artnet.rdm",
2516         FT_NONE, BASE_NONE, NULL, 0,
2517         "Art-Net ArtRdm packet", HFILL }},
2518
2519     { &hf_artnet_rdm_command,
2520       { "Command",
2521         "artnet.rdm.command",
2522         FT_UINT8, BASE_HEX, VALS(artnet_rdm_command_vals), 0x0,
2523         NULL, HFILL }},
2524
2525     { &hf_artnet_rdm_address,
2526       { "Address",
2527         "artnet.rdm.address",
2528         FT_UINT8, BASE_HEX, NULL, 0x0,
2529         NULL, HFILL }},
2530
2531     /* ArtIpProg */
2532     { &hf_artnet_ip_prog,
2533       { "ArtIpProg packet",
2534         "artnet.ip_prog",
2535         FT_NONE, BASE_NONE, NULL, 0,
2536         "ArtNET ArtIpProg packet", HFILL }},
2537
2538     { &hf_artnet_ip_prog_command,
2539       { "Command",
2540         "artnet.ip_prog.command",
2541         FT_UINT8, BASE_HEX, NULL, 0x0,
2542         NULL, HFILL }},
2543
2544     { &hf_artnet_ip_prog_command_prog_port,
2545       { "Program Port",
2546         "artnet.ip_prog.command_prog_port",
2547         FT_UINT8, BASE_HEX, NULL, 0x01,
2548         NULL, HFILL }},
2549
2550     { &hf_artnet_ip_prog_command_prog_sm,
2551       { "Program Subnet Mask",
2552         "artnet.ip_prog.command_prog_sm",
2553         FT_UINT8, BASE_HEX, NULL, 0x02,
2554         NULL, HFILL }},
2555
2556     { &hf_artnet_ip_prog_command_prog_ip,
2557       { "Program IP",
2558         "artnet.ip_prog.command_prog_ip",
2559         FT_UINT8, BASE_HEX, NULL, 0x04,
2560         NULL, HFILL }},
2561
2562     { &hf_artnet_ip_prog_command_reset,
2563       { "Reset parameters",
2564         "artnet.ip_prog.command_reset",
2565         FT_UINT8, BASE_HEX, NULL, 0x08,
2566         NULL, HFILL }},
2567
2568     { &hf_artnet_ip_prog_command_unused,
2569       { "Unused",
2570         "artnet.ip_prog.command_unused",
2571         FT_UINT8, BASE_HEX, NULL, 0x70,
2572         NULL, HFILL }},
2573
2574     { &hf_artnet_ip_prog_command_prog_enable,
2575       { "Enable Programming",
2576         "artnet.ip_prog.command_prog_enable",
2577         FT_UINT8, BASE_HEX, NULL, 0x80,
2578         NULL, HFILL }},
2579
2580     { &hf_artnet_ip_prog_ip,
2581       { "IP Address",
2582         "artnet.ip_prog.ip",
2583         FT_IPv4, BASE_NONE, NULL, 0x0,
2584         NULL, HFILL }},
2585
2586     { &hf_artnet_ip_prog_sm,
2587       { "Subnet mask",
2588         "artnet.ip_prog.sm",
2589         FT_IPv4, BASE_NONE, NULL, 0x0,
2590         "IP Subnet mask", HFILL }},
2591
2592     { &hf_artnet_ip_prog_port,
2593       { "Port",
2594         "artnet.ip_prog.port",
2595         FT_UINT16, BASE_DEC, NULL, 0x0,
2596         NULL, HFILL }},
2597
2598     /* ArtIpProgReply */
2599     { &hf_artnet_ip_prog_reply,
2600       { "ArtIpProgReplay packet",
2601         "artnet.ip_prog_reply",
2602         FT_NONE, BASE_NONE, NULL, 0,
2603         "Art-Net ArtIpProgReply packet", HFILL }},
2604
2605     { &hf_artnet_ip_prog_reply_ip,
2606       { "IP Address",
2607         "artnet.ip_prog_reply.ip",
2608         FT_IPv4, BASE_NONE, NULL, 0x0,
2609         NULL, HFILL }},
2610
2611     { &hf_artnet_ip_prog_reply_sm,
2612       { "Subnet mask",
2613         "artnet.ip_prog_reply.sm",
2614         FT_IPv4, BASE_NONE, NULL, 0x0,
2615         "IP Subnet mask", HFILL }},
2616
2617     { &hf_artnet_ip_prog_reply_port,
2618       { "Port",
2619         "artnet.ip_prog_reply.port",
2620         FT_UINT16, BASE_DEC, NULL, 0x0,
2621         NULL, HFILL }},
2622
2623     /* ArtPollServerReply */
2624     { &hf_artnet_poll_server_reply,
2625       { "ArtPollServerReply packet",
2626         "artnet.poll_server_reply",
2627         FT_NONE, BASE_NONE, NULL, 0,
2628         "Art-Net ArtPollServerReply packet", HFILL }}
2629
2630   };
2631
2632   static gint *ett[] = {
2633     &ett_artnet,
2634   };
2635
2636   module_t *artnet_module;
2637
2638   static enum_val_t disp_chan_val_types[] = {
2639      { "pro", "Percent", 0 },
2640      { "hex", "Hexadecimal", 1 },
2641      { "dec", "Decimal", 2 },
2642      { NULL, NULL, 0 }
2643   };
2644
2645   static enum_val_t disp_chan_nr_types[] = {
2646      { "hex", "Hexadecimal", 0 },
2647      { "dec", "Decimal", 1 },
2648      { NULL, NULL, 0 }
2649   };
2650
2651   static enum_val_t col_count[] = {
2652      { "6", "6", 6 },
2653      { "10", "10", 10 },
2654      { "12", "12", 12 },
2655      { "16", "16", 16 },
2656      { "24", "24", 24 },
2657      { NULL, NULL, 0 }
2658   };
2659
2660   proto_artnet = proto_register_protocol("Art-Net",
2661                                        "ARTNET","artnet");
2662   proto_register_field_array(proto_artnet,hf,array_length(hf));
2663   proto_register_subtree_array(ett,array_length(ett));
2664
2665   artnet_module = prefs_register_protocol(proto_artnet,
2666                                         proto_reg_handoff_artnet);
2667   prefs_register_uint_preference(artnet_module, "udp_port",
2668                                  "UDP Port",
2669                                  "The UDP port on which "
2670                                  "Art-Net "
2671                                  "packets will be sent",
2672                                  10,&global_udp_port_artnet);
2673
2674   prefs_register_enum_preference(artnet_module, "dmx_disp_chan_val_type",
2675             "DMX Display channel value type", 
2676             "The way DMX values are displayed", 
2677                                  &global_disp_chan_val_type,
2678                                  disp_chan_val_types, FALSE);
2679
2680   prefs_register_enum_preference(artnet_module, "dmx_disp_chan_nr_type",
2681             "DMX Display channel nr. type",
2682             "The way DMX channel numbers are displayed",
2683                                  &global_disp_chan_nr_type,
2684                                  disp_chan_nr_types, FALSE);
2685
2686   prefs_register_enum_preference(artnet_module, "dmx_disp_col_count",
2687             "DMX Display Column Count",
2688             "The number of columns for the DMX display",
2689                                  &global_disp_col_count,
2690                                  col_count, FALSE);
2691 }
2692
2693 /* The registration hand-off routing */
2694
2695 void
2696 proto_reg_handoff_artnet(void) {
2697   static gboolean artnet_initialized = FALSE;
2698   static dissector_handle_t artnet_handle;
2699   static guint udp_port_artnet;
2700
2701   if(!artnet_initialized) {
2702     artnet_handle = create_dissector_handle(dissect_artnet,proto_artnet);
2703     rdm_handle = find_dissector("rdm");
2704     artnet_initialized = TRUE;
2705   } else {
2706     dissector_delete("udp.port",udp_port_artnet,artnet_handle);
2707   }
2708
2709   udp_port_artnet = global_udp_port_artnet;
2710   
2711   dissector_add("udp.port",global_udp_port_artnet,artnet_handle);
2712 }