nexmon – Rev 1

Subversion Repositories:
Rev:
/* packet-rdm.c
 * RDM (Remote Device Management) packet disassembly.
 *
 * This dissector is written by
 *
 *  Erwin Rol <erwin@erwinrol.com>
 *  Copyright 2003, 2011, 2012 Erwin Rol
 *
 *  Shaun Jackman <sjackman@gmail.com>
 *  Copyright 2006 Pathway Connectivity
 *
 *  Wireshark - Network traffic analyzer
 *  Gerald Combs <gerald@wireshark.org>
 *  Copyright 1999 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301, USA.
 */
/*
 * ANSI E1.20-2006, Entertainment Technology
 * Remote Device Management over USITT DMX512, describes a method of
 * bi-directional communications over a USITT DMX512/1990 data link
 * between an entertainment lighting controller and one or more
 * remotely controlled lighting devices. The protocol also is intended
 * to work with the ANSI E1.11-2004 control protocol. It allows
 * discovery of devices on a DMX512/E1.11 network and the remote
 * setting of DMX starting addresses, as well as status and fault
 * reporting back to the control console.
 */

#include "config.h"

#include <epan/packet.h>
#include "packet-rdm.h"

void proto_register_rdm(void);
void proto_reg_handoff_rdm(void);

#define RDM_SC_RDM                              0xCC
#define RDM_SC_SUB_MESSAGE                      0x01

#define RDM_CC_DISCOVERY_COMMAND                0x10
#define RDM_CC_DISCOVERY_COMMAND_RESPONSE       0x11
#define RDM_CC_GET_COMMAND                      0x20
#define RDM_CC_GET_COMMAND_RESPONSE             0x21
#define RDM_CC_SET_COMMAND                      0x30
#define RDM_CC_SET_COMMAND_RESPONSE             0x31

static const value_string rdm_cc_vals[] = {
        { RDM_CC_DISCOVERY_COMMAND,             "Discovery Command" },
        { RDM_CC_DISCOVERY_COMMAND_RESPONSE,    "Discovery Command Response" },
        { RDM_CC_GET_COMMAND,                   "Get Command" },
        { RDM_CC_GET_COMMAND_RESPONSE,          "Get Command Response" },
        { RDM_CC_SET_COMMAND,                   "Set Command" },
        { RDM_CC_SET_COMMAND_RESPONSE,          "Set Command Response" },
        { 0, NULL },
};

#define RDM_RESPONSE_TYPE_ACK                   0x00
#define RDM_RESPONSE_TYPE_ACK_TIMER             0x01
#define RDM_RESPONSE_TYPE_NACK_REASON           0x02
#define RDM_RESPONSE_TYPE_ACK_OVERFLOW          0x03

static const value_string rdm_rt_vals[] = {
        { RDM_RESPONSE_TYPE_ACK,                "Ack" },
        { RDM_RESPONSE_TYPE_ACK_TIMER,          "Ack Timer" },
        { RDM_RESPONSE_TYPE_NACK_REASON,        "Nack Reason" },
        { RDM_RESPONSE_TYPE_ACK_OVERFLOW,       "Ack Overflow" },
        { 0, NULL },
};

#define RDM_PARAM_ID_DISC_UNIQUE_BRANCH                 0x0001
#define RDM_PARAM_ID_DISC_MUTE                          0x0002
#define RDM_PARAM_ID_DISC_UN_MUTE                       0x0003
#define RDM_PARAM_ID_PROXIED_DEVICES                    0x0010
#define RDM_PARAM_ID_PROXIED_DEVICE_COUNT               0x0011
#define RDM_PARAM_ID_COMMS_STATUS                       0x0015
#define RDM_PARAM_ID_QUEUED_MESSAGE                     0x0020
#define RDM_PARAM_ID_STATUS_MESSAGES                    0x0030
#define RDM_PARAM_ID_STATUS_ID_DESCRIPTION              0x0031
#define RDM_PARAM_ID_CLEAR_STATUS_ID                    0x0032
#define RDM_PARAM_ID_SUB_DEVICE_STATUS_REPORT_THRESHOLD 0x0033
#define RDM_PARAM_ID_SUPPORTED_PARAMETERS               0x0050
#define RDM_PARAM_ID_PARAMETER_DESCRIPTION              0x0051
#define RDM_PARAM_ID_DEVICE_INFO                        0x0060
#define RDM_PARAM_ID_PRODUCT_DETAIL_ID_LIST             0x0070
#define RDM_PARAM_ID_DEVICE_MODEL_DESCRIPTION           0x0080
#define RDM_PARAM_ID_MANUFACTURER_LABEL                 0x0081
#define RDM_PARAM_ID_DEVICE_LABEL                       0x0082
#define RDM_PARAM_ID_FACTORY_DEFAULTS                   0x0090
#define RDM_PARAM_ID_LANGUAGE_CAPABILITIES              0x00A0
#define RDM_PARAM_ID_LANGUAGE                           0x00B0
#define RDM_PARAM_ID_SOFTWARE_VERSION_LABEL             0x00C0
#define RDM_PARAM_ID_BOOT_SOFTWARE_VERSION_ID           0x00C1
#define RDM_PARAM_ID_BOOT_SOFTWARE_VERSION_LABEL        0x00C2
#define RDM_PARAM_ID_DMX_PERSONALITY                    0x00E0
#define RDM_PARAM_ID_DMX_PERSONALITY_DESCRIPTION        0x00E1
#define RDM_PARAM_ID_DMX_START_ADDRESS                  0x00F0
#define RDM_PARAM_ID_SLOT_INFO                          0x0120
#define RDM_PARAM_ID_SLOT_DESCRIPTION                   0x0121
#define RDM_PARAM_ID_DEFAULT_SLOT_VALUE                 0x0122
#define RDM_PARAM_ID_SENSOR_DEFINITION                  0x0200
#define RDM_PARAM_ID_SENSOR_VALUE                       0x0201
#define RDM_PARAM_ID_RECORD_SENSORS                     0x0202
#define RDM_PARAM_ID_DEVICE_HOURS                       0x0400
#define RDM_PARAM_ID_LAMP_HOURS                         0x0401
#define RDM_PARAM_ID_LAMP_STRIKES                       0x0402
#define RDM_PARAM_ID_LAMP_STATE                         0x0403
#define RDM_PARAM_ID_LAMP_ON_MODE                       0x0404
#define RDM_PARAM_ID_DEVICE_POWER_CYCLES                0x0405
#define RDM_PARAM_ID_DISPLAY_INVERT                     0x0500
#define RDM_PARAM_ID_DISPLAY_LEVEL                      0x0501
#define RDM_PARAM_ID_PAN_INVERT                         0x0600
#define RDM_PARAM_ID_TILT_INVERT                        0x0601
#define RDM_PARAM_ID_PAN_TILT_SWAP                      0x0602
#define RDM_PARAM_ID_REAL_TIME_CLOCK                    0x0603
#define RDM_PARAM_ID_IDENTIFY_DEVICE                    0x1000
#define RDM_PARAM_ID_RESET_DEVICE                       0x1001
#define RDM_PARAM_ID_POWER_STATE                        0x1010
#define RDM_PARAM_ID_PERFORM_SELFTEST                   0x1020
#define RDM_PARAM_ID_SELF_TEST_DESCRIPTION              0x1021
#define RDM_PARAM_ID_CAPTURE_PRESET                     0x1030
#define RDM_PARAM_ID_PRESET_PLAYBACK                    0x1031

const value_string rdm_param_id_vals[] = {
        { RDM_PARAM_ID_DISC_UNIQUE_BRANCH,                 "DISC_UNIQUE_BRANCH" },
        { RDM_PARAM_ID_DISC_MUTE,                          "DISC_MUTE" },
        { RDM_PARAM_ID_DISC_UN_MUTE,                       "DISC_UN_MUTE" },
        { RDM_PARAM_ID_PROXIED_DEVICES,                    "PROXIED_DEVICES" },
        { RDM_PARAM_ID_PROXIED_DEVICE_COUNT,               "PROXIED_DEVICE_COUNT" },
        { RDM_PARAM_ID_COMMS_STATUS,                       "COMMS_STATUS" },
        { RDM_PARAM_ID_QUEUED_MESSAGE,                     "QUEUED_MESSAGE" },
        { RDM_PARAM_ID_STATUS_MESSAGES,                    "STATUS_MESSAGES" },
        { RDM_PARAM_ID_STATUS_ID_DESCRIPTION,              "STATUS_ID_DESCRIPTION" },
        { RDM_PARAM_ID_CLEAR_STATUS_ID,                    "CLEAR_STATUS_ID" },
        { RDM_PARAM_ID_SUB_DEVICE_STATUS_REPORT_THRESHOLD, "DEVICE_STATUS_REPORT_THRESHOLD" },
        { RDM_PARAM_ID_SUPPORTED_PARAMETERS,               "SUPPORTED_PARAMETERS" },
        { RDM_PARAM_ID_PARAMETER_DESCRIPTION,              "PARAMETER_DESCRIPTION" },
        { RDM_PARAM_ID_DEVICE_INFO,                        "DEVICE_INFO" },
        { RDM_PARAM_ID_PRODUCT_DETAIL_ID_LIST,             "PRODUCT_DETAIL_ID_LIST" },
        { RDM_PARAM_ID_DEVICE_MODEL_DESCRIPTION,           "DEVICE_MODEL_DESCRIPTION" },
        { RDM_PARAM_ID_MANUFACTURER_LABEL,                 "MANUFACTURER_LABEL" },
        { RDM_PARAM_ID_DEVICE_LABEL,                       "DEVICE_LABEL" },
        { RDM_PARAM_ID_FACTORY_DEFAULTS,                   "FACTORY_DEFAULTS" },
        { RDM_PARAM_ID_LANGUAGE_CAPABILITIES,              "LANGUAGE_CAPABILITIES" },
        { RDM_PARAM_ID_LANGUAGE,                           "LANGUAGE" },
        { RDM_PARAM_ID_SOFTWARE_VERSION_LABEL,             "SOFTWARE_VERSION_LABEL" },
        { RDM_PARAM_ID_BOOT_SOFTWARE_VERSION_ID,           "BOOT_SOFTWARE_VERSION_ID" },
        { RDM_PARAM_ID_BOOT_SOFTWARE_VERSION_LABEL,        "BOOT_SOFTWARE_VERSION_LABEL" },
        { RDM_PARAM_ID_DMX_PERSONALITY,                    "DMX_PERSONALITY" },
        { RDM_PARAM_ID_DMX_PERSONALITY_DESCRIPTION,        "DMX_PERSONALITY_DESCRIPTION" },
        { RDM_PARAM_ID_DMX_START_ADDRESS,                  "DMX_START_ADDRESS" },
        { RDM_PARAM_ID_SLOT_INFO,                          "SLOT_INFO" },
        { RDM_PARAM_ID_SLOT_DESCRIPTION,                   "SLOT_DESCRIPTION" },
        { RDM_PARAM_ID_DEFAULT_SLOT_VALUE,                 "DEFAULT_SLOT_VALUE" },
        { RDM_PARAM_ID_SENSOR_DEFINITION,                  "SENSOR_DEFINITION" },
        { RDM_PARAM_ID_SENSOR_VALUE,                       "SENSOR_VALUE" },
        { RDM_PARAM_ID_RECORD_SENSORS,                     "RECORD_SENSORS" },
        { RDM_PARAM_ID_DEVICE_HOURS,                       "DEVICE_HOURS" },
        { RDM_PARAM_ID_LAMP_HOURS,                         "LAMP_HOURS" },
        { RDM_PARAM_ID_LAMP_STRIKES,                       "LAMP_STRIKES" },
        { RDM_PARAM_ID_LAMP_STATE,                         "LAMP_STATE" },
        { RDM_PARAM_ID_LAMP_ON_MODE,                       "LAMP_ON_MODE" },
        { RDM_PARAM_ID_DEVICE_POWER_CYCLES,                "DEVICE_POWER_CYCLES" },
        { RDM_PARAM_ID_DISPLAY_INVERT,                     "DISPLAY_INVERT" },
        { RDM_PARAM_ID_DISPLAY_LEVEL,                      "DISPLAY_LEVEL" },
        { RDM_PARAM_ID_PAN_INVERT,                         "PAN_INVERT" },
        { RDM_PARAM_ID_TILT_INVERT,                        "TILT_INVERT" },
        { RDM_PARAM_ID_PAN_TILT_SWAP,                      "PAN_TILT_SWAP" },
        { RDM_PARAM_ID_REAL_TIME_CLOCK,                    "REAL_TIME_CLOCK" },
        { RDM_PARAM_ID_IDENTIFY_DEVICE,                    "IDENTIFY_DEVICE" },
        { RDM_PARAM_ID_RESET_DEVICE,                       "RESET_DEVICE" },
        { RDM_PARAM_ID_POWER_STATE,                        "POWER_STATE" },
        { RDM_PARAM_ID_PERFORM_SELFTEST,                   "PERFORM_SELFTEST" },
        { RDM_PARAM_ID_SELF_TEST_DESCRIPTION,              "SELF_TEST_DESCRIPTION" },
        { RDM_PARAM_ID_CAPTURE_PRESET,                     "CAPTURE_PRESET" },
        { RDM_PARAM_ID_PRESET_PLAYBACK,                    "PRESET_PLAYBACK" },
        { 0, NULL },
};

value_string_ext rdm_param_id_vals_ext = VALUE_STRING_EXT_INIT(rdm_param_id_vals);

#define RDM_STATUS_NONE                         0x00
#define RMD_STATUS_GET_LAST_MESSAGE             0x01
#define RDM_STATUS_ADVISORY                     0x02
#define RDM_STATUS_WARNING                      0x03
#define RDM_STATUS_ERROR                        0x04

static const value_string rdm_status_vals[] = {
        { RDM_STATUS_NONE,              "None" },
        { RMD_STATUS_GET_LAST_MESSAGE,  "Get Last Message" },
        { RDM_STATUS_ADVISORY,          "Advisory" },
        { RDM_STATUS_WARNING,           "Warning" },
        { RDM_STATUS_ERROR,             "Error" },
        { 0, NULL },
};

#define RDM_PREFIX_NONE         0x00
#define RDM_PREFIX_DECI         0x01
#define RDM_PREFIX_CENTI        0x02
#define RDM_PREFIX_MILLI        0x03
#define RDM_PREFIX_MICRO        0x04
#define RDM_PREFIX_NANO         0x05
#define RDM_PREFIX_PICO         0x06
#define RDM_PREFIX_FEMPTO       0x07
#define RDM_PREFIX_ATTO         0x08
#define RDM_PREFIX_ZEPTO        0x09
#define RDM_PREFIX_YOCTO        0x0A
#define RDM_PREFIX_DECA         0x11
#define RDM_PREFIX_HECTO        0x12
#define RDM_PREFIX_KILO         0x13
#define RDM_PREFIX_MEGA         0x14
#define RDM_PREFIX_GIGA         0x15
#define RDM_PREFIX_TERRA        0x16
#define RDM_PREFIX_PETA         0x17
#define RDM_PREFIX_EXA          0x18
#define RDM_PREFIX_ZETTA        0x19
#define RDM_PREFIX_YOTTA        0x1A

static const value_string rdm_prefix_vals[] = {
        { RDM_PREFIX_NONE,      "NONE (x1)" },
        { RDM_PREFIX_DECI,      "deci (x10^-1)" },
        { RDM_PREFIX_CENTI,     "centi (x10^-2)" },
        { RDM_PREFIX_MILLI,     "milli (x10^-3)" },
        { RDM_PREFIX_MICRO,     "micro (x10^-6)" },
        { RDM_PREFIX_NANO,      "nano (x10^-9)" },
        { RDM_PREFIX_PICO,      "pico (x10^-12)" },
        { RDM_PREFIX_FEMPTO,    "fempto (x10^-15)" },
        { RDM_PREFIX_ATTO,      "atto (x10^-18)" },
        { RDM_PREFIX_ZEPTO,     "zepto (x10^-21)" },
        { RDM_PREFIX_YOCTO,     "yocto (x10^-24)" },
        { RDM_PREFIX_DECA,      "deca (x10^1)" },
        { RDM_PREFIX_HECTO,     "hecto (x10^2)" },
        { RDM_PREFIX_KILO,      "kilo (x10^3)" },
        { RDM_PREFIX_MEGA,      "mega (x10^6)" },
        { RDM_PREFIX_GIGA,      "giga (x10^9)" },
        { RDM_PREFIX_TERRA,     "terra (x10^12)" },
        { RDM_PREFIX_PETA,      "peta (x10^15)" },
        { RDM_PREFIX_EXA,       "exa (x10^18)" },
        { RDM_PREFIX_ZETTA,     "zetta (x10^21)" },
        { RDM_PREFIX_YOTTA,     "yotta (x10^24)" },
        { 0, NULL },
};
static value_string_ext rdm_prefix_vals_ext = VALUE_STRING_EXT_INIT(rdm_prefix_vals);

#define RDM_UNITS_NONE                        0x00
#define RDM_UNITS_CENTIGRADE                  0x01
#define RDM_UNITS_VOLTS_DC                    0x02
#define RDM_UNITS_VOLTS_AC_PEAK               0x03
#define RDM_UNITS_VOLTS_AC_RMS                0x04
#define RDM_UNITS_AMPERE_DC                   0x05
#define RDM_UNITS_AMPERE_AC_PEAK              0x06
#define RDM_UNITS_AMPERE_AC_RMS               0x07
#define RDM_UNITS_HERTZ                       0x08
#define RDM_UNITS_OHM                         0x09
#define RDM_UNITS_WATT                        0x0A
#define RDM_UNITS_KILOGRAM                    0x0B
#define RDM_UNITS_METERS                      0x0C
#define RDM_UNITS_METERS_SQUARED              0x0D
#define RDM_UNITS_METERS_CUBED                0x0E
#define RDM_UNITS_KILOGRAMMES_PER_METER_CUBED 0x0F
#define RDM_UNITS_METERS_PER_SECOND           0x10
#define RDM_UNITS_METERS_PER_SECOND_SQUARED   0x11
#define RDM_UNITS_NEWTON                      0x12
#define RDM_UNITS_JOULE                       0x13
#define RDM_UNITS_PASCAL                      0x14
#define RDM_UNITS_SECOND                      0x15
#define RDM_UNITS_DEGREE                      0x16
#define RDM_UNITS_STERADIAN                   0x17
#define RDM_UNITS_CANDELA                     0x18
#define RDM_UNITS_LUMEN                       0x19
#define RDM_UNITS_LUX                         0x1A
#define RDM_UNITS_IRE                         0x1B
#define RDM_UNITS_BYTE                        0x1C

static const value_string rdm_unit_vals[] = {
        { RDM_UNITS_NONE,                        "NONE" },
        { RDM_UNITS_CENTIGRADE,                  "Centigrade" },
        { RDM_UNITS_VOLTS_DC,                    "Volts DC" },
        { RDM_UNITS_VOLTS_AC_PEAK,               "Volts AC Peak" },
        { RDM_UNITS_VOLTS_AC_RMS,                "Volts AC RMS" },
        { RDM_UNITS_AMPERE_DC,                   "Ampere DC" },
        { RDM_UNITS_AMPERE_AC_PEAK,              "Ampere AC Peak" },
        { RDM_UNITS_AMPERE_AC_RMS,               "Ampere AC RMS" },
        { RDM_UNITS_HERTZ,                       "Hertz" },
        { RDM_UNITS_OHM,                         "Ohm" },
        { RDM_UNITS_WATT,                        "Watt" },
        { RDM_UNITS_KILOGRAM,                    "Kilogram" },
        { RDM_UNITS_METERS,                      "Meters" },
        { RDM_UNITS_METERS_SQUARED,              "Meters Squared" },
        { RDM_UNITS_METERS_CUBED,                "Meters Cubed" },
        { RDM_UNITS_KILOGRAMMES_PER_METER_CUBED, "Kilogrammes per Meter Cubed" },
        { RDM_UNITS_METERS_PER_SECOND,           "Meters per Second" },
        { RDM_UNITS_METERS_PER_SECOND_SQUARED,   "Meters per Second Squared" },
        { RDM_UNITS_NEWTON,                      "Newton" },
        { RDM_UNITS_JOULE,                       "Joule" },
        { RDM_UNITS_PASCAL,                      "Pascal" },
        { RDM_UNITS_SECOND,                      "Second" },
        { RDM_UNITS_DEGREE,                      "Degree" },
        { RDM_UNITS_STERADIAN,                   "Steradian" },
        { RDM_UNITS_CANDELA,                     "Candela" },
        { RDM_UNITS_LUMEN,                       "Lumen" },
        { RDM_UNITS_LUX,                         "Lux" },
        { RDM_UNITS_IRE,                         "Ire" },
        { RDM_UNITS_BYTE,                        "Byte" },
        { 0, NULL },
};
static value_string_ext rdm_unit_vals_ext = VALUE_STRING_EXT_INIT(rdm_unit_vals);

#define RDM_SENS_TEMPERATURE        0x00
#define RDM_SENS_VOLTAGE            0x01
#define RDM_SENS_CURRENT            0x02
#define RDM_SENS_FREQUENCY          0x03
#define RDM_SENS_RESISTANCE         0x04
#define RDM_SENS_POWER              0x05
#define RDM_SENS_MASS               0x06
#define RDM_SENS_LENGTH             0x07
#define RDM_SENS_AREA               0x08
#define RDM_SENS_VOLUME             0x09
#define RDM_SENS_DENSITY            0x0A
#define RDM_SENS_VELOCITY           0x0B
#define RDM_SENS_ACCELERATION       0x0C
#define RDM_SENS_FORCE              0x0D
#define RDM_SENS_ENERGY             0x0E
#define RDM_SENS_PRESSURE           0x0F
#define RDM_SENS_TIME               0x10
#define RDM_SENS_ANGLE              0x11
#define RDM_SENS_POSITION_X         0x12
#define RDM_SENS_POSITION_Y         0x13
#define RDM_SENS_POSITION_Z         0x14
#define RDM_SENS_ANGULAR_VELOCITY   0x15
#define RDM_SENS_LUMINOUS_INTENSITY 0x16
#define RDM_SENS_LUMINOUS_FLUX      0x17
#define RDM_SENS_ILLUMINANCE        0x18
#define RDM_SENS_CHROMINANCE_RED    0x19
#define RDM_SENS_CHROMINANCE_GREEN  0x1A
#define RDM_SENS_CHROMINANCE_BLUE   0x1B
#define RDM_SENS_CONTACTS           0x1C
#define RDM_SENS_MEMORY             0x1D
#define RDM_SENS_ITEMS              0x1E
#define RDM_SENS_HUMIDITY           0x1F
#define RDM_SENS_COUNTER_16BIT      0x20
#define RDM_SENS_OTHER              0x7F

static const value_string rdm_sensor_type_vals[] = {
        { RDM_SENS_TEMPERATURE,         "Temperature" },
        { RDM_SENS_VOLTAGE,             "Voltage" },
        { RDM_SENS_CURRENT,             "Current" },
        { RDM_SENS_FREQUENCY,           "Frequency" },
        { RDM_SENS_RESISTANCE,          "Resistance" },
        { RDM_SENS_POWER,               "Power" },
        { RDM_SENS_MASS,                "Mass" },
        { RDM_SENS_LENGTH,              "Length" },
        { RDM_SENS_AREA,                "Area" },
        { RDM_SENS_VOLUME,              "Volume" },
        { RDM_SENS_DENSITY,             "Density" },
        { RDM_SENS_VELOCITY,            "Velocity" },
        { RDM_SENS_ACCELERATION,        "Acceleration" },
        { RDM_SENS_FORCE,               "Force" },
        { RDM_SENS_ENERGY,              "Energy" },
        { RDM_SENS_PRESSURE,            "Pressure" },
        { RDM_SENS_TIME,                "Time" },
        { RDM_SENS_ANGLE,               "Angle" },
        { RDM_SENS_POSITION_X,          "Position X" },
        { RDM_SENS_POSITION_Y,          "Position Y" },
        { RDM_SENS_POSITION_Z,          "Position Z" },
        { RDM_SENS_ANGULAR_VELOCITY,    "Angular Velocity" },
        { RDM_SENS_LUMINOUS_INTENSITY,  "Luminous Intensity" },
        { RDM_SENS_LUMINOUS_FLUX,       "Luminous Flux" },
        { RDM_SENS_ILLUMINANCE,         "Illuminance" },
        { RDM_SENS_CHROMINANCE_RED,     "Chrominance Red" },
        { RDM_SENS_CHROMINANCE_GREEN,   "Chrominance Green" },
        { RDM_SENS_CHROMINANCE_BLUE,    "Chrominance Blue" },
        { RDM_SENS_CONTACTS,            "Contacts" },
        { RDM_SENS_MEMORY,              "Memory" },
        { RDM_SENS_ITEMS,               "Items" },
        { RDM_SENS_HUMIDITY,            "Humidity" },
        { RDM_SENS_COUNTER_16BIT,       "Counter 16bit" },
        { RDM_SENS_OTHER,               "Other" },
        { 0, NULL} ,
};
static value_string_ext rdm_sensor_type_vals_ext = VALUE_STRING_EXT_INIT(rdm_sensor_type_vals);

#define RDM_PRODUCT_CATEGORY_NOT_DECLARED               0x0000
#define RDM_PRODUCT_CATEGORY_FIXTURE                    0x0100
#define RDM_PRODUCT_CATEGORY_FIXTURE_FIXED              0x0101
#define RDM_PRODUCT_CATEGORY_FIXTURE_MOVING_YOKE        0x0102
#define RDM_PRODUCT_CATEGORY_FIXTURE_MOVING_MIRROR      0x0103
#define RDM_PRODUCT_CATEGORY_FIXTURE_OTHER              0x01FF
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY          0x0200
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_COLOR    0x0201
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_YOKE     0x0202
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_MIRROR   0x0203
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_EFFECT   0x0204
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_BEAM     0x0205
#define RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_OTHER    0x02FF
#define RDM_PRODUCT_CATEGORY_PROJECTOR                  0x0300
#define RDM_PRODUCT_CATEGORY_PROJECTOR_FIXED            0x0301
#define RDM_PRODUCT_CATEGORY_PROJECTOR_MOVING_YOKE      0x0302
#define RDM_PRODUCT_CATEGORY_PROJECTOR_MOVING_MIRROR    0x0303
#define RDM_PRODUCT_CATEGORY_PROJECTOR_OTHER            0x03FF
#define RDM_PRODUCT_CATEGORY_ATMOSPHERIC                0x0400
#define RDM_PRODUCT_CATEGORY_ATMOSPHERIC_EFFECT         0x0401
#define RDM_PRODUCT_CATEGORY_ATMOSPHERIC_PYRO           0x0402
#define RDM_PRODUCT_CATEGORY_ATMOSPHERIC_OTHER          0x04FF
#define RDM_PRODUCT_CATEGORY_DIMMER                     0x0500
#define RDM_PRODUCT_CATEGORY_DIMMER_AC_INCANDESCENT     0x0501
#define RDM_PRODUCT_CATEGORY_DIMMER_AC_FLUORESCENT      0x0502
#define RDM_PRODUCT_CATEGORY_DIMMER_AC_COLDCATHODE      0x0503
#define RDM_PRODUCT_CATEGORY_DIMMER_AC_NONDIM           0x0504
#define RDM_PRODUCT_CATEGORY_DIMMER_AC_ELV              0x0505
#define RDM_PRODUCT_CATEGORY_DIMMER_AC_OTHER            0x0506
#define RDM_PRODUCT_CATEGORY_DIMMER_DC_LEVEL            0x0507
#define RDM_PRODUCT_CATEGORY_DIMMER_DC_PWM              0x0508
#define RDM_PRODUCT_CATEGORY_DIMMER_CS_LED              0x0509
#define RDM_PRODUCT_CATEGORY_DIMMER_OTHER               0x05FF
#define RDM_PRODUCT_CATEGORY_POWER                      0x0600
#define RDM_PRODUCT_CATEGORY_POWER_CONTROL              0x0601
#define RDM_PRODUCT_CATEGORY_POWER_SOURCE               0x0602
#define RDM_PRODUCT_CATEGORY_POWER_OTHER                0x06FF
#define RDM_PRODUCT_CATEGORY_SCENIC                     0x0700
#define RDM_PRODUCT_CATEGORY_SCENIC_DRIVE               0x0701
#define RDM_PRODUCT_CATEGORY_SCENIC_OTHER               0x07FF
#define RDM_PRODUCT_CATEGORY_DATA                       0x0800
#define RDM_PRODUCT_CATEGORY_DATA_DISTRIBUTION          0x0801
#define RDM_PRODUCT_CATEGORY_DATA_CONVERSION            0x0802
#define RDM_PRODUCT_CATEGORY_DATA_OTHER                 0x08FF
#define RDM_PRODUCT_CATEGORY_AV                         0x0900
#define RDM_PRODUCT_CATEGORY_AV_AUDIO                   0x0901
#define RDM_PRODUCT_CATEGORY_AV_VIDEO                   0x0902
#define RDM_PRODUCT_CATEGORY_AV_OTHER                   0x09FF
#define RDM_PRODUCT_CATEGORY_MONITOR                    0x0A00
#define RDM_PRODUCT_CATEGORY_MONITOR_ACLINEPOWER        0x0A01
#define RDM_PRODUCT_CATEGORY_MONITOR_DCPOWER            0x0A02
#define RDM_PRODUCT_CATEGORY_MONITOR_ENVIRONMENTAL      0x0A03
#define RDM_PRODUCT_CATEGORY_MONITOR_OTHER              0x0AFF
#define RDM_PRODUCT_CATEGORY_CONTROL                    0x7000
#define RDM_PRODUCT_CATEGORY_CONTROL_CONTROLLER         0x7001
#define RDM_PRODUCT_CATEGORY_CONTROL_BACKUPDEVICE       0x7002
#define RDM_PRODUCT_CATEGORY_CONTROL_OTHER              0x70FF
#define RDM_PRODUCT_CATEGORY_TEST                       0x7100
#define RDM_PRODUCT_CATEGORY_TEST_EQUIPMENT             0x7101
#define RDM_PRODUCT_CATEGORY_TEST_EQUIPMENT_OTHER       0x71FF
#define RDM_PRODUCT_CATEGORY_OTHER                      0x7FFF

static const value_string rdm_product_cat_vals[] = {
        { RDM_PRODUCT_CATEGORY_NOT_DECLARED,             "Not Declared" },
        { RDM_PRODUCT_CATEGORY_FIXTURE,                  "Fixture" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_FIXED,            "Fixture Fixed" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_MOVING_YOKE,      "Fixture Moving Yoke" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_MOVING_MIRROR,    "Fixture Moving Mirror" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_OTHER,            "Fixture Other" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY,        "Fixture Accessory" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_COLOR,  "Fixture Accessory Color" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_YOKE,   "Fixture Accessory Yoke" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_MIRROR, "Fixture Accessory Mirror" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_EFFECT, "Fixture Accessory Effect" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_BEAM,   "Fixture Accessory Beam" },
        { RDM_PRODUCT_CATEGORY_FIXTURE_ACCESSORY_OTHER,  "Fixture Accessory Other" },
        { RDM_PRODUCT_CATEGORY_PROJECTOR,                "Projector" },
        { RDM_PRODUCT_CATEGORY_PROJECTOR_FIXED,          "Projector Fixed" },
        { RDM_PRODUCT_CATEGORY_PROJECTOR_MOVING_YOKE,    "Projector Moving Yoke" },
        { RDM_PRODUCT_CATEGORY_PROJECTOR_MOVING_MIRROR,  "Projector Moving Mirror" },
        { RDM_PRODUCT_CATEGORY_PROJECTOR_OTHER,          "Projector Other" },
        { RDM_PRODUCT_CATEGORY_ATMOSPHERIC,              "Atmospheric" },
        { RDM_PRODUCT_CATEGORY_ATMOSPHERIC_EFFECT,       "Atmospheric Effect" },
        { RDM_PRODUCT_CATEGORY_ATMOSPHERIC_PYRO,         "Atmospheric Pyro" },
        { RDM_PRODUCT_CATEGORY_ATMOSPHERIC_OTHER,        "Atmospheric Other" },
        { RDM_PRODUCT_CATEGORY_DIMMER,                   "Dimmer" },
        { RDM_PRODUCT_CATEGORY_DIMMER_AC_INCANDESCENT,   "Dimmer AC Incandescent" },
        { RDM_PRODUCT_CATEGORY_DIMMER_AC_FLUORESCENT,    "Dimmer AC Fluorescent" },
        { RDM_PRODUCT_CATEGORY_DIMMER_AC_COLDCATHODE,    "Dimmer AC Coldcathode" },
        { RDM_PRODUCT_CATEGORY_DIMMER_AC_NONDIM,         "Dimmer AC Nondim" },
        { RDM_PRODUCT_CATEGORY_DIMMER_AC_ELV,            "Dimmer AC ELV" },
        { RDM_PRODUCT_CATEGORY_DIMMER_AC_OTHER,          "Dimmer AC Other" },
        { RDM_PRODUCT_CATEGORY_DIMMER_DC_LEVEL,          "Dimmer DC Level" },
        { RDM_PRODUCT_CATEGORY_DIMMER_DC_PWM,            "Dimmer DC PWM" },
        { RDM_PRODUCT_CATEGORY_DIMMER_CS_LED,            "Dimmer CS LED" },
        { RDM_PRODUCT_CATEGORY_DIMMER_OTHER,             "Dimmer Other" },
        { RDM_PRODUCT_CATEGORY_POWER,                    "Power" },
        { RDM_PRODUCT_CATEGORY_POWER_CONTROL,            "Power Control" },
        { RDM_PRODUCT_CATEGORY_POWER_SOURCE,             "Power Source" },
        { RDM_PRODUCT_CATEGORY_POWER_OTHER,              "Power Other" },
        { RDM_PRODUCT_CATEGORY_SCENIC,                   "Scenic" },
        { RDM_PRODUCT_CATEGORY_SCENIC_DRIVE,             "Scenic Drive" },
        { RDM_PRODUCT_CATEGORY_SCENIC_OTHER,             "Scenic Other" },
        { RDM_PRODUCT_CATEGORY_DATA,                     "Data" },
        { RDM_PRODUCT_CATEGORY_DATA_DISTRIBUTION,        "Data Distribution" },
        { RDM_PRODUCT_CATEGORY_DATA_CONVERSION,          "Data Conversion" },
        { RDM_PRODUCT_CATEGORY_DATA_OTHER,               "Data Other" },
        { RDM_PRODUCT_CATEGORY_AV,                       "AV" },
        { RDM_PRODUCT_CATEGORY_AV_AUDIO,                 "AV Audio" },
        { RDM_PRODUCT_CATEGORY_AV_VIDEO,                 "AV Video" },
        { RDM_PRODUCT_CATEGORY_AV_OTHER,                 "AV Other" },
        { RDM_PRODUCT_CATEGORY_MONITOR,                  "Monitor" },
        { RDM_PRODUCT_CATEGORY_MONITOR_ACLINEPOWER,      "Monitor AC Line Power" },
        { RDM_PRODUCT_CATEGORY_MONITOR_DCPOWER,          "Monitor DC Power" },
        { RDM_PRODUCT_CATEGORY_MONITOR_ENVIRONMENTAL,    "Monitor Environmental" },
        { RDM_PRODUCT_CATEGORY_MONITOR_OTHER,            "Monitor Other" },
        { RDM_PRODUCT_CATEGORY_CONTROL,                  "Control" },
        { RDM_PRODUCT_CATEGORY_CONTROL_CONTROLLER,       "Control Controller" },
        { RDM_PRODUCT_CATEGORY_CONTROL_BACKUPDEVICE,     "Control Backup Device" },
        { RDM_PRODUCT_CATEGORY_CONTROL_OTHER,            "Control Other" },
        { RDM_PRODUCT_CATEGORY_TEST,                     "Test" },
        { RDM_PRODUCT_CATEGORY_TEST_EQUIPMENT,           "Test Equipment" },
        { RDM_PRODUCT_CATEGORY_TEST_EQUIPMENT_OTHER,     "Test Equipment Other" },
        { RDM_PRODUCT_CATEGORY_OTHER,                    "Other" },
        { 0, NULL },
};
static value_string_ext rdm_product_cat_vals_ext = VALUE_STRING_EXT_INIT(rdm_product_cat_vals);

static int proto_rdm = -1;

static int hf_rdm_sub_start_code = -1;
static int hf_rdm_message_length = -1;
static int hf_rdm_dest_uid = -1;
static int hf_rdm_src_uid = -1;
static int hf_rdm_transaction_number = -1;
static int hf_rdm_port_id = -1;
static int hf_rdm_response_type = -1;
static int hf_rdm_message_count = -1;
static int hf_rdm_sub_device = -1;
static int hf_rdm_mdb = -1;
static int hf_rdm_command_class = -1;
static int hf_rdm_parameter_id = -1;
static int hf_rdm_parameter_data_length = -1;
static int hf_rdm_parameter_data = -1;
static int hf_rdm_parameter_data_raw = -1;
static int hf_rdm_intron = -1;
static int hf_rdm_checksum = -1;
static int hf_rdm_checksum_status = -1;
static int hf_rdm_trailer = -1;

static int hf_rdm_pd_device_label = -1;

static int hf_rdm_pd_manu_label = -1;

static int hf_rdm_pd_dmx_start_address = -1;

static int hf_rdm_pd_queued_message_status = -1;

static int hf_rdm_pd_sensor_nr = -1;
static int hf_rdm_pd_sensor_type = -1;
static int hf_rdm_pd_sensor_unit = -1;
static int hf_rdm_pd_sensor_prefix = -1;
static int hf_rdm_pd_sensor_value_pres = -1;
static int hf_rdm_pd_sensor_value_low = -1;
static int hf_rdm_pd_sensor_value_high = -1;
static int hf_rdm_pd_sensor_value_rec = -1;

static int hf_rdm_pd_sensor_range_min_value = -1;
static int hf_rdm_pd_sensor_range_max_value = -1;
static int hf_rdm_pd_sensor_normal_min_value = -1;
static int hf_rdm_pd_sensor_normal_max_value = -1;
static int hf_rdm_pd_sensor_recorded_value_support = -1;
static int hf_rdm_pd_sensor_description = -1;

static int hf_rdm_pd_device_hours = -1;
static int hf_rdm_pd_lamp_hours = -1;
static int hf_rdm_pd_lamp_strikes = -1;


static int hf_rdm_pd_proto_vers = -1;
static int hf_rdm_pd_device_model_id = -1;
static int hf_rdm_pd_product_cat = -1;
static int hf_rdm_pd_software_vers_id = -1;
static int hf_rdm_pd_dmx_footprint = -1;
static int hf_rdm_pd_dmx_pers_current = -1;
static int hf_rdm_pd_dmx_pers_total = -1;
static int hf_rdm_pd_sub_device_count = -1;
static int hf_rdm_pd_sensor_count = -1;

static int hf_rdm_pd_device_model_description = -1;

static int hf_rdm_pd_disc_unique_branch_lb_uid = -1;
static int hf_rdm_pd_disc_unique_branch_ub_uid = -1;
static int hf_rdm_pd_disc_mute_control_field = -1;
static int hf_rdm_pd_disc_mute_binding_uid = -1;
static int hf_rdm_pd_disc_unmute_control_field = -1;
static int hf_rdm_pd_disc_unmute_binding_uid = -1;
static int hf_rdm_pd_proxied_devices_uid = -1;
static int hf_rdm_pd_proxied_device_count = -1;
static int hf_rdm_pd_proxied_device_list_change = -1;
static int hf_rdm_pd_real_time_clock_year = -1;
static int hf_rdm_pd_real_time_clock_month = -1;
static int hf_rdm_pd_real_time_clock_day = -1;
static int hf_rdm_pd_real_time_clock_hour = -1;
static int hf_rdm_pd_real_time_clock_minute = -1;
static int hf_rdm_pd_real_time_clock_second = -1;
static int hf_rdm_pd_lamp_state = -1;
static int hf_rdm_pd_lamp_on_mode = -1;
static int hf_rdm_pd_device_power_cycles = -1;
static int hf_rdm_pd_display_invert = -1;
static int hf_rdm_pd_display_level = -1;
static int hf_rdm_pd_pan_invert = -1;
static int hf_rdm_pd_tilt_invert = -1;
static int hf_rdm_pd_tilt_swap = -1;
static int hf_rdm_pd_selftest_nr = -1;
static int hf_rdm_pd_selftest_state = -1;
static int hf_rdm_pd_selftest_description = -1;
static int hf_rdm_pd_language_code = -1;
static int hf_rdm_pd_identify_device = -1;
static int hf_rdm_pd_identify_device_state = -1;
static int hf_rdm_pd_reset_device = -1;
static int hf_rdm_pd_power_state = -1;
static int hf_rdm_pd_capture_preset_scene_nr = -1;
static int hf_rdm_pd_capture_preset_up_fade_time = -1;
static int hf_rdm_pd_capture_preset_down_fade_time = -1;
static int hf_rdm_pd_capture_preset_wait_time = -1;
static int hf_rdm_pd_preset_playback_mode = -1;
static int hf_rdm_pd_preset_playback_level = -1;
static int hf_rdm_pd_parameter_id = -1;
static int hf_rdm_pd_parameter_pdl_size = -1;
static int hf_rdm_pd_parameter_data_type = -1;
static int hf_rdm_pd_parameter_cmd_class = -1;
static int hf_rdm_pd_parameter_type = -1;
static int hf_rdm_pd_parameter_unit = -1;
static int hf_rdm_pd_parameter_prefix = -1;
static int hf_rdm_pd_parameter_min_value = -1;
static int hf_rdm_pd_parameter_max_value = -1;
static int hf_rdm_pd_parameter_default_value = -1;
static int hf_rdm_pd_parameter_description = -1;
static int hf_rdm_pd_software_version_label = -1;
static int hf_rdm_pd_boot_software_version_id = -1;
static int hf_rdm_pd_boot_software_version_label = -1;
static int hf_rdm_pd_comms_status_short_msg = -1;
static int hf_rdm_pd_comms_status_len_mismatch = -1;
static int hf_rdm_pd_comms_status_csum_fail = -1;
static int hf_rdm_pd_status_messages_type = -1;
static int hf_rdm_pd_status_messages_sub_device_id = -1;
static int hf_rdm_pd_status_messages_id = -1;
static int hf_rdm_pd_status_messages_data_value_1 = -1;
static int hf_rdm_pd_status_messages_data_value_2 = -1;
static int hf_rdm_pd_status_id = -1;
static int hf_rdm_pd_status_id_description = -1;
static int hf_rdm_pd_sub_device_status_report_threshold_status_type = -1;
static int hf_rdm_pd_product_detail_id_list = -1;
static int hf_rdm_pd_factory_defaults = -1;
static int hf_rdm_pd_dmx_pers_nr = -1;
static int hf_rdm_pd_dmx_pers_count = -1;
static int hf_rdm_pd_dmx_pers_description = -1;
static int hf_rdm_pd_dmx_pers_slots = -1;
static int hf_rdm_pd_dmx_pers_text = -1;
static int hf_rdm_pd_slot_offset = -1;
static int hf_rdm_pd_slot_type = -1;
static int hf_rdm_pd_slot_label_id = -1;
static int hf_rdm_pd_slot_nr = -1;
static int hf_rdm_pd_slot_description = -1;
static int hf_rdm_pd_slot_value = -1;
static int hf_rdm_pd_rec_value_support = -1;

static int ett_rdm = -1;

static guint16
rdm_checksum(tvbuff_t *tvb, guint length)
{
        guint16 sum = RDM_SC_RDM;
        guint   i;
        for (i = 0; i < length; i++)
                sum += tvb_get_guint8(tvb, i);
        return sum;
}

static guint
dissect_rdm_pd_queued_message(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_queued_message_status, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_dmx_start_address(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_dmx_start_address, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_device_info(tvbuff_t *tvb _U_, guint offset, proto_tree *tree _U_, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_proto_vers, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_device_model_id, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_product_cat, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_software_vers_id, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset +=  4;

                proto_tree_add_item(tree, hf_rdm_pd_dmx_footprint, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_current, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_total, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_dmx_start_address, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_sub_device_count, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_count, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                break;
        }

        return offset;
}


static guint
dissect_rdm_pd_device_model_description(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_device_model_description, tvb,
                        offset, len, ENC_ASCII|ENC_NA);
                offset +=  len;
                break;
        }

        return offset;
}


static guint
dissect_rdm_pd_device_label(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_device_label, tvb,
                        offset, len, ENC_ASCII|ENC_NA);
                offset +=  len;
                break;
        }

        return offset;
}


static guint
dissect_rdm_pd_device_hours(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_device_hours, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset +=  4;
                break;
        }

        return offset;
}


static guint
dissect_rdm_pd_lamp_hours(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_lamp_hours, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset +=  4;
                break;
        }

        return offset;
}


static guint
dissect_rdm_pd_lamp_strikes(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_lamp_strikes, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset +=  4;
                break;
        }

        return offset;
}


static guint
dissect_rdm_pd_sensor_definition(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_sensor_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_sensor_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_unit, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_prefix, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_range_min_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_range_max_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_normal_min_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_normal_max_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_recorded_value_support, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                proto_tree_add_item(tree, hf_rdm_pd_sensor_description, tvb,
                        offset, len - 13, ENC_ASCII|ENC_NA);
                offset += (len - 13);
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_sensor_value(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_sensor_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
        case RDM_CC_SET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_sensor_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_value_pres, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset +=  2;

                if (len == 7 || len == 9) {
                        proto_tree_add_item(tree, hf_rdm_pd_sensor_value_low, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset +=  2;
                        proto_tree_add_item(tree, hf_rdm_pd_sensor_value_high, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset +=  2;
                }

                if (len == 5 || len == 9) {
                        proto_tree_add_item(tree, hf_rdm_pd_sensor_value_rec, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset +=  2;
                }

                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_manufacturer_label(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_manu_label, tvb,
                        offset, len, ENC_ASCII|ENC_NA);
                offset +=  len;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_disc_unique_branch(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_DISCOVERY_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_disc_unique_branch_lb_uid, tvb,
                        offset, 6, ENC_NA);
                offset += 6;

                proto_tree_add_item(tree, hf_rdm_pd_disc_unique_branch_ub_uid, tvb,
                        offset, 6, ENC_NA);
                offset += 6;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_disc_mute(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_DISCOVERY_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_disc_mute_control_field, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                if (len > 2) {
                        proto_tree_add_item(tree, hf_rdm_pd_disc_mute_binding_uid, tvb,
                                offset, 6, ENC_NA);
                        offset += 6;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_disc_un_mute(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_DISCOVERY_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_disc_unmute_control_field, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                if (len > 2) {
                        proto_tree_add_item(tree, hf_rdm_pd_disc_unmute_binding_uid, tvb,
                                offset, 6, ENC_NA);
                        offset += 6;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_proxied_devices(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 6) {
                        proto_tree_add_item(tree, hf_rdm_pd_proxied_devices_uid, tvb,
                                offset, 6, ENC_NA);
                        offset += 6;
                        len    -= 6;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_proxied_device_count(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_proxied_device_count, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_proxied_device_list_change, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_comms_status(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_comms_status_short_msg, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_comms_status_len_mismatch, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_comms_status_csum_fail, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_status_messages(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_status_messages_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 9) {
                        proto_tree_add_item(tree, hf_rdm_pd_status_messages_sub_device_id, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                        proto_tree_add_item(tree, hf_rdm_pd_status_messages_type, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
                        offset += 1;
                        len    -= 1;
                        proto_tree_add_item(tree, hf_rdm_pd_status_messages_id, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                        proto_tree_add_item(tree, hf_rdm_pd_status_messages_data_value_1, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                        proto_tree_add_item(tree, hf_rdm_pd_status_messages_data_value_2, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_status_id_description(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_status_id, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_status_id_description, tvb,
                        offset, len, ENC_ASCII|ENC_NA);
                offset += len;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_clear_status_id(tvbuff_t *tvb _U_, guint offset, proto_tree *tree _U_, guint8 cc _U_, guint8 len _U_)
{
        return offset;
}

static guint
dissect_rdm_pd_sub_device_status_report_threshold(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_sub_device_status_report_threshold_status_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_supported_parameters(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 2) {
                        proto_tree_add_item(tree, hf_rdm_pd_parameter_id, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_parameter_description(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_parameter_id, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_parameter_id, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_pdl_size, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_data_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_cmd_class, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_unit, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_prefix, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_min_value, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_max_value, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_default_value, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                proto_tree_add_item(tree, hf_rdm_pd_parameter_description, tvb,
                        offset, len - 0x14, ENC_ASCII|ENC_NA);
                offset += (len - 0x14);
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_product_detail_id_list(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 2) {
                        proto_tree_add_item(tree, hf_rdm_pd_product_detail_id_list, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_factory_defaults(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_factory_defaults, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_language_capabilities(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 2) {
                        proto_tree_add_item(tree, hf_rdm_pd_language_code, tvb,
                                offset, 2, ENC_ASCII|ENC_NA);
                        offset += 2;
                        len    -= 2;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_language(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_language_code, tvb,
                        offset, 2, ENC_ASCII|ENC_NA);
                offset += 2;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_software_version_label(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_software_version_label, tvb,
                        offset, len, ENC_ASCII|ENC_NA);
                offset += len;

                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_boot_software_version_id(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_boot_software_version_id, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset += 4;

                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_boot_software_version_label(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_boot_software_version_label, tvb,
                        offset, len, ENC_ASCII|ENC_NA);
                offset += len;

                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_dmx_personality(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_current, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_count, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_dmx_personality_description(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_description, tvb,
                        offset, 1, ENC_ASCII|ENC_NA);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_description, tvb,
                        offset, 1, ENC_ASCII|ENC_NA);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_slots, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_dmx_pers_text, tvb,
                        offset, (len - 3), ENC_ASCII|ENC_NA);
                offset += (len - 3);
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_slot_info(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 5) {
                        proto_tree_add_item(tree, hf_rdm_pd_slot_offset, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                        proto_tree_add_item(tree, hf_rdm_pd_slot_type, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
                        offset += 1;
                        len    -= 1;
                        proto_tree_add_item(tree, hf_rdm_pd_slot_label_id, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_slot_description(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_slot_nr, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_slot_nr, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_slot_description, tvb,
                        offset, (len - 2), ENC_ASCII|ENC_NA);
                offset += (len - 2);
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_slot_value(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND_RESPONSE:
                while (len >= 3) {
                        proto_tree_add_item(tree, hf_rdm_pd_slot_offset, tvb,
                                offset, 2, ENC_BIG_ENDIAN);
                        offset += 2;
                        len    -= 2;
                        proto_tree_add_item(tree, hf_rdm_pd_slot_value, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
                        offset += 1;
                        len    -= 1;
                }
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_record_sensors(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_sensor_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_sensor_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_unit, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_prefix, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_range_min_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_range_max_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_normal_min_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_normal_max_value, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_rec_value_support, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_sensor_description, tvb,
                        offset, (len - 13), ENC_ASCII|ENC_NA);
                offset += (len - 13);

                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_lamp_state(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_lamp_state, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_lamp_on_mode(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_lamp_on_mode, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_device_power_cycles(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_device_power_cycles, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_display_invert(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_display_invert, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_display_level(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_display_level, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_pan_invert(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_pan_invert, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_tilt_invert(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_tilt_invert, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_pan_tilt_swap(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_tilt_swap, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_real_time_clock(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_real_time_clock_year, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_real_time_clock_month, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_real_time_clock_day, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_real_time_clock_hour, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_real_time_clock_minute, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_real_time_clock_second, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_identify_device(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_identify_device, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_identify_device_state, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_reset_device(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_reset_device, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_power_state(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_power_state, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_perform_selftest(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_selftest_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_selftest_state, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_self_test_description(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len)
{
        switch(cc) {
        case RDM_CC_GET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_selftest_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_selftest_nr, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                proto_tree_add_item(tree, hf_rdm_pd_selftest_description, tvb,
                        offset, (len - 1), ENC_ASCII|ENC_NA);
                offset += (len - 1);
                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_capture_preset(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_pd_capture_preset_scene_nr, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_capture_preset_up_fade_time, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_capture_preset_down_fade_time, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_capture_preset_wait_time, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;

                break;
        }

        return offset;
}

static guint
dissect_rdm_pd_preset_playback(tvbuff_t *tvb, guint offset, proto_tree *tree, guint8 cc, guint8 len _U_)
{
        switch(cc) {
        case RDM_CC_SET_COMMAND:
        case RDM_CC_GET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_pd_preset_playback_mode, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                proto_tree_add_item(tree, hf_rdm_pd_preset_playback_level, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        return offset;
}

static guint
dissect_rdm_mdb(tvbuff_t *tvb, guint offset, proto_tree *tree)
{
        guint8      cc;
        guint16     param_id;
        guint8      parameter_data_length;
        proto_tree *hi,*si, *mdb_tree;

        cc = tvb_get_guint8(tvb, offset + 4);

        switch (cc) {
        case RDM_CC_DISCOVERY_COMMAND:
        case RDM_CC_GET_COMMAND:
        case RDM_CC_SET_COMMAND:
                proto_tree_add_item(tree, hf_rdm_port_id, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;

        case RDM_CC_DISCOVERY_COMMAND_RESPONSE:
        case RDM_CC_GET_COMMAND_RESPONSE:
        case RDM_CC_SET_COMMAND_RESPONSE:
                proto_tree_add_item(tree, hf_rdm_response_type, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
                offset += 1;
                break;
        }

        proto_tree_add_item(tree, hf_rdm_message_count, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        proto_tree_add_item(tree, hf_rdm_sub_device, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        hi = proto_tree_add_item(tree, hf_rdm_mdb, tvb,
                        offset, -1, ENC_NA);
        mdb_tree = proto_item_add_subtree(hi,ett_rdm);


        proto_tree_add_item(mdb_tree, hf_rdm_command_class, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        param_id = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(mdb_tree, hf_rdm_parameter_id, tvb,
                        offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        parameter_data_length = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(mdb_tree, hf_rdm_parameter_data_length, tvb,
                        offset, 1, ENC_BIG_ENDIAN);
        offset += 1;
        proto_item_set_len( mdb_tree,  parameter_data_length + 4);

        if (parameter_data_length > 0) {
                hi = proto_tree_add_item(mdb_tree, hf_rdm_parameter_data, tvb,
                                offset, parameter_data_length, ENC_NA);
                si = proto_item_add_subtree(hi,ett_rdm);

                switch(param_id) {
                case RDM_PARAM_ID_SENSOR_VALUE:
                        offset = dissect_rdm_pd_sensor_value(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_QUEUED_MESSAGE:
                        offset = dissect_rdm_pd_queued_message(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DMX_START_ADDRESS:
                        offset = dissect_rdm_pd_dmx_start_address(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DEVICE_INFO:
                        offset = dissect_rdm_pd_device_info(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DEVICE_MODEL_DESCRIPTION:
                        offset = dissect_rdm_pd_device_model_description(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DEVICE_LABEL:
                        offset = dissect_rdm_pd_device_label(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DEVICE_HOURS:
                        offset = dissect_rdm_pd_device_hours(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_LAMP_HOURS:
                        offset = dissect_rdm_pd_lamp_hours(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_LAMP_STRIKES:
                        offset = dissect_rdm_pd_lamp_strikes(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SENSOR_DEFINITION:
                        offset = dissect_rdm_pd_sensor_definition(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_MANUFACTURER_LABEL:
                        offset = dissect_rdm_pd_manufacturer_label(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DISC_UNIQUE_BRANCH:
                        offset = dissect_rdm_pd_disc_unique_branch(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DISC_MUTE:
                        offset = dissect_rdm_pd_disc_mute(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DISC_UN_MUTE:
                        offset = dissect_rdm_pd_disc_un_mute(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PROXIED_DEVICES:
                        offset = dissect_rdm_pd_proxied_devices(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PROXIED_DEVICE_COUNT:
                        offset = dissect_rdm_pd_proxied_device_count(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_COMMS_STATUS:
                        offset = dissect_rdm_pd_comms_status(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_STATUS_MESSAGES:
                        offset = dissect_rdm_pd_status_messages(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_STATUS_ID_DESCRIPTION:
                        offset = dissect_rdm_pd_status_id_description(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_CLEAR_STATUS_ID:
                        offset = dissect_rdm_pd_clear_status_id(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SUB_DEVICE_STATUS_REPORT_THRESHOLD:
                        offset = dissect_rdm_pd_sub_device_status_report_threshold(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SUPPORTED_PARAMETERS:
                        offset = dissect_rdm_pd_supported_parameters(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PARAMETER_DESCRIPTION:
                        offset = dissect_rdm_pd_parameter_description(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PRODUCT_DETAIL_ID_LIST:
                        offset = dissect_rdm_pd_product_detail_id_list(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_FACTORY_DEFAULTS:
                        offset = dissect_rdm_pd_factory_defaults(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_LANGUAGE_CAPABILITIES:
                        offset = dissect_rdm_pd_language_capabilities(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_LANGUAGE:
                        offset = dissect_rdm_pd_language(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SOFTWARE_VERSION_LABEL:
                        offset = dissect_rdm_pd_software_version_label(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_BOOT_SOFTWARE_VERSION_ID:
                        offset = dissect_rdm_pd_boot_software_version_id(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_BOOT_SOFTWARE_VERSION_LABEL:
                        offset = dissect_rdm_pd_boot_software_version_label(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DMX_PERSONALITY:
                        offset = dissect_rdm_pd_dmx_personality(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DMX_PERSONALITY_DESCRIPTION:
                        offset = dissect_rdm_pd_dmx_personality_description(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SLOT_INFO:
                        offset = dissect_rdm_pd_slot_info(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SLOT_DESCRIPTION:
                        offset = dissect_rdm_pd_slot_description(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DEFAULT_SLOT_VALUE:
                        offset = dissect_rdm_pd_slot_value(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_RECORD_SENSORS:
                        offset = dissect_rdm_pd_record_sensors(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_LAMP_STATE:
                        offset = dissect_rdm_pd_lamp_state(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_LAMP_ON_MODE:
                        offset = dissect_rdm_pd_lamp_on_mode(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DEVICE_POWER_CYCLES:
                        offset = dissect_rdm_pd_device_power_cycles(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DISPLAY_INVERT:
                        offset = dissect_rdm_pd_display_invert(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_DISPLAY_LEVEL:
                        offset = dissect_rdm_pd_display_level(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PAN_INVERT:
                        offset = dissect_rdm_pd_pan_invert(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_TILT_INVERT:
                        offset = dissect_rdm_pd_tilt_invert(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PAN_TILT_SWAP:
                        offset = dissect_rdm_pd_pan_tilt_swap(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_REAL_TIME_CLOCK:
                        offset = dissect_rdm_pd_real_time_clock(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_IDENTIFY_DEVICE:
                        offset = dissect_rdm_pd_identify_device(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_RESET_DEVICE:
                        offset = dissect_rdm_pd_reset_device(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_POWER_STATE:
                        offset = dissect_rdm_pd_power_state(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PERFORM_SELFTEST:
                        offset = dissect_rdm_pd_perform_selftest(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_SELF_TEST_DESCRIPTION:
                        offset = dissect_rdm_pd_self_test_description(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_CAPTURE_PRESET:
                        offset = dissect_rdm_pd_capture_preset(tvb, offset, si, cc, parameter_data_length);
                        break;

                case RDM_PARAM_ID_PRESET_PLAYBACK:
                        offset = dissect_rdm_pd_preset_playback(tvb, offset, si, cc, parameter_data_length);
                        break;

                default:
                        proto_tree_add_item(si, hf_rdm_parameter_data_raw, tvb,
                                offset, parameter_data_length, ENC_NA);
                        offset += parameter_data_length;
                        break;
                }
        }

        return offset;
}

static int
dissect_rdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDM");
        col_clear(pinfo->cinfo, COL_INFO);

        if (tree) {
                gint        padding_size;
                guint16     man_id;
                guint32     dev_id;
                guint       message_length, offset = 0;

                proto_tree *ti = proto_tree_add_item(tree, proto_rdm, tvb,
                                offset, -1, ENC_NA);
                proto_tree *rdm_tree = proto_item_add_subtree(ti, ett_rdm);

                proto_tree_add_item(rdm_tree, hf_rdm_sub_start_code, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                message_length = tvb_get_guint8(tvb, offset);
                proto_tree_add_item(rdm_tree, hf_rdm_message_length, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                man_id = tvb_get_ntohs(tvb, offset);
                dev_id = tvb_get_ntohl(tvb, offset + 2);
                proto_item_append_text(ti, ", Dst UID: %04x:%08x", man_id, dev_id);
                proto_tree_add_item(rdm_tree, hf_rdm_dest_uid, tvb,
                                offset, 6, ENC_NA);
                offset += 6;


                man_id = tvb_get_ntohs(tvb, offset);
                dev_id = tvb_get_ntohl(tvb, offset + 2);
                proto_item_append_text(ti, ", Src UID: %04x:%08x", man_id, dev_id);
                proto_tree_add_item(rdm_tree, hf_rdm_src_uid, tvb,
                                offset, 6, ENC_NA);
                offset += 6;

                proto_tree_add_item(rdm_tree, hf_rdm_transaction_number, tvb,
                                offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                offset = dissect_rdm_mdb(tvb, offset, rdm_tree);

                padding_size = offset - (message_length - 1);
                if (padding_size > 0) {
                        proto_tree_add_item(rdm_tree, hf_rdm_intron, tvb,
                                        offset, padding_size, ENC_NA);
                        offset += padding_size;
                }

                proto_tree_add_checksum(rdm_tree, tvb, offset, hf_rdm_checksum, hf_rdm_checksum_status, NULL, pinfo, rdm_checksum(tvb, offset),
                                                        ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY);
                offset += 2;

                if (offset < tvb_reported_length(tvb))
                        proto_tree_add_item(rdm_tree, hf_rdm_trailer, tvb,
                                        offset, -1, ENC_NA);
        }
        return tvb_captured_length(tvb);
}

void
proto_register_rdm(void)
{
        static hf_register_info hf[] = {
                { &hf_rdm_sub_start_code,
                        { "Sub-start code", "rdm.ssc",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_message_length,
                        { "Message length", "rdm.len",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_dest_uid,
                        { "Destination UID", "rdm.dst",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_src_uid,
                        { "Source UID", "rdm.src",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_transaction_number,
                        { "Transaction number", "rdm.tn",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_port_id,
                        { "Port ID", "rdm.port_id",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_response_type,
                        { "Response type", "rdm.rt",
                                FT_UINT8, BASE_HEX, VALS(rdm_rt_vals), 0x0,
                                NULL, HFILL }},

                { &hf_rdm_message_count,
                        { "Message count", "rdm.mc",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_sub_device,
                        { "Sub-device", "rdm.sd",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_mdb,
                        { "Message Data Block", "rdm.mdb",
                                FT_NONE, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_command_class,
                        { "Command class", "rdm.cc",
                                FT_UINT8, BASE_HEX, VALS(rdm_cc_vals), 0x0,
                                NULL, HFILL }},

                { &hf_rdm_parameter_id,
                        { "Parameter ID", "rdm.pid",
                                FT_UINT16, BASE_HEX | BASE_EXT_STRING, &rdm_param_id_vals_ext, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_parameter_data_length,
                        { "Parameter data length", "rdm.pdl",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_parameter_data,
                        { "Parameter data", "rdm.pd",
                                FT_NONE, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_parameter_data_raw,
                        { "Raw Data", "rdm.pd.raw",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_intron,
                        { "Intron", "rdm.intron",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_checksum,
                        { "Checksum", "rdm.checksum",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_checksum_status,
                        { "Checksum Status", "rdm.checksum.status",
                                FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
                                NULL, HFILL }},

                { &hf_rdm_trailer,
                        { "Trailer", "rdm.trailer",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_queued_message_status,
                        { "Status", "rdm.pd.queued_message.status",
                                FT_UINT8, BASE_HEX, VALS(rdm_status_vals), 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_nr,
                        { "Sensor Nr.", "rdm.pd.sensor.nr",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_value_pres,
                        { "Sensor Present Value", "rdm.pd.sensor.value.present",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_value_low,
                        { "Sensor Lowest Value", "rdm.pd.sensor.value.lowest",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_value_high,
                        { "Sensor Highest Value", "rdm.pd.sensor.value.highest",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_value_rec,
                        { "Sensor Recorded Value", "rdm.pd.sensor.value.recorded",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_range_min_value,
                        { "Sensor Range Min. Value", "rdm.pd.sensor.range.min_value",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_range_max_value,
                        { "Sensor Range Max. Value", "rdm.pd.sensor.range.max_value",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_normal_min_value,
                        { "Sensor Normal Min. Value", "rdm.pd.sensor.normal.min_value",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_normal_max_value,
                        { "Sensor Normal Max. Value", "rdm.pd.sensor.normal.max_value",
                                FT_INT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_recorded_value_support,
                        { "Sensor Recorded Value Support", "rdm.pd.sensor.recorded_value_support",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_type,
                        { "Sensor Type", "rdm.pd.sensor_type",
                                FT_UINT8, BASE_HEX | BASE_EXT_STRING, &rdm_sensor_type_vals_ext, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_unit,
                        { "Sensor Unit", "rdm.pd.sensor_unit",
                                FT_UINT8, BASE_HEX | BASE_EXT_STRING, &rdm_unit_vals_ext, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_prefix,
                        { "Sensor Prefix", "rdm.pd.sensor_prefix",
                                FT_UINT8, BASE_HEX | BASE_EXT_STRING, &rdm_prefix_vals_ext, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_description,
                        { "Sensor Description", "rdm.pd.sensor.description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_manu_label,
                        { "Manufacturer Label", "rdm.pd.manu_label",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},


                { &hf_rdm_pd_device_label,
                        { "Device Label", "rdm.pd.device_label",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_start_address,
                        { "DMX Start Address", "rdm.pd.dmx_start_address",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_device_hours,
                        { "Device Hours", "rdm.pd.device_hours",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_lamp_hours,
                        { "Lamp Hours", "rdm.pd.lamp_hours",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_lamp_strikes,
                        { "Lamp Strikes", "rdm.pd.lamp_strikes",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_proto_vers,
                        { "RDM Protocol Version", "rdm.pd.proto_vers",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_device_model_id,
                        { "Device Model ID", "rdm.pd.device_model_id",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_product_cat,
                        { "Product Category", "rdm.pd.product_cat",
                                FT_UINT16, BASE_HEX | BASE_EXT_STRING, &rdm_product_cat_vals_ext, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_software_vers_id,
                        { "Software Version ID", "rdm.pd.software_version_id",
                                FT_UINT32, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_footprint,
                        { "DMX Footprint", "rdm.pd.dmx_footprint",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_current,
                        { "Current DMX Personality", "rdm.pd.dmx_pers_current",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_total,
                        { "Total nr. DMX Personalities", "rdm.pd.dmx_pers_total",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sub_device_count,
                        { "Sub-Device Count", "rdm.pd.sub_device_count",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sensor_count,
                        { "Sensor Count", "rdm.pd.sensor_count",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_device_model_description,
                        { "Device Model Description", "rdm.pd.device_model_description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_disc_unique_branch_lb_uid,
                        { "Lower Bound UID", "rdm.pd.disc_unique_branch.lb_uid",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_disc_unique_branch_ub_uid,
                        { "Upper Bound UID", "rdm.pd.disc_unique_branch.ub_uid",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_disc_mute_control_field,
                        { "Control Field", "rdm.pd.disc_mute.control_field",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_disc_mute_binding_uid,
                        { "Binding UID", "rdm.pd.disc_mute.binding_uid",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_disc_unmute_control_field,
                        { "Control Field", "rdm.pd.disc_unmute.control_field",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_disc_unmute_binding_uid,
                        { "Binding UID", "rdm.pd.disc_unmute.binding_uid",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_proxied_devices_uid,
                        { "UID", "rdm.pd.proxied_devices.uid",
                                FT_BYTES, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_proxied_device_count,
                        { "Device Count", "rdm.pd.device_count",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_proxied_device_list_change,
                        { "List Change", "rdm.pd.list_change",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_real_time_clock_year,
                        { "Year", "rdm.pd.real_time_clock.year",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_real_time_clock_month,
                        { "Month", "rdm.pd.real_time_clock.month",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_real_time_clock_day,
                        { "Day", "rdm.pd.real_time_clock.day",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_real_time_clock_hour,
                        { "Hour", "rdm.pd.real_time_clock.hour",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_real_time_clock_minute,
                        { "Minute", "rdm.pd.real_time_clock.minute",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_real_time_clock_second,
                        { "Second", "rdm.pd.real_time_clock.second",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_lamp_state,
                        { "Lamp State", "rdm.pd.lamp_state",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_lamp_on_mode,
                        { "Lamp On Mode", "rdm.pd.lamp_on_mode",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_device_power_cycles,
                        { "Device Power Cycles", "rdm.pd.device_power_cycles",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_display_invert,
                        { "Display Invert", "rdm.pd.display_invert",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_display_level,
                        { "Display Level", "rdm.pd.display_level",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_pan_invert,
                        { "Pan Invert", "rdm.pd.pan_invert",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_tilt_invert,
                        { "Tilt Invert", "rdm.pd.tilt_invert",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_tilt_swap,
                        { "Tilt Swap", "rdm.pd.tilt_swap",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_selftest_nr,
                        { "Selftest Nr.", "rdm.pd.selftest.nr",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_selftest_state,
                        { "Selftest State", "rdm.pd.selftest.state",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_selftest_description,
                        { "Selftest Description", "rdm.pd.selftest.description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_language_code,
                        { "Language Code", "rdm.pd.language_code",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_identify_device,
                        { "Identify Device", "rdm.pd.identify_device",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_identify_device_state,
                        { "Identify Device State", "rdm.pd.identify_device.state",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_reset_device,
                        { "Reset Device", "rdm.pd.reset_device",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_power_state,
                        { "Power State", "rdm.pd.power_state",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_capture_preset_scene_nr,
                        { "Scene Nr.", "rdm.pd.capture_preset.scene_nr",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_capture_preset_up_fade_time,
                        { "Up Fade Time", "rdm.pd.capture_preset.up_fade_time",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_capture_preset_down_fade_time,
                        { "Down Fade Time", "rdm.pd.capture_preset.down_fade_time",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_capture_preset_wait_time,
                        { "Wait Time", "rdm.pd.capture_preset.wait_time",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_preset_playback_mode,
                        { "Mode", "rdm.pd.preset_playback.mode",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_preset_playback_level,
                        { "Level", "rdm.pd.preset_playback.level",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_id,
                        { "ID", "rdm.pd.parameter.id",
                                FT_UINT16, BASE_HEX, VALS(rdm_param_id_vals), 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_pdl_size,
                        { "PDL Size", "rdm.pd.parameter.pdl_size",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_data_type,
                        { "Data Type", "rdm.pd.parameter.data_type",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_cmd_class,
                        { "Command Class", "rdm.pd.parameter.cmd_class",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_type,
                        { "Type", "rdm.pd.parameter.type",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_unit,
                        { "Unit", "rdm.pd.parameter.unit",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_prefix,
                        { "Prefix", "rdm.pd.parameter.prefix",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_min_value,
                        { "Min. Value", "rdm.pd.parameter.min_value",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_max_value,
                        { "Max. Value", "rdm.pd.parameter.max_value",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_default_value,
                        { "Default Value", "rdm.pd.parameter.default_value",
                                FT_UINT32, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_parameter_description,
                        { "Description", "rdm.pd.parameter.description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_software_version_label,
                        { "Version Label", "rdm.pd.software_version.label",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_boot_software_version_id,
                        { "Version ID", "rdm.pd.boot_software_version.id",
                                FT_UINT32, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_boot_software_version_label,
                        { "Version Label", "rdm.pd.boot_software_version.label",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_comms_status_short_msg,
                        { "Short Msg", "rdm.pd.comms_status.short_msg",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_comms_status_len_mismatch,
                        { "Len Mismatch", "rdm.pd.comms_status.len_mismatch",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_comms_status_csum_fail,
                        { "Checksum Fail", "rdm.pd.comms_status.csum_fail",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_messages_type,
                        { "Type", "rdm.pd.status_messages.type",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_messages_sub_device_id,
                        { "Sub. Device ID", "rdm.pd.status_messages.sub_devices_id",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_messages_id,
                        { "ID", "rdm.pd.status_messages.id",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_messages_data_value_1,
                        { "Data Value 1", "rdm.pd.status_messages.data_value_1",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_messages_data_value_2,
                        { "Data Value 2", "rdm.pd.status_messages.data_value_2",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_id,
                        { "ID", "rdm.pd.status_id",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_status_id_description,
                        { "Description", "rdm.pd.status_id.description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_sub_device_status_report_threshold_status_type,
                        { "Status Type", "rdm.pd.sub_device_status_report_threshold.status_type",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_product_detail_id_list,
                        { "Sensor Count", "rdm.pd.product_detail_id_list",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_factory_defaults,
                        { "Factory Defaults", "rdm.pd.factory_defaults",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_nr,
                        { "DMX Pers. Nr.", "rdm.pd.dmx_pers.nr",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_count,
                        { "DMX Pers. Count", "rdm.pd.dmx_pers.count",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_description,
                        { "DMX Pers. Description", "rdm.pd.dmx_pers.description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_slots,
                        { "DMX Pers. Slots", "rdm.pd.dmx_pers.slots",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_dmx_pers_text,
                        { "DMX Pers. Text", "rdm.pd.dmx_pers.text",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_slot_offset,
                        { "Slot Offset", "rdm.pd.slot_offset",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_slot_type,
                        { "Slot Type", "rdm.pd.slot_type",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_slot_label_id,
                        { "Slot Label ID", "rdm.pd.slot_label_id",
                                FT_UINT16, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_slot_nr,
                        { "Slot Nr.", "rdm.pd.slot_nr",
                                FT_UINT16, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_slot_description,
                        { "Slot Description", "rdm.pd.slot_description",
                                FT_STRING, BASE_NONE, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_slot_value,
                        { "Slot Value", "rdm.pd.slot_value",
                                FT_UINT8, BASE_DEC, NULL, 0x0,
                                NULL, HFILL }},

                { &hf_rdm_pd_rec_value_support,
                        { "Rec. Value Support", "rdm.pd.rec_value_support",
                                FT_UINT8, BASE_HEX, NULL, 0x0,
                                NULL, HFILL }}
        };

        static gint *ett[] = {
                &ett_rdm
        };

        proto_rdm = proto_register_protocol("Remote Device Management",
                        "RDM", "rdm");
        proto_register_field_array(proto_rdm, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
        register_dissector("rdm", dissect_rdm, proto_rdm);
}

void
proto_reg_handoff_rdm(void) {
        dissector_add_uint("dmx", 0xCC, create_dissector_handle(dissect_rdm, proto_rdm));
}

/*
 * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 8
 * tab-width: 8
 * indent-tabs-mode: t
 * End:
 *
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
 * :indentSize=8:tabSize=8:noTabs=false:
 */