/*
* Dissector for Ettus Octoclock packets
*
* Copyright 2016 Ettus Research
*
* 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 3 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, see .
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include "../../host/lib/usrp_clock/octoclock/common.h"
#define LOG_HEADER "[Octoclock] "
#define size_mem(t,m) sizeof(((t*)0)->m)
#define packet_elem_size(m) (size_mem(octoclock_packet_t,m))
#define packet_offset(m) (offsetof(octoclock_packet_t, m))
const unsigned int OCTOCLOCK_PORT = OCTOCLOCK_UDP_CTRL_PORT;
static int proto_octo = -1;
static int hf_octo_proto_version = -1;
static int hf_octo_proto_sequence = -1;
static int hf_octo_proto_code = -1;
static int hf_octo_proto_poolsize = -1;
static int hf_octo_proto_data = -1;
static int hf_octo_proto_payload = -1;
static int hf_octo_proto_len = -1;
static gint ett_octo = -1;
static const value_string packetcodes[] = {
{1, "OCTOCLOCK_QUERY_CMD"},
{2, "OCTOCLOCK_QUERY_ACK"},
{3, "SEND_EEPROM_CMD"},
{4, "SEND_EEPROM_ACK"},
{5, "BURN_EEPROM_CMD"},
{6, "BURN_EEPROM_SUCCESS_ACK"},
{7, "BURN_EEPROM_FAILURE_ACK"},
{8, "CLEAR_EEPROM_CMD"},
{9, "CLEAR_EEPROM_ACK"},
{10, "SEND_STATE_CMD"},
{11, "SEND_STATE_ACK"},
{12, "RESET_CMD"},
{13, "RESET_ACK"},
{14, "HOST_SEND_TO_GPSDO_CMD"},
{15, "HOST_SEND_TO_GPSDO_ACK"},
{16, "SEND_POOLSIZE_CMD"},
{17, "SEND_POOLSIZE_ACK"},
{18, "SEND_CACHE_STATE_CMD"},
{19, "SEND_CACHE_STATE_ACK"},
{20, "SEND_GPSDO_CACHE_CMD"},
{21, "SEND_GPSDO_CACHE_ACK"},
{22, "PREPARE_FW_BURN_CMD"},
{23, "FW_BURN_READY_ACK"},
{24, "FILE_TRANSFER_CMD"},
{25, "FILE_TRANSFER_ACK"},
{26, "READ_FW_CMD"},
{27, "READ_FW_ACK"},
{28, "FINALIZE_BURNING_CMD"},
{29, "FINALIZE_BURNING_ACK"},
{ 0, NULL }
};
/* Forward-declare the dissector functions */
void proto_register_octo(void);
void proto_reg_handoff_octo(void);
static void dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static void dissect_octo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "OCTO");
col_clear(pinfo->cinfo, COL_INFO);
proto_item *ti = proto_tree_add_item(tree, proto_octo, tvb, 0, -1, ENC_NA);
proto_tree *octo_tree = proto_item_add_subtree(ti, ett_octo);
proto_tree_add_item(octo_tree,
hf_octo_proto_version,
tvb,
packet_offset(proto_ver),
packet_elem_size(proto_ver),
ENC_LITTLE_ENDIAN);
guint32 rev = tvb_get_letohl(tvb, packet_offset(proto_ver));
if(rev==3)
{
proto_tree_add_item(octo_tree,
hf_octo_proto_sequence,
tvb,
packet_offset(sequence),
packet_elem_size(sequence),
ENC_LITTLE_ENDIAN);
proto_tree_add_item(octo_tree,
hf_octo_proto_code,
tvb,
packet_offset(code),
packet_elem_size(code),
ENC_LITTLE_ENDIAN);
proto_tree_add_item(octo_tree,
hf_octo_proto_poolsize,
tvb,
packet_offset(poolsize),
packet_elem_size(poolsize),
ENC_LITTLE_ENDIAN);
//packet_code_t code = (packet_code_t)(tvb_get_guint8(tvb, packet_offset(code)));
guint16 len = tvb_get_letohs(tvb, packet_offset(len));
if(len && len <= packet_elem_size(data))
{
proto_tree_add_item(octo_tree,
hf_octo_proto_payload,
tvb,
packet_offset(data),
len,
ENC_LITTLE_ENDIAN);
}
proto_tree_add_item(octo_tree,
hf_octo_proto_data,
tvb,
packet_offset(data),
packet_elem_size(data),
ENC_LITTLE_ENDIAN);
proto_tree_add_item(octo_tree,
hf_octo_proto_len,
tvb,
packet_offset(len),
packet_elem_size(len),
ENC_LITTLE_ENDIAN);
}
}
void proto_register_octo(void)
{
static hf_register_info hf[] = {
{ &hf_octo_proto_version,
{ "version", "octo.rev",
FT_UINT32, BASE_DEC,
NULL, 0x0,
"Protocol Revision", HFILL }
},
{ &hf_octo_proto_sequence,
{ "sequence number", "octo.seq",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_octo_proto_code,
{ "code", "octo.code",
FT_UINT8, BASE_DEC,
VALS(packetcodes), 0x0,
NULL, HFILL }
},
{ &hf_octo_proto_poolsize,
{ "poolsize", "octo.poolsize",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_octo_proto_payload,
{ "payload", "octo.payload",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_octo_proto_data,
{ "data", "octo.data",
FT_BYTES, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_octo_proto_len,
{ "length", "octo.len",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
}
};
//protocol subtree array
static gint *ett[] = {
&ett_octo
};
proto_octo = proto_register_protocol(
"Octoclock",
"Octoclock",
"octo"
);
proto_register_field_array(proto_octo, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("octo", dissect_octo, proto_octo);
}
void proto_reg_handoff_octo(void)
{
static dissector_handle_t octo_handle;
octo_handle = create_dissector_handle(dissect_octo, proto_octo);
dissector_add_uint("udp.port", OCTOCLOCK_PORT, octo_handle);
dissector_add_uint("udp.port", OCTOCLOCK_UDP_GPSDO_PORT, octo_handle);
}