/* packet-csm-encaps.c
 * Routines for CSM_ENCAPS dissection
 * Copyright 2005, Angelo Bannack <angelo.bannack@siemens.com>
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 2003 Gerald Combs
 *
 * Copied from packet-ans.c
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "config.h"

#include <epan/packet.h>
#include <epan/etypes.h>
#include <epan/tfs.h>

#define OPCODE_NOOP              0x0000
#define OPCODE_CONTROL_PACKET    0x0001
#define OPCODE_RELIABLE_DATA     0x0002

#define CSM_ENCAPS_CTRL_ACK              0x80
#define CSM_ENCAPS_CTRL_ACK_SUPPRESS     0x40
#define CSM_ENCAPS_CTRL_ACK_TO_HOST      0x20
#define CSM_ENCAPS_CTRL_ENDIAN           0x01

#define CSM_ENCAPS_TYPE_CHANGE               0x00
#define CSM_ENCAPS_TYPE_QUERY                0x01
#define CSM_ENCAPS_TYPE_RESPONSE             0x02
#define CSM_ENCAPS_TYPE_INDICATION           0x03
#define CSM_ENCAPS_TYPE_QUERY_RESPONSE       0x04
#define CSM_ENCAPS_TYPE_INDICATION_RESPONSE  0x05

void proto_register_csm_encaps(void);
void proto_reg_handoff_csm_encaps(void);

static dissector_handle_t csm_encaps_handle;

static const value_string opcode_vals[] = {
    { OPCODE_NOOP,           "No Operation" },
    { OPCODE_CONTROL_PACKET, "Control Packet" },
    { OPCODE_RELIABLE_DATA,  "Reliable Data Transfer" },
    { 0,       NULL }
};

static const value_string function_code_vals[] = {
    {0x0000, " "},
    { 0,       NULL }
};

static const value_string class_type_vals[] = {
    { 0,      NULL }
};

static const value_string exclusive_to_host_vals[] = {
    { 0,      NULL }
};

static const value_string exclusive_to_host_ct_vals[] = {
    { 0,      NULL }
};

static const value_string error_vals[] = {
    { 0,      NULL }
};

/* Initialize the protocol and registered fields */
static int proto_csm_encaps;

static int hf_csm_encaps_opcode;
static int hf_csm_encaps_seq;
static int hf_csm_encaps_ctrl;
static int hf_csm_encaps_ctrl_endian;
static int hf_csm_encaps_ctrl_ack;
static int hf_csm_encaps_ctrl_ack_suppress;
static int hf_csm_encaps_channel;
static int hf_csm_encaps_index;
static int hf_csm_encaps_length;
static int hf_csm_encaps_class;
static int hf_csm_encaps_type;
static int hf_csm_encaps_function_code;
static int hf_csm_encaps_reserved;
static int hf_csm_encaps_param_error;
static int hf_csm_encaps_param1;
static int hf_csm_encaps_param2;
static int hf_csm_encaps_param3;
static int hf_csm_encaps_param4;
static int hf_csm_encaps_param5;
static int hf_csm_encaps_param6;
static int hf_csm_encaps_param7;
static int hf_csm_encaps_param8;
static int hf_csm_encaps_param9;
static int hf_csm_encaps_param10;
static int hf_csm_encaps_param11;
static int hf_csm_encaps_param12;
static int hf_csm_encaps_param13;
static int hf_csm_encaps_param14;
static int hf_csm_encaps_param15;
static int hf_csm_encaps_param16;
static int hf_csm_encaps_param17;
static int hf_csm_encaps_param18;
static int hf_csm_encaps_param19;
static int hf_csm_encaps_param20;
static int hf_csm_encaps_param21;
static int hf_csm_encaps_param22;
static int hf_csm_encaps_param23;
static int hf_csm_encaps_param24;
static int hf_csm_encaps_param25;
static int hf_csm_encaps_param26;
static int hf_csm_encaps_param27;
static int hf_csm_encaps_param28;
static int hf_csm_encaps_param29;
static int hf_csm_encaps_param30;
static int hf_csm_encaps_param31;
static int hf_csm_encaps_param32;
static int hf_csm_encaps_param33;
static int hf_csm_encaps_param34;
static int hf_csm_encaps_param35;
static int hf_csm_encaps_param36;
static int hf_csm_encaps_param37;
static int hf_csm_encaps_param38;
static int hf_csm_encaps_param39;
static int hf_csm_encaps_param40;
static int hf_csm_encaps_param;


/* Initialize the subtree pointers */
static int ett_csm_encaps;
static int ett_csm_encaps_control;


/* returns the command name */
static const char *
csm_fc(wmem_allocator_t* scope, uint16_t fc, uint16_t ct)
{
    if (fc == 0x0000) {
        return val_to_str(scope, ct, class_type_vals, "0x%04x");
    } else {
        return val_to_str(scope, fc, function_code_vals, "0x%04x");
    }
}



/* check to see if the message is an exclusive message send to host */
static bool
csm_to_host(uint16_t fc, uint16_t ct)
{
    if (fc == 0x0000) {
        return (try_val_to_str(ct, exclusive_to_host_ct_vals) != NULL);
    } else {
        return (try_val_to_str(fc, exclusive_to_host_vals) != NULL);
    }
}



/* Code to actually dissect the packets */
static int
dissect_csm_encaps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
    proto_item  *ti;
    proto_tree  *csm_encaps_tree = NULL;
    uint16_t     function_code, channel, class_type;
    unsigned     control, type, sequence, length;
    unsigned     i;
    bool         show_error_param= false;
    const char *str_function_name;


    function_code = tvb_get_letohs(tvb, 10);
    control = tvb_get_uint8(tvb, 3);

    class_type = tvb_get_uint8(tvb, 9);
    class_type = class_type<<8;
    class_type|= tvb_get_uint8(tvb, 8);

    type     = tvb_get_uint8(tvb, 8);
    sequence = tvb_get_uint8(tvb, 2);
    length   = tvb_get_uint8(tvb, 6);
    channel  = tvb_get_ntohs(tvb, 4);


    if (CSM_ENCAPS_CTRL_ACK&control)
        show_error_param= false;
    else {
        if (csm_to_host(function_code, class_type)) /* exclusive messages to host */
            show_error_param= false;
        else {
            if (type == CSM_ENCAPS_TYPE_RESPONSE)
                show_error_param= true;
            else
                show_error_param= false;
        }
    }

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "CSM_ENCAPS");

    col_clear(pinfo->cinfo, COL_INFO);

    if (CSM_ENCAPS_CTRL_ACK&control) {
        if (CSM_ENCAPS_CTRL_ACK_TO_HOST&control)
            col_append_fstr(pinfo->cinfo, COL_INFO,
                            "<-- ACK                                 Ch: 0x%04X, Seq: %2d (To Host)",
                            channel, sequence);
        else
            col_append_fstr(pinfo->cinfo, COL_INFO,
                            "--> ACK                                 Ch: 0x%04X, Seq: %2d (From Host)",
                            channel, sequence);
    } else {
        str_function_name= csm_fc(pinfo->pool, function_code, class_type);
        if ((type == CSM_ENCAPS_TYPE_RESPONSE) || (csm_to_host(function_code, class_type)))
            col_append_fstr(pinfo->cinfo, COL_INFO,
                            "<-- %-35s Ch: 0x%04X, Seq: %2d (To Host)",
                            str_function_name, channel, sequence);
        else
            col_append_fstr(pinfo->cinfo, COL_INFO,
                            "--> %-35s Ch: 0x%04X, Seq: %2d (From Host)",
                            str_function_name, channel, sequence);
    }


    if (tree) {
        static int * const control_flags[] = {
            &hf_csm_encaps_ctrl_ack,
            &hf_csm_encaps_ctrl_ack_suppress,
            &hf_csm_encaps_ctrl_endian,
            NULL
        };

        ti = proto_tree_add_item(tree, proto_csm_encaps, tvb, 0, -1, ENC_NA);
        csm_encaps_tree = proto_item_add_subtree(ti, ett_csm_encaps);

        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_opcode, tvb, 0, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_seq, tvb, 2, 1, ENC_BIG_ENDIAN);

        proto_tree_add_bitmask(tree, tvb, 3, hf_csm_encaps_ctrl, ett_csm_encaps_control, control_flags, ENC_NA);

        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_channel, tvb, 4, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_length, tvb, 6, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_index, tvb, 7, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_class, tvb, 9, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_type, tvb, 8, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_function_code, tvb, 10, 2, ENC_LITTLE_ENDIAN);

        i = 6;

        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_reserved, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            if (show_error_param)
                proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param_error, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            else
                proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param1, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param2, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param3, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param4, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param5, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param6, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param7, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param8, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param9, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param10, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param11, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param12, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param13, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param14, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param15, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param16, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param17, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param18, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param19, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param20, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param21, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param22, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param23, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param24, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param25, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param26, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param27, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param28, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param29, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param30, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param31, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param32, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param33, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param34, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param35, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param36, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param37, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param38, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param39, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }
        if (i < length) {
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param40, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
            i += 2;
        }

        for (; i < length; i += 2)
            proto_tree_add_item(csm_encaps_tree, hf_csm_encaps_param, tvb, 12 + i - 6, 2, ENC_LITTLE_ENDIAN);
    }
    return tvb_captured_length(tvb);
}


void
proto_register_csm_encaps(void)
{
    static struct true_false_string control_endian_bit       = {"Little Endian","Big Endian"};
    static struct true_false_string control_ack_bit          = {"ACK Packet", "Message Packet"};
    static struct true_false_string control_ack_suppress_bit = {"ACK Suppressed", "ACK Required"};

    static hf_register_info hf[] = {
        { &hf_csm_encaps_opcode,
            { "Opcode", "csm_encaps.opcode",
                FT_UINT16, BASE_HEX, VALS(opcode_vals), 0,
                "CSM_ENCAPS Opcode", HFILL }
        },
        { &hf_csm_encaps_seq,
            { "Sequence Number", "csm_encaps.seq_num",
                FT_UINT8, BASE_DEC, NULL, 0,
                "CSM_ENCAPS Sequence Number", HFILL }
        },
        { &hf_csm_encaps_ctrl,
            { "Control", "csm_encaps.ctrl",
                FT_UINT8, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Control", HFILL }
        },
        { &hf_csm_encaps_ctrl_ack,
           { "Packet Bit",  "csm_encaps.ctrl.ack",
                FT_BOOLEAN, 8, TFS(&control_ack_bit), CSM_ENCAPS_CTRL_ACK,
                "Message Packet/ACK Packet", HFILL }
        },
        { &hf_csm_encaps_ctrl_ack_suppress,
           { "ACK Suppress Bit",    "csm_encaps.ctrl.ack_suppress",
                FT_BOOLEAN, 8, TFS(&control_ack_suppress_bit), CSM_ENCAPS_CTRL_ACK_SUPPRESS,
                "ACK Required/ACK Suppressed", HFILL }
        },
        { &hf_csm_encaps_ctrl_endian,
           { "Endian Bit",  "csm_encaps.ctrl.endian",
                FT_BOOLEAN, 8, TFS(&control_endian_bit), CSM_ENCAPS_CTRL_ENDIAN,
                "Little Endian/Big Endian", HFILL }
        },
        { &hf_csm_encaps_channel,
            { "Channel Number", "csm_encaps.channel",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Channel Number", HFILL }
        },
        { &hf_csm_encaps_index,
            { "Index", "csm_encaps.index",
                FT_UINT8, BASE_DEC, NULL, 0,
                "CSM_ENCAPS Index", HFILL }
        },
        { &hf_csm_encaps_length,
            { "Length", "csm_encaps.length",
                FT_UINT8, BASE_DEC, NULL, 0,
                "CSM_ENCAPS Length", HFILL }
        },
        { &hf_csm_encaps_class,
            { "Class", "csm_encaps.class",
                FT_UINT8, BASE_DEC, NULL, 0,
                "CSM_ENCAPS Class", HFILL }
        },
        { &hf_csm_encaps_type,
            { "Type", "csm_encaps.type",
                FT_UINT8, BASE_DEC, NULL, 0,
                "CSM_ENCAPS Type", HFILL }
        },
        { &hf_csm_encaps_function_code,
            { "Function Code", "csm_encaps.function_code",
                FT_UINT16, BASE_HEX, VALS(function_code_vals), 0,
                "CSM_ENCAPS Function Code", HFILL }
        },
        { &hf_csm_encaps_reserved,
            { "Reserved", "csm_encaps.reserved",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Reserved", HFILL }
        },
        { &hf_csm_encaps_param_error,
            { "Parameter 1", "csm_encaps.param1",
                FT_UINT16, BASE_HEX, VALS(error_vals), 0,
                "CSM_ENCAPS Parameter 1", HFILL }
        },
        { &hf_csm_encaps_param1,
            { "Parameter 1", "csm_encaps.param1",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 1", HFILL }
        },
        { &hf_csm_encaps_param2,
            { "Parameter 2", "csm_encaps.param2",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 2", HFILL }
        },
        { &hf_csm_encaps_param3,
            { "Parameter 3", "csm_encaps.param3",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 3", HFILL }
        },
        { &hf_csm_encaps_param4,
            { "Parameter 4", "csm_encaps.param4",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 4", HFILL }
        },
        { &hf_csm_encaps_param5,
            { "Parameter 5", "csm_encaps.param5",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 5", HFILL }
        },
        { &hf_csm_encaps_param6,
            { "Parameter 6", "csm_encaps.param6",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 6", HFILL }
        },
        { &hf_csm_encaps_param7,
            { "Parameter 7", "csm_encaps.param7",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 7", HFILL }
        },
        { &hf_csm_encaps_param8,
            { "Parameter 8", "csm_encaps.param8",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 8", HFILL }
        },
        { &hf_csm_encaps_param9,
            { "Parameter 9", "csm_encaps.param9",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 9", HFILL }
        },
        { &hf_csm_encaps_param10,
            { "Parameter 10", "csm_encaps.param10",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 10", HFILL }
        },
        { &hf_csm_encaps_param11,
            { "Parameter 11", "csm_encaps.param11",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 11", HFILL }
        },
        { &hf_csm_encaps_param12,
            { "Parameter 12", "csm_encaps.param12",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 12", HFILL }
        },
        { &hf_csm_encaps_param13,
            { "Parameter 13", "csm_encaps.param13",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 13", HFILL }
        },
        { &hf_csm_encaps_param14,
            { "Parameter 14", "csm_encaps.param14",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 14", HFILL }
        },
        { &hf_csm_encaps_param15,
            { "Parameter 15", "csm_encaps.param15",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 15", HFILL }
        },
        { &hf_csm_encaps_param16,
            { "Parameter 16", "csm_encaps.param16",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 16", HFILL }
        },
        { &hf_csm_encaps_param17,
            { "Parameter 17", "csm_encaps.param17",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 17", HFILL }
        },
        { &hf_csm_encaps_param18,
            { "Parameter 18", "csm_encaps.param18",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 18", HFILL }
        },
        { &hf_csm_encaps_param19,
            { "Parameter 19", "csm_encaps.param19",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 19", HFILL }
        },
        { &hf_csm_encaps_param20,
            { "Parameter 20", "csm_encaps.param20",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 20", HFILL }
        },
        { &hf_csm_encaps_param21,
            { "Parameter 21", "csm_encaps.param21",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 21", HFILL }
        },
        { &hf_csm_encaps_param22,
            { "Parameter 22", "csm_encaps.param22",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 22", HFILL }
        },
        { &hf_csm_encaps_param23,
            { "Parameter 23", "csm_encaps.param23",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 23", HFILL }
        },
        { &hf_csm_encaps_param24,
            { "Parameter 24", "csm_encaps.param24",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 24", HFILL }
        },
        { &hf_csm_encaps_param25,
            { "Parameter 25", "csm_encaps.param25",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 25", HFILL }
        },
        { &hf_csm_encaps_param26,
            { "Parameter 26", "csm_encaps.param26",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 26", HFILL }
        },
        { &hf_csm_encaps_param27,
            { "Parameter 27", "csm_encaps.param27",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 27", HFILL }
        },
        { &hf_csm_encaps_param28,
            { "Parameter 28", "csm_encaps.param28",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 28", HFILL }
        },
        { &hf_csm_encaps_param29,
            { "Parameter 29", "csm_encaps.param29",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 29", HFILL }
        },
        { &hf_csm_encaps_param30,
            { "Parameter 30", "csm_encaps.param30",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 30", HFILL }
        },
        { &hf_csm_encaps_param31,
            { "Parameter 31", "csm_encaps.param31",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 31", HFILL }
        },
        { &hf_csm_encaps_param32,
            { "Parameter 32", "csm_encaps.param32",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 32", HFILL }
        },
        { &hf_csm_encaps_param33,
            { "Parameter 33", "csm_encaps.param33",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 33", HFILL }
        },
        { &hf_csm_encaps_param34,
            { "Parameter 34", "csm_encaps.param34",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 34", HFILL }
        },
        { &hf_csm_encaps_param35,
            { "Parameter 35", "csm_encaps.param35",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 35", HFILL }
        },
        { &hf_csm_encaps_param36,
            { "Parameter 36", "csm_encaps.param36",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 36", HFILL }
        },
        { &hf_csm_encaps_param37,
            { "Parameter 37", "csm_encaps.param37",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 37", HFILL }
        },
        { &hf_csm_encaps_param38,
            { "Parameter 38", "csm_encaps.param38",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 38", HFILL }
        },
        { &hf_csm_encaps_param39,
            { "Parameter 39", "csm_encaps.param39",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 39", HFILL }
        },
        { &hf_csm_encaps_param40,
            { "Parameter 40", "csm_encaps.param40",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter 40", HFILL }
        },
        { &hf_csm_encaps_param,
            { "Parameter", "csm_encaps.param",
                FT_UINT16, BASE_HEX, NULL, 0,
                "CSM_ENCAPS Parameter", HFILL }
        },
    };

    static int *ett[] = {
        &ett_csm_encaps,
        &ett_csm_encaps_control
    };

    proto_csm_encaps = proto_register_protocol("CSM_ENCAPS", "CSM_ENCAPS", "csm_encaps");
    proto_register_field_array(proto_csm_encaps, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));

    csm_encaps_handle = register_dissector("csm_encaps", dissect_csm_encaps, proto_csm_encaps);
}


void
proto_reg_handoff_csm_encaps(void)
{
    dissector_add_uint("ethertype", ETHERTYPE_CSM_ENCAPS, csm_encaps_handle);
}

/*
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
 *
 * Local variables:
 * c-basic-offset: 4
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 *
 * vi: set shiftwidth=4 tabstop=8 expandtab:
 * :indentSize=4:tabSize=8:noTabs=true:
 */
