aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-s7comm.c1882
1 files changed, 1675 insertions, 207 deletions
diff --git a/epan/dissectors/packet-s7comm.c b/epan/dissectors/packet-s7comm.c
index 18a329824b..1b13455a19 100644
--- a/epan/dissectors/packet-s7comm.c
+++ b/epan/dissectors/packet-s7comm.c
@@ -35,6 +35,7 @@ static int proto_s7comm = -1;
/* Forward declarations */
void proto_reg_handoff_s7comm(void);
void proto_register_s7comm (void);
+static guint32 s7comm_decode_ud_tis_data(tvbuff_t *tvb, proto_tree *tree, guint8 type, guint8 subfunc, guint16 td_size, guint32 offset);
/**************************************************************************
* PDU types
@@ -687,18 +688,6 @@ static const value_string userdata_functiongroup_names[] = {
/**************************************************************************
* Variable status: Area of data request
- */
-#define S7COMM_UD_SUBF_PROG_VARTAB_TYPE_REQ 0x14
-#define S7COMM_UD_SUBF_PROG_VARTAB_TYPE_RES 0x04
-
-static const value_string userdata_prog_vartab_type_names[] = {
- { S7COMM_UD_SUBF_PROG_VARTAB_TYPE_REQ, "Request" }, /* Request of data areas */
- { S7COMM_UD_SUBF_PROG_VARTAB_TYPE_RES, "Response" }, /* Response from plc with data */
- { 0, NULL }
-};
-
-/**************************************************************************
- * Vartab: area of data request
*
* Low Hi
* 0=M 0=BOOL
@@ -807,6 +796,27 @@ static const value_string userdata_prog_subfunc_names[] = {
};
/**************************************************************************
+ * Variable status: Trigger point
+ */
+static const value_string userdata_varstat_trgevent_names[] = {
+ { 0x0000, "Immediately" },
+ { 0x0100, "System Trigger" },
+ { 0x0200, "System checkpoint main cycle start" },
+ { 0x0300, "System checkpoint main cycle end" },
+ { 0x0400, "Mode transition RUN-STOP" },
+ { 0x0500, "After code address" },
+ { 0x0600, "Code address area" },
+ { 0x0601, "Code address area with call environment" }, /* Call conditions like opened DB/DI or called block */
+ { 0x0700, "Data address" },
+ { 0x0800, "Data address area" },
+ { 0x0900, "Local data address" },
+ { 0x0a00, "Local data address area" },
+ { 0x0b00, "Range trigger" },
+ { 0x0c00, "Before code address" },
+ { 0, NULL }
+};
+
+/**************************************************************************
* Names of userdata subfunctions in group 2 (cyclic data)
*/
#define S7COMM_UD_SUBF_CYCLIC_TRANSF 0x01
@@ -1240,17 +1250,159 @@ static const int *s7comm_userdata_blockinfo_flags_fields[] = {
NULL
};
-/* Programmer commands, diagnostic data */
-static gint hf_s7comm_diagdata_req_askheadersize = -1; /* Ask header size, 2 bytes as int */
-static gint hf_s7comm_diagdata_req_asksize = -1; /* Ask size, 2 bytes as int */
-static gint hf_s7comm_diagdata_req_unknown = -1; /* for all unknown bytes */
-static gint hf_s7comm_diagdata_req_answersize = -1; /* Answer size, 2 bytes as int */
-static gint hf_s7comm_diagdata_req_block_type = -1; /* Block type, 1 byte, stringlist subblktype_names */
-static gint hf_s7comm_diagdata_req_block_num = -1; /* Block number, 2 bytes as int */
-static gint hf_s7comm_diagdata_req_startaddr_awl = -1; /* Start address AWL, 2 bytes as int */
-static gint hf_s7comm_diagdata_req_saz = -1; /* Step address counter (SAZ), 2 bytes as int */
-static gint hf_s7comm_diagdata_req_number_of_lines = -1; /* Number of lines, 1 byte as int */
-static gint hf_s7comm_diagdata_req_line_address = -1; /* Address, 2 bytes as int */
+/* Programmer commands / Test and installation (TIS) functions */
+static gint hf_s7comm_tis_parameter = -1;
+static gint hf_s7comm_tis_data = -1;
+static gint hf_s7comm_tis_parametersize = -1;
+static gint hf_s7comm_tis_datasize = -1;
+static gint hf_s7comm_tis_param1 = -1;
+static gint hf_s7comm_tis_param2 = -1;
+static const value_string tis_param2_names[] = { /* Values and their meaning are not always clearly defined in every function */
+ { 0, "Update Monitor Variables / Activate Modify Values"},
+ { 1, "Monitor Variable / Modify Variable" },
+ { 2, "Modify Variable permanent" },
+ { 256, "Force immediately" },
+ { 0, NULL }
+};
+static gint hf_s7comm_tis_param3 = -1;
+static const value_string tis_param3_names[] = {
+ { 0, "Every cycle (permanent)" },
+ { 1, "Once" },
+ { 2, "Always (force)" },
+ { 0, NULL }
+};
+static gint hf_s7comm_tis_answersize = -1;
+static gint hf_s7comm_tis_param5 = -1;
+static gint hf_s7comm_tis_param6 = -1;
+static gint hf_s7comm_tis_param7 = -1;
+static gint hf_s7comm_tis_param8 = -1;
+static gint hf_s7comm_tis_param9 = -1;
+static gint hf_s7comm_tis_trgevent = -1;
+static gint hf_s7comm_tis_res_param1 = -1;
+static gint hf_s7comm_tis_res_param2 = -1;
+static gint hf_s7comm_tis_job_function = -1;
+static gint hf_s7comm_tis_job_seqnr = -1;
+static gint hf_s7comm_tis_job_reserved = -1;
+
+
+
+/* B/I/L Stack */
+static gint hf_s7comm_tis_interrupted_blocktype = -1;
+static gint hf_s7comm_tis_interrupted_blocknr = -1;
+static gint hf_s7comm_tis_interrupted_address = -1;
+static gint hf_s7comm_tis_interrupted_prioclass = -1;
+static gint hf_s7comm_tis_continued_blocktype = -1;
+static gint hf_s7comm_tis_continued_blocknr = -1;
+static gint hf_s7comm_tis_continued_address = -1;
+static gint hf_s7comm_tis_breakpoint_blocktype = -1;
+static gint hf_s7comm_tis_breakpoint_blocknr = -1;
+static gint hf_s7comm_tis_breakpoint_address = -1;
+static gint hf_s7comm_tis_breakpoint_reserved = -1;
+
+static gint hf_s7comm_tis_p_callenv = -1;
+static const value_string tis_p_callenv_names[] = {
+ { 0, "Specified call environment"},
+ { 2, "Specified global and/or instance data block"},
+ { 0, NULL }
+};
+static gint hf_s7comm_tis_p_callcond = -1;
+static const value_string tis_p_callcond_names[] = {
+ { 0x0000, "Not set" },
+ { 0x0001, "On block number" },
+ { 0x0101, "On block number with code address" },
+ { 0x0a00, "On DB1 (DB) content" },
+ { 0x000a, "On DB2 (DI) content" },
+ { 0x0a0a, "On DB1 (DB) and DB2 (DI) content" },
+ { 0, NULL }
+};
+static gint hf_s7comm_tis_p_callcond_blocktype = -1;
+static gint hf_s7comm_tis_p_callcond_blocknr = -1;
+static gint hf_s7comm_tis_p_callcond_address = -1;
+
+
+static gint hf_s7comm_tis_register_db1_type = -1;
+static gint hf_s7comm_tis_register_db2_type = -1;
+static gint hf_s7comm_tis_register_db1_nr = -1;
+static gint hf_s7comm_tis_register_db2_nr = -1;
+static gint hf_s7comm_tis_register_accu1 = -1;
+static gint hf_s7comm_tis_register_accu2 = -1;
+static gint hf_s7comm_tis_register_accu3 = -1;
+static gint hf_s7comm_tis_register_accu4 = -1;
+static gint hf_s7comm_tis_register_ar1 = -1;
+static gint hf_s7comm_tis_register_ar2 = -1;
+static gint hf_s7comm_tis_register_stw = -1;
+static gint hf_s7comm_tis_exithold_until = -1;
+static const value_string tis_exithold_until_names[] = {
+ { 0, "Next breakpoint" },
+ { 1, "Next statement" },
+ { 0, NULL }
+};
+static gint hf_s7comm_tis_exithold_res1 = -1;
+static gint hf_s7comm_tis_bstack_nest_depth = -1;
+static gint hf_s7comm_tis_bstack_reserved = -1;
+static gint hf_s7comm_tis_istack_reserved = -1;
+static gint hf_s7comm_tis_lstack_reserved = -1;
+static gint hf_s7comm_tis_lstack_size = -1;
+static gint hf_s7comm_tis_lstack_data = -1;
+static gint hf_s7comm_tis_blockstat_flagsunknown = -1;
+static gint hf_s7comm_tis_blockstat_number_of_lines = -1;
+static gint hf_s7comm_tis_blockstat_line_address = -1;
+static gint hf_s7comm_tis_blockstat_data = -1;
+static gint hf_s7comm_tis_blockstat_reserved = -1;
+
+/* Organization block local data */
+static gint hf_s7comm_ob_ev_class = -1;
+static gint hf_s7comm_ob_scan_1 = -1;
+static gint hf_s7comm_ob_strt_inf = -1;
+static gint hf_s7comm_ob_flt_id = -1;
+static gint hf_s7comm_ob_priority = -1;
+static gint hf_s7comm_ob_number = -1;
+static gint hf_s7comm_ob_reserved_1 = -1;
+static gint hf_s7comm_ob_reserved_2 = -1;
+static gint hf_s7comm_ob_reserved_3 = -1;
+static gint hf_s7comm_ob_reserved_4 = -1;
+static gint hf_s7comm_ob_reserved_4_dw = -1;
+static gint hf_s7comm_ob_prev_cycle = -1;
+static gint hf_s7comm_ob_min_cycle = -1;
+static gint hf_s7comm_ob_max_cycle = -1;
+static gint hf_s7comm_ob_period_exe = -1;
+static gint hf_s7comm_ob_sign = -1;
+static gint hf_s7comm_ob_dtime = -1;
+static gint hf_s7comm_ob_phase_offset = -1;
+static gint hf_s7comm_ob_exec_freq = -1;
+static gint hf_s7comm_ob_io_flag = -1;
+static gint hf_s7comm_ob_mdl_addr = -1;
+static gint hf_s7comm_ob_point_addr = -1;
+static gint hf_s7comm_ob_inf_len = -1;
+static gint hf_s7comm_ob_alarm_type = -1;
+static gint hf_s7comm_ob_alarm_slot = -1;
+static gint hf_s7comm_ob_alarm_spec = -1;
+static guint hf_s7comm_ob_error_info = -1;
+static guint hf_s7comm_ob_err_ev_class = -1;
+static guint hf_s7comm_ob_err_ev_num = -1;
+static guint hf_s7comm_ob_err_ob_priority = -1;
+static guint hf_s7comm_ob_err_ob_num = -1;
+static guint hf_s7comm_ob_rack_cpu = -1;
+static guint hf_s7comm_ob_8x_fault_flags = -1;
+static guint hf_s7comm_ob_mdl_type_b = -1;
+static guint hf_s7comm_ob_mdl_type_w = -1;
+static guint hf_s7comm_ob_rack_num = -1;
+static guint hf_s7comm_ob_racks_flt = -1;
+static guint hf_s7comm_ob_strtup = -1;
+static guint hf_s7comm_ob_stop = -1;
+static guint hf_s7comm_ob_strt_info = -1;
+static guint hf_s7comm_ob_sw_flt = -1;
+static guint hf_s7comm_ob_blk_type = -1;
+static guint hf_s7comm_ob_flt_reg = -1;
+static guint hf_s7comm_ob_flt_blk_num = -1;
+static guint hf_s7comm_ob_prg_addr = -1;
+static guint hf_s7comm_ob_mem_area = -1;
+static guint hf_s7comm_ob_mem_addr = -1;
+
+static gint hf_s7comm_diagdata_req_block_type = -1;
+static gint hf_s7comm_diagdata_req_block_num = -1;
+static gint hf_s7comm_diagdata_req_startaddr_awl = -1;
+static gint hf_s7comm_diagdata_req_saz = -1;
/* Flags for requested registers in diagnostic data telegrams */
static gint hf_s7comm_diagdata_registerflag = -1; /* Registerflags */
@@ -1540,8 +1692,6 @@ static gint hf_s7comm_data_ncprg_filepath = -1;
static gint hf_s7comm_data_ncprg_filedata = -1;
/* Variable status */
-static gint hf_s7comm_varstat_data_type = -1; /* Type of data, 1 byte, stringlist userdata_prog_vartab_type_names */
-static gint hf_s7comm_varstat_byte_count = -1; /* Byte count, 2 bytes, int */
static gint hf_s7comm_varstat_unknown = -1; /* Unknown byte(s), hex */
static gint hf_s7comm_varstat_item_count = -1; /* Item count, 2 bytes, int */
static gint hf_s7comm_varstat_req_memory_area = -1; /* Memory area, 1 byte, stringlist userdata_prog_varstat_area_names */
@@ -2342,6 +2492,8 @@ static gint ett_s7comm_cpu_alarm_message_object = -1; /* Subtree f
static gint ett_s7comm_cpu_alarm_message_timestamp = -1; /* Subtree for an alarm message timestamp */
static gint ett_s7comm_cpu_alarm_message_associated_value = -1; /* Subtree for an alarm message associated value */
static gint ett_s7comm_cpu_diag_msg = -1; /* Subtree for a CPU diagnostic message */
+static gint ett_s7comm_prog_parameter = -1;
+static gint ett_s7comm_prog_data = -1;
static const char mon_names[][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
@@ -3620,82 +3772,80 @@ s7comm_decode_plc_controls_updownload(tvbuff_t *tvb,
/*******************************************************************************************************
*
- * PDU Type: User Data -> Function group 1 -> Programmer commands -> Request diagnostic data (0x13 or 0x01)
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Block status (0x13 or 0x01)
*
*******************************************************************************************************/
static guint32
-s7comm_decode_ud_prog_reqdiagdata(tvbuff_t *tvb,
- proto_tree *data_tree,
- guint8 subfunc, /* Subfunction */
- guint32 offset)
+s7comm_decode_ud_tis_blockstat(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint16 td_size,
+ guint8 type,
+ guint8 subfunc,
+ guint32 offset)
{
proto_item *item = NULL;
proto_tree *item_tree = NULL;
guint16 line_nr;
guint16 line_cnt;
- guint16 ask_size;
guint16 item_size = 4;
guint8 registerflags;
gchar str_flags[80];
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_askheadersize, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- ask_size = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(data_tree, hf_s7comm_diagdata_req_asksize, tvb, offset, 2, ask_size);
- offset += 2;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_unknown, tvb, offset, 6, ENC_NA);
- offset += 6;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_answersize, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_unknown, tvb, offset, 13, ENC_NA);
- offset += 13;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_block_type, tvb, offset, 1, ENC_BIG_ENDIAN);
- offset += 1;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_block_num, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_saz, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_unknown, tvb, offset, 1, ENC_NA);
- offset += 1;
- if (subfunc == 0x13) {
- line_cnt = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(data_tree, hf_s7comm_diagdata_req_number_of_lines, tvb, offset, 2, line_cnt);
- offset += 1;
- proto_tree_add_item(data_tree, hf_s7comm_diagdata_req_unknown, tvb, offset, 1, ENC_NA);
- offset += 1;
- } else {
- line_cnt = (ask_size - 2) / 2;
- }
- proto_tree_add_bitmask(data_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
- ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
- offset += 1;
-
- if (subfunc == 0x13) {
- item_size = 4;
- } else {
- item_size = 2;
- }
- for (line_nr = 0; line_nr < line_cnt; line_nr++) {
-
- item = proto_tree_add_item(data_tree, hf_s7comm_data_item, tvb, offset, item_size, ENC_NA);
- item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
- if (subfunc == 0x13) {
- proto_tree_add_item(item_tree, hf_s7comm_diagdata_req_line_address, tvb, offset, 2, ENC_BIG_ENDIAN);
- offset += 2;
+ if (type == S7COMM_UD_TYPE_REQ) {
+ if (subfunc == S7COMM_UD_SUBF_PROG_BLOCKSTAT2) {
+ proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_flagsunknown, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ line_cnt = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_tis_blockstat_number_of_lines, tvb, offset, 1, line_cnt);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ } else {
+ proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ line_cnt = (td_size - 2) / 2;
}
- proto_tree_add_item(item_tree, hf_s7comm_diagdata_req_unknown, tvb, offset, 1, ENC_NA);
- offset += 1;
-
- registerflags = tvb_get_guint8(tvb, offset);
- make_registerflag_string(str_flags, registerflags, sizeof(str_flags));
- proto_item_append_text(item, " [%d]: (%s)", line_nr+1, str_flags);
- proto_tree_add_bitmask(item_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
+ proto_tree_add_bitmask(td_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
offset += 1;
- }
+ if (subfunc == S7COMM_UD_SUBF_PROG_BLOCKSTAT2) {
+ item_size = 4;
+ } else {
+ item_size = 2;
+ }
+ for (line_nr = 0; line_nr < line_cnt; line_nr++) {
+ item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, item_size, ENC_NA);
+ item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
+ if (subfunc == S7COMM_UD_SUBF_PROG_BLOCKSTAT2) {
+ proto_tree_add_item(item_tree, hf_s7comm_tis_blockstat_line_address, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ }
+ proto_tree_add_item(item_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ registerflags = tvb_get_guint8(tvb, offset);
+ make_registerflag_string(str_flags, registerflags, sizeof(str_flags));
+ proto_item_append_text(item, " [%d]: (%s)", line_nr+1, str_flags);
+ proto_tree_add_bitmask(item_tree, tvb, offset, hf_s7comm_diagdata_registerflag,
+ ett_s7comm_diagdata_registerflag, s7comm_diagdata_registerflag_fields, ENC_BIG_ENDIAN);
+ offset += 1;
+ }
+ } else if (type == S7COMM_UD_TYPE_PUSH) {
+ /* The response data can only be dissected when the requested registers for each line
+ * from the job setup is known. As the STW is only 16 Bits and all other registers 32 Bits,
+ * this has no fixed structure.
+ * The only thing that can be shown is the start address. Next the requested registers,
+ * the start address of next line with the requested registers and so on.
+ */
+ proto_tree_add_item(td_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_data, tvb, offset, td_size - 2, ENC_NA);
+ offset += (td_size - 2);
+ } else {
+ /* TODO: Show unknown data as raw bytes */
+ proto_tree_add_item(td_tree, hf_s7comm_tis_blockstat_reserved, tvb, offset, td_size, ENC_NA);
+ offset += td_size;
+ }
return offset;
}
@@ -3708,7 +3858,8 @@ static guint32
s7comm_decode_ud_tis_item_address(tvbuff_t *tvb,
guint32 offset,
proto_tree *sub_tree,
- guint16 item_no)
+ guint16 item_no,
+ gchar *add_text)
{
guint32 bytepos = 0;
guint16 len = 0;
@@ -3722,7 +3873,7 @@ s7comm_decode_ud_tis_item_address(tvbuff_t *tvb,
sub_tree = proto_item_add_subtree(item, ett_s7comm_param_item);
- proto_item_append_text(item, " [%d]:", item_no + 1);
+ proto_item_append_text(item, " [%d]%s:", item_no + 1, add_text);
/* Area, 1 byte */
area = tvb_get_guint8(tvb, offset);
@@ -3831,14 +3982,15 @@ s7comm_decode_ud_tis_item_address(tvbuff_t *tvb,
/*******************************************************************************************************
*
- * PDU Type: User Data -> Function group 1 -> Programmer commands -> Variable table -> response
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Item value
*
*******************************************************************************************************/
static guint32
-s7comm_decode_ud_prog_vartab_res_item(tvbuff_t *tvb,
- guint32 offset,
- proto_tree *sub_tree,
- guint16 item_no)
+s7comm_decode_ud_tis_item_value(tvbuff_t *tvb,
+ guint32 offset,
+ proto_tree *sub_tree,
+ guint16 item_no,
+ gchar *add_text)
{
guint16 len = 0, len2 = 0;
guint8 ret_val = 0;
@@ -3861,7 +4013,7 @@ s7comm_decode_ud_prog_vartab_res_item(tvbuff_t *tvb,
/* the PLC places extra bytes at the end if length is not a multiple of 2 */
if (len % 2) {
len2 = len + 1;
- }else {
+ } else {
len2 = len;
}
}
@@ -3869,7 +4021,7 @@ s7comm_decode_ud_prog_vartab_res_item(tvbuff_t *tvb,
item = proto_tree_add_item(sub_tree, hf_s7comm_data_item, tvb, offset, len + head_len, ENC_NA);
sub_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
- proto_item_append_text(item, " [%d]: (%s)", item_no + 1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
+ proto_item_append_text(item, " [%d]%s: (%s)", item_no + 1, add_text, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
proto_tree_add_uint(sub_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
proto_tree_add_uint(sub_tree, hf_s7comm_data_transport_size, tvb, offset + 1, 1, tsize);
@@ -3889,6 +4041,1113 @@ s7comm_decode_ud_prog_vartab_res_item(tvbuff_t *tvb,
/*******************************************************************************************************
*
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Force (0x09)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_force(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ guint16 item_count;
+ guint16 i;
+ guint8 ret_val = 0;
+ proto_item *item = NULL;
+ proto_tree *item_tree = NULL;
+
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ item_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
+ offset += 2;
+ for (i = 0; i < item_count; i++) {
+ offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to force");
+ }
+ for (i = 0; i < item_count; i++) {
+ offset = s7comm_decode_ud_tis_item_value(tvb, offset, td_tree, i, " Value to force");
+ }
+ break;
+ case S7COMM_UD_TYPE_PUSH:
+ item_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
+ offset += 2;
+ for (i = 0; i < item_count; i++) {
+ item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
+ item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
+ ret_val = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
+ proto_item_append_text(item, " [%d]: (%s)", i + 1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
+ offset += 1;
+ }
+ if (item_count % 2) {
+ proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ }
+ break;
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
+ * Dissects the parameter part
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_param(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint8 type,
+ guint16 tp_size,
+ guint32 offset)
+{
+ guint32 start_offset;
+ guint32 callenv_setup = 0;
+ proto_item *item = NULL;
+ proto_tree *tp_tree = NULL;
+
+ start_offset = offset;
+ if (tp_size > 0) {
+ item = proto_tree_add_item(tree, hf_s7comm_tis_parameter, tvb, offset, tp_size, ENC_NA);
+ tp_tree = proto_item_add_subtree(item, ett_s7comm_prog_parameter);
+ if (type == S7COMM_UD_TYPE_REQ) {
+ if (tp_size >= 4) {
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param1, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param2, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ }
+ if (tp_size >= 20) {
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param3, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_answersize, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param5, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param6, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param7, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param8, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_param9, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_trgevent, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ }
+ if (tp_size >= 26) {
+ proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_block_type, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_block_num, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_startaddr_awl, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ }
+ if (tp_size >= 28) {
+ proto_tree_add_item(tp_tree, hf_s7comm_diagdata_req_saz, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ }
+ if (tp_size >= 36) {
+ proto_tree_add_item_ret_uint(tp_tree, hf_s7comm_tis_p_callenv, tvb, offset, 2, ENC_BIG_ENDIAN, &callenv_setup);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ if (callenv_setup == 2) {
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ } else {
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ if (tp_size >= 38) {
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_p_callcond_address, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ }
+ }
+ }
+ } else {
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_res_param1, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(tp_tree, hf_s7comm_tis_res_param2, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ }
+ }
+ /* May be we don't know all values when here, so set offset to the given length */
+ return start_offset + tp_size;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Disable job (0x0d), Enable job (0x0e),
+ * Delete job (0x0f), Read job list (0x10),
+ * Read job (0x11)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_jobs(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint16 td_size,
+ guint8 type,
+ guint8 subfunc,
+ guint32 offset)
+{
+ guint16 i;
+ proto_item *item = NULL;
+ proto_tree *item_tree = NULL;
+ guint16 job_tp_size;
+ guint16 job_td_size;
+ proto_tree *job_td_tree = NULL;
+ guint8 job_subfunc;
+
+ if (type == S7COMM_UD_TYPE_REQ) {
+ switch (subfunc) {
+ case S7COMM_UD_SUBF_PROG_DELETEJOB:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ /* fallthrough */
+ case S7COMM_UD_SUBF_PROG_ENABLEJOB:
+ case S7COMM_UD_SUBF_PROG_DISABLEJOB:
+ case S7COMM_UD_SUBF_PROG_READJOB:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ break;
+ case S7COMM_UD_SUBF_PROG_READJOBLIST:
+ /* 4 bytes, possible as filter? */
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ break;
+ case S7COMM_UD_SUBF_PROG_REPLACEJOB:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ /* The job which has to be replaced */
+ job_subfunc = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ job_tp_size = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(td_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ job_td_size = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(td_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ /* New job parameter tree */
+ if (job_tp_size > 0) {
+ offset = s7comm_decode_ud_tis_param(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_tp_size, offset);
+ }
+ /* New job data tree */
+ if (job_td_size > 0) {
+ offset = s7comm_decode_ud_tis_data(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_subfunc, job_td_size, offset);
+ }
+ break;
+ }
+ } else {
+ switch (subfunc) {
+ case S7COMM_UD_SUBF_PROG_READJOBLIST:
+ /* 4 bytes each job:
+ * - 2 bytes job id
+ * - 2 bytes status: 1=active, 0=idle/pending?
+ */
+ for (i = 0; i < td_size / 4; i++) {
+ item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 4, ENC_NA);
+ item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
+ proto_item_append_text(item, " [%d] Job", i + 1);
+
+ proto_tree_add_item(item_tree, hf_s7comm_tis_job_function, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_job_seqnr, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_job_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ }
+ break;
+ case S7COMM_UD_SUBF_PROG_READJOB:
+ /* This includes the same data as in the job request. With the disadvantage that is does
+ * not contain information of the function, so the data can't be further dissected.
+ * We need to know the function from the request.
+ */
+ job_tp_size = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(td_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ job_td_size = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(td_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ /* Job parameter tree */
+ if (job_tp_size > 0) {
+ offset = s7comm_decode_ud_tis_param(tvb, td_tree, S7COMM_UD_TYPE_REQ, job_tp_size, offset);
+ }
+ /* Job data tree */
+ if (job_td_size > 0) {
+ item = proto_tree_add_item(td_tree, hf_s7comm_tis_data, tvb, offset, job_td_size, ENC_NA);
+ job_td_tree = proto_item_add_subtree(item, ett_s7comm_prog_data);
+ proto_tree_add_item(job_td_tree, hf_s7comm_tis_job_reserved, tvb, offset, job_td_size, ENC_NA);
+ offset += job_td_size;
+ }
+ break;
+ }
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Variable status (0x03)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_varstat(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ guint16 item_count;
+ guint16 i;
+
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ item_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
+ offset += 2;
+ for (i = 0; i < item_count; i++) {
+ offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to read");
+ }
+ break;
+ case S7COMM_UD_TYPE_PUSH:
+ item_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
+ offset += 2;
+ for (i = 0; i < item_count; i++) {
+ offset = s7comm_decode_ud_tis_item_value(tvb, offset, td_tree, i, " Read data");
+ }
+ break;
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Modify variable (0x08)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_modvar(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ guint16 item_count;
+ guint16 i;
+ guint8 ret_val = 0;
+ proto_item *item = NULL;
+ proto_tree *item_tree = NULL;
+
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ item_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
+ offset += 2;
+ for (i = 0; i < item_count; i++) {
+ offset = s7comm_decode_ud_tis_item_address(tvb, offset, td_tree, i, " Address to write");
+ }
+ for (i = 0; i < item_count; i++) {
+ offset = s7comm_decode_ud_tis_item_value(tvb, offset, td_tree, i, " Data to write");
+ }
+ break;
+ case S7COMM_UD_TYPE_PUSH:
+ item_count = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(td_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
+ offset += 2;
+ for (i = 0; i < item_count; i++) {
+ item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 1, ENC_NA);
+ item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
+ ret_val = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(item_tree, hf_s7comm_data_returncode, tvb, offset, 1, ret_val);
+ proto_item_append_text(item, " [%d]: (%s)", i + 1, val_to_str(ret_val, s7comm_item_return_valuenames, "Unknown code: 0x%02x"));
+ offset += 1;
+ }
+ if (item_count % 2) {
+ proto_tree_add_item(item_tree, hf_s7comm_data_fillbyte, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ }
+ break;
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output ISTACK (0x03)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_istack(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ guint8 ob_number = 0;
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ break;
+ case S7COMM_UD_TYPE_RES:
+ case S7COMM_UD_TYPE_PUSH:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_continued_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_continued_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_continued_address, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu1, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu2, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu3, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu4, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar1, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar2, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_stw, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ /* read the OB number first */
+ ob_number = tvb_get_guint8(tvb, offset + 3);
+ switch (ob_number) {
+ case 1: /* Cyclic execution */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_scan_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_prev_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_min_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_max_cycle, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 10: /* Time of day interrupt 0..7 */
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_period_exe, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 20: /* Time delay interrupt 0..3 */
+ case 21:
+ case 22:
+ case 23:
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_scan_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_sign, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_dtime, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ case 30: /* Cyclic interrupt 0..8 */
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_phase_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_exec_freq, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 40: /* Hardware interrupt 0..8 */
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ case 48:
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_point_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ case 55: /* DP Statusalarm */
+ case 56: /* DP Updatealarm */
+ case 57: /* DP Specific alarm */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_inf_len, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_slot, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_alarm_spec, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ break;
+ case 80: /* Cycle time fault */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_error_info, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_num, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_num, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ break;
+ case 81: /* Power supply fault */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_rack_cpu, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 82: /* I/O Point fault 1 */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_type_b, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_8x_fault_flags, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ break;
+ case 83: /* I/O Point fault 2 */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_io_flag, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_rack_num, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_type_w, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 84: /* CPU fault */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4_dw, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ case 85: /* OB not loaded fault */
+ case 87: /* Communication Fault */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ev_num, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_err_ob_num, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ break;
+ case 86: /* Loss of rack fault */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_id, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mdl_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_racks_flt, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ case 90: /* Background cycle */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_inf, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_3, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_4_dw, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ case 100: /* Complete restart */
+ case 101: /* Restart */
+ case 102: /* Cold restart */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strtup, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_2, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_stop, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_strt_info, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ case 121: /* Programming Error */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_sw_flt, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_blk_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_reserved_1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_reg, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_blk_num, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_prg_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ case 122: /* Module Access Error */
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_sw_flt, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_blk_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mem_area, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_mem_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_flt_blk_num, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_prg_addr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ break;
+ default:
+ proto_tree_add_item(td_tree, hf_s7comm_ob_ev_class, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_priority, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_ob_number, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_istack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ break;
+ }
+ offset = s7comm_add_timestamp_to_tree(tvb, td_tree, offset, FALSE, FALSE);
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output BSTACK (0x04)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_bstack(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint16 td_size,
+ guint8 type,
+ guint32 offset)
+{
+ guint16 i;
+ guint16 blocktype;
+ guint16 blocknumber;
+ proto_item *item = NULL;
+ proto_tree *item_tree = NULL;
+ int rem;
+ guint32 replen;
+
+ /* Possible firmware bug in IM151-8 CPU, where also the date size information
+ * in the header is 4 bytes too short.
+ */
+ replen = tvb_reported_length_remaining(tvb, offset);
+ if (replen < td_size) {
+ /* TODO: Show this mismatch? We fix the length here. */
+ td_size = replen;
+ }
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ break;
+ case S7COMM_UD_TYPE_RES:
+ case S7COMM_UD_TYPE_PUSH:
+ rem = td_size;
+ i = 1;
+ while (rem > 16) {
+ item = proto_tree_add_item(td_tree, hf_s7comm_data_item, tvb, offset, 16, ENC_NA);
+ item_tree = proto_item_add_subtree(item, ett_s7comm_data_item);
+ blocktype = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ blocknumber = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_item_append_text(item, " [%d] BSTACK entry for: %s %d", i++,
+ val_to_str(blocktype, subblktype_names, "Unknown Subblk type: 0x%02x"), blocknumber);
+ rem -= 16;
+ if (blocktype == S7COMM_SUBBLKTYPE_OB) {
+ proto_tree_add_item(item_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ rem -= 4;
+ if (rem >= 8) {
+ offset = s7comm_add_timestamp_to_tree(tvb, item_tree, offset, FALSE, FALSE);
+ rem -= 8;
+ } else {
+ proto_tree_add_item(item_tree, hf_s7comm_tis_bstack_reserved, tvb, offset, rem, ENC_NA);
+ offset += rem;
+ rem = 0;
+ break;
+ }
+ }
+ }
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Output LSTACK (0x05)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_lstack(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ guint16 len;
+
+ if (type == S7COMM_UD_TYPE_REQ) {
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_bstack_nest_depth, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ } else {
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ len = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_size, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_data, tvb, offset, len, ENC_NA);
+ offset += len;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_prioclass, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_reserved, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_lstack_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ offset = s7comm_add_timestamp_to_tree(tvb, td_tree, offset, FALSE, FALSE);
+ }
+ return offset;
+}
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Exit Hold (0x0b)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_exithold(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ /* Only request with data payload was seen */
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_exithold_until, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_exithold_res1, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ break;
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands -> Breakpoint (0x0a)
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_breakpoint(tvbuff_t *tvb,
+ proto_tree *td_tree,
+ guint8 type,
+ guint32 offset)
+{
+ switch (type) {
+ case S7COMM_UD_TYPE_REQ:
+ proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ break;
+ case S7COMM_UD_TYPE_RES:
+ case S7COMM_UD_TYPE_PUSH:
+ /* Info: Both blocknumbers and addresses are the same on online-blockview inside a block.
+ * On return out of a block, the first address contains the current breakpoint, the second
+ * address the address from where it was returned (previous block).
+ */
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_interrupted_address, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_blocktype, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_blocknr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_address, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_breakpoint_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_stw, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu1, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_accu2, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar1, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_ar2, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_type, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db1_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ proto_tree_add_item(td_tree, hf_s7comm_tis_register_db2_nr, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
+ * Dissects the data part
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_data(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint8 type,
+ guint8 subfunc,
+ guint16 td_size,
+ guint32 offset)
+{
+ proto_item *item = NULL;
+ proto_tree *td_tree = NULL;
+
+ if (td_size > 0) {
+ item = proto_tree_add_item(tree, hf_s7comm_tis_data, tvb, offset, td_size, ENC_NA);
+ td_tree = proto_item_add_subtree(item, ett_s7comm_prog_data);
+ switch (subfunc) {
+ case S7COMM_UD_SUBF_PROG_OUTISTACK:
+ offset = s7comm_decode_ud_tis_istack(tvb, td_tree, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_OUTBSTACK:
+ offset = s7comm_decode_ud_tis_bstack(tvb, td_tree, td_size, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_OUTLSTACK:
+ offset = s7comm_decode_ud_tis_lstack(tvb, td_tree, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_BREAKPOINT:
+ offset = s7comm_decode_ud_tis_breakpoint(tvb, td_tree, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_EXITHOLD:
+ offset = s7comm_decode_ud_tis_exithold(tvb, td_tree, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_BLOCKSTAT:
+ case S7COMM_UD_SUBF_PROG_BLOCKSTAT2:
+ offset = s7comm_decode_ud_tis_blockstat(tvb, td_tree, td_size, type, subfunc, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_VARSTAT:
+ offset = s7comm_decode_ud_tis_varstat(tvb, td_tree, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_DISABLEJOB:
+ case S7COMM_UD_SUBF_PROG_ENABLEJOB:
+ case S7COMM_UD_SUBF_PROG_DELETEJOB:
+ case S7COMM_UD_SUBF_PROG_READJOBLIST:
+ case S7COMM_UD_SUBF_PROG_READJOB:
+ case S7COMM_UD_SUBF_PROG_REPLACEJOB:
+ offset = s7comm_decode_ud_tis_jobs(tvb, td_tree, td_size, type, subfunc, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_MODVAR:
+ offset = s7comm_decode_ud_tis_modvar(tvb, td_tree, type, offset);
+ break;
+ case S7COMM_UD_SUBF_PROG_FORCE:
+ offset = s7comm_decode_ud_tis_force(tvb, td_tree, type, offset);
+ break;
+ default:
+ proto_tree_add_item(td_tree, hf_s7comm_varstat_unknown, tvb, offset, td_size, ENC_NA);
+ offset += td_size;
+ break;
+ }
+ }
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
+ * PDU Type: User Data -> Function group 1 -> Programmer commands / Test and installation functions
+ *
+ *******************************************************************************************************/
+static guint32
+s7comm_decode_ud_tis_subfunc(tvbuff_t *tvb,
+ proto_tree *data_tree,
+ guint8 type,
+ guint8 subfunc,
+ guint32 offset)
+{
+ guint16 tp_size = 0;
+ guint16 td_size = 0;
+
+ tp_size = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(data_tree, hf_s7comm_tis_parametersize, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ td_size = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_item(data_tree, hf_s7comm_tis_datasize, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+ /* Parameter tree */
+ offset = s7comm_decode_ud_tis_param(tvb, data_tree, type, tp_size, offset);
+ /* Data tree */
+ offset = s7comm_decode_ud_tis_data(tvb, data_tree, type, subfunc, td_size, offset);
+ return offset;
+}
+
+/*******************************************************************************************************
+ *
* PDU Type: User Data -> Function group 5 -> Security functions?
*
*******************************************************************************************************/
@@ -4851,96 +6110,6 @@ s7comm_decode_ud_cyclic_subfunc(tvbuff_t *tvb,
/*******************************************************************************************************
*
- * PDU Type: User Data -> Function group 1 -> Programmer commands
- *
- *******************************************************************************************************/
-static guint32
-s7comm_decode_ud_prog_subfunc(tvbuff_t *tvb,
- proto_tree *data_tree,
- guint8 type, /* Type of data (request/response) */
- guint8 subfunc, /* Subfunction */
- guint32 dlength,
- guint32 offset)
-{
- gboolean know_data = FALSE;
-
- guint8 data_type;
- guint16 byte_count;
- guint16 item_count;
- guint16 i;
-
- switch(subfunc)
- {
- case S7COMM_UD_SUBF_PROG_BLOCKSTAT:
- case S7COMM_UD_SUBF_PROG_BLOCKSTAT2:
- /* start variable table or block online view */
- /* TODO: Can only handle requests/response, not the "following" telegrams because it's necessary to correlate them
- with the previous request */
- if (type != S7COMM_UD_TYPE_PUSH) {
- offset = s7comm_decode_ud_prog_reqdiagdata(tvb, data_tree, subfunc, offset);
- know_data = TRUE;
- }
- break;
-
- case S7COMM_UD_SUBF_PROG_VARSTAT:
- /* online status in variable table */
- offset += 1; /* 1 Byte const 0, skip */
- data_type = tvb_get_guint8(tvb, offset); /* 1 Byte type: 0x14 = Request, 0x04 = Response */
- proto_tree_add_uint(data_tree, hf_s7comm_varstat_data_type, tvb, offset, 1, data_type);
- offset += 1;
-
- byte_count = tvb_get_ntohs(tvb, offset); /* 2 Bytes: Number of bytes of item-data including item-count */
- proto_tree_add_uint(data_tree, hf_s7comm_varstat_byte_count, tvb, offset, 2, byte_count);
- offset += 2;
-
- switch (data_type)
- {
- case S7COMM_UD_SUBF_PROG_VARTAB_TYPE_REQ:
- /*** Request of data areas ***/
-
- /* 20 Bytes unknown part */
- proto_tree_add_item(data_tree, hf_s7comm_varstat_unknown, tvb, offset, 20, ENC_NA);
- offset += 20;
-
- item_count = tvb_get_ntohs(tvb, offset); /* 2 Bytes header: number of items following */
- proto_tree_add_uint(data_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
- offset += 2;
-
- /* parse item data */
- for (i = 0; i < item_count; i++) {
- offset = s7comm_decode_ud_tis_item_address(tvb, offset, data_tree, i);
- }
- know_data = TRUE;
- break;
-
- case S7COMM_UD_SUBF_PROG_VARTAB_TYPE_RES:
- /*** Response of PLC to requested data-areas ***/
-
- /* 4 Bytes unknown part */
- proto_tree_add_item(data_tree, hf_s7comm_varstat_unknown, tvb, offset, 4, ENC_NA);
- offset += 4;
-
- item_count = tvb_get_ntohs(tvb, offset); /* 2 Bytes: number of items following */
- proto_tree_add_uint(data_tree, hf_s7comm_varstat_item_count, tvb, offset, 2, item_count);
- offset += 2;
-
- /* parse item data */
- for (i = 0; i < item_count; i++) {
- offset = s7comm_decode_ud_prog_vartab_res_item(tvb, offset, data_tree, i);
- }
- know_data = TRUE;
- break;
- }
- }
-
- if (know_data == FALSE && dlength > 0) {
- proto_tree_add_item(data_tree, hf_s7comm_userdata_data, tvb, offset, dlength, ENC_NA);
- offset += dlength;
- }
- return offset;
-}
-/*******************************************************************************************************
- *
* PDU Type: User Data: Data part and reassembly
*
*******************************************************************************************************/
@@ -5059,7 +6228,7 @@ s7comm_decode_ud_data(tvbuff_t *tvb,
if (last_data_unit == S7COMM_UD_LASTDATAUNIT_YES && length_rem > 0) {
switch (funcgroup) {
case S7COMM_UD_FUNCGROUP_PROG:
- offset = s7comm_decode_ud_prog_subfunc(next_tvb, data_tree, type, subfunc, length_rem, offset);
+ offset = s7comm_decode_ud_tis_subfunc(next_tvb, data_tree, type, subfunc, offset);
break;
case S7COMM_UD_FUNCGROUP_CYCLIC:
offset = s7comm_decode_ud_cyclic_subfunc(next_tvb, pinfo, seq_num, data_tree, type, subfunc, length_rem, offset);
@@ -5892,21 +7061,330 @@ proto_register_s7comm (void)
{ "Non Retain", "s7comm.param.userdata.blockinfo.nonretain", FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
NULL, HFILL }},
- /* Programmer commands, diagnostic data */
- { &hf_s7comm_diagdata_req_askheadersize,
- { "Ask header size", "s7comm.diagdata.req.askheadersize", FT_UINT16, BASE_DEC, NULL, 0x0,
+ /* Programmer commands / Test and installation (TIS) functions */
+ { &hf_s7comm_tis_parameter,
+ { "TIS Parameter", "s7comm.tis.parameter", FT_NONE, BASE_NONE, NULL, 0x0,
+ "TIS Test and Installation: Parameter", HFILL }},
+ { &hf_s7comm_tis_data,
+ { "TIS Data", "s7comm.cpu.tis.data", FT_NONE, BASE_NONE, NULL, 0x0,
+ "TIS Test and Installation: Data", HFILL }},
+ { &hf_s7comm_tis_parametersize,
+ { "TIS Parameter size", "s7comm.tis.parametersize", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_datasize,
+ { "TIS Data size", "s7comm.tis.datasize", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_param1,
+ { "TIS Parameter 1", "s7comm.tis.param1", FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }},
- { &hf_s7comm_diagdata_req_asksize,
- { "Ask size", "s7comm.diagdata.req.asksize", FT_UINT16, BASE_DEC, NULL, 0x0,
+ { &hf_s7comm_tis_param2,
+ { "TIS Parameter 2 - Trigger type", "s7comm.tis.param2", FT_UINT16, BASE_DEC, VALS(tis_param2_names), 0x0,
NULL, HFILL }},
- { &hf_s7comm_diagdata_req_unknown,
- { "Unknown byte(s) diagdata", "s7comm.diagdata.req.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
+ { &hf_s7comm_tis_param3,
+ { "TIS Parameter 3 - Trigger frequency", "s7comm.tis.param3", FT_UINT16, BASE_DEC, VALS(tis_param3_names), 0x0,
NULL, HFILL }},
- { &hf_s7comm_diagdata_req_answersize,
- { "Answer size", "s7comm.diagdata.req.answersize", FT_UINT16, BASE_DEC, NULL, 0x0,
+ { &hf_s7comm_tis_answersize,
+ { "TIS Parameter 4 - Answer size", "s7comm.tis.answersize", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "TIS Answer size: Expected data size of PLC answer to this job", HFILL }},
+ { &hf_s7comm_tis_param5,
+ { "TIS Parameter 5", "s7comm.tis.param5", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_param6,
+ { "TIS Parameter 6", "s7comm.tis.param6", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_param7,
+ { "TIS Parameter 7", "s7comm.tis.param7", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_param8,
+ { "TIS Parameter 8", "s7comm.tis.param8", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_param9,
+ { "TIS Parameter 9", "s7comm.tis.param9", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_trgevent,
+ { "TIS Parameter 10 - Trigger event", "s7comm.varstat.trgevent", FT_UINT16, BASE_HEX, VALS(userdata_varstat_trgevent_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_res_param1,
+ { "TIS Response Parameter 1", "s7comm.tis.res.param1", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_res_param2,
+ { "TIS Response Parameter 2", "s7comm.tis.res.param2", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_job_function,
+ { "Job function", "s7comm.tis.job.function", FT_UINT8, BASE_DEC, VALS(userdata_prog_subfunc_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_job_seqnr,
+ { "Job reference sequence number", "s7comm.tis.job.response_seq_num", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Job reference sequence number (find function setup with s7comm.param.userdata.seq_num)", HFILL }},
+ { &hf_s7comm_tis_job_reserved,
+ { "Job Reserved / Unknown", "s7comm.tis.job.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_interrupted_blocktype,
+ { "Interrupted block type", "s7comm.tis.interrupted.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_interrupted_blocknr,
+ { "Interrupted block number", "s7comm.tis.interrupted.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_interrupted_address,
+ { "Interrupted code address", "s7comm.tis.interrupted.address", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_interrupted_prioclass,
+ { "Interrupted priority class", "s7comm.tis.interrupted.priorityclass", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_continued_blocktype,
+ { "Continued block type", "s7comm.tis.continued.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_continued_blocknr,
+ { "Continued block number", "s7comm.tis.continued.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_continued_address,
+ { "Continued code address", "s7comm.tis.continued.address", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_breakpoint_blocktype,
+ { "Breakpoint block type", "s7comm.tis.breakpoint.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_breakpoint_blocknr,
+ { "Breakpoint block number", "s7comm.tis.breakpoint.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_breakpoint_address,
+ { "Breakpoint code address", "s7comm.tis.breakpoint.address", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_breakpoint_reserved,
+ { "Breakpoint Reserved / Unknown", "s7comm.tis.breakpoint.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_s7comm_tis_p_callenv,
+ { "Call environment setup", "s7comm.tis.callenv_setup", FT_UINT16, BASE_DEC, VALS(tis_p_callenv_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_p_callcond,
+ { "Call condition", "s7comm.tis.callenv_cond", FT_UINT16, BASE_DEC, VALS(tis_p_callcond_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_p_callcond_blocktype,
+ { "Call condition block type", "s7comm.tis.callenv_cond_blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_p_callcond_blocknr,
+ { "Call condition block number", "s7comm.tis.callenv_cond_blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_p_callcond_address,
+ { "Call condition code address", "s7comm.tis.callenv_cond_blockaddress", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+
+ { &hf_s7comm_tis_register_db1_type,
+ { "Register DB1 content type", "s7comm.tis.db1.type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_db2_type,
+ { "Register DB2 content type", "s7comm.tis.db2.type", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_db1_nr,
+ { "Register DB1 block number", "s7comm.tis.db1.number", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_db2_nr,
+ { "Register DB2 block number", "s7comm.tis.db2.number", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_accu1,
+ { "Register ACCU1", "s7comm.tis.accu1", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_accu2,
+ { "Register ACCU2", "s7comm.tis.accu2", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_accu3,
+ { "Register ACCU3", "s7comm.tis.accu3", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_accu4,
+ { "Register ACCU4", "s7comm.tis.accu4", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_ar1,
+ { "Register AR1", "s7comm.tis.ar1", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_ar2,
+ { "Register AR2", "s7comm.tis.ar2", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_register_stw,
+ { "Register STW", "s7comm.tis.stw", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_exithold_until,
+ { "Exit HOLD state until", "s7comm.tis.exithold_until", FT_UINT8, BASE_DEC, VALS(tis_exithold_until_names), 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_exithold_res1 ,
+ { "Exit HOLD Reserved / Unknown", "s7comm.tis.exithold_res1", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_bstack_nest_depth,
+ { "BSTACK nesting depth", "s7comm.tis.bstack.neting_depth", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_bstack_reserved,
+ { "BSTACK Reserved / Unknown", "s7comm.tis.bstack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_istack_reserved,
+ { "ISTACK Reserved / Unknown", "s7comm.tis.istack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_lstack_reserved,
+ { "LSTACK Reserved / Unknown", "s7comm.tis.lstack.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_lstack_size,
+ { "Localdata stack size", "s7comm.tis.lstack.size", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_lstack_data,
+ { "Localdata stack data", "s7comm.tis.lstack.data", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_blockstat_flagsunknown,
+ { "Blockstat flags", "s7comm.tis.blockstat.flagsunknown", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_blockstat_number_of_lines,
+ { "Number of lines", "s7comm.tis.blockstat.number_of_lines", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_blockstat_line_address,
+ { "Address", "s7comm.tis.blockstat.line_address", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_blockstat_data,
+ { "Blockstatus data", "s7comm.tis.blockstat.data", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_tis_blockstat_reserved,
+ { "Blockstatus Reserved / Unknown", "s7comm.tis.blockstat.reserved", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }},
+ /* Organization block local data */
+ { &hf_s7comm_ob_ev_class,
+ { "OB Event class", "s7comm.ob.ev_class", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "OB Event class (Bits 0-3 = 1 (Coming event), Bits 4-7 = 1 (Event class 1)", HFILL }},
+ { &hf_s7comm_ob_scan_1,
+ { "OB Scan 1", "s7comm.ob.scan_1", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "OB Scan 1 (1=Cold restart scan 1 of OB 1), 3=Scan 2-n of OB 1)", HFILL }},
+ { &hf_s7comm_ob_strt_inf,
+ { "OB Start info", "s7comm.ob.strt_info", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "OB Start info (OB n has started)", HFILL }},
+ { &hf_s7comm_ob_flt_id,
+ { "OB Fault identifcation code", "s7comm.ob.flt_id", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_priority,
+ { "OB Priority", "s7comm.ob.priority", FT_UINT8, BASE_DEC, NULL, 0x0,
+ "OB Priority (1 is lowest)", HFILL }},
+ { &hf_s7comm_ob_number,
+ { "OB Number", "s7comm.ob.number", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_reserved_1,
+ { "OB Reserved 1", "s7comm.ob.reserved_1", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "OB Reserved 1 (Reserved for System)", HFILL }},
+ { &hf_s7comm_ob_reserved_2,
+ { "OB Reserved 2", "s7comm.ob.reserved_2", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "OB Reserved 2 (Reserved for System)", HFILL }},
+ { &hf_s7comm_ob_reserved_3,
+ { "OB Reserved 3", "s7comm.ob.reserved_3", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "OB Reserved 3 (Reserved for System)", HFILL }},
+ { &hf_s7comm_ob_reserved_4,
+ { "OB Reserved 4", "s7comm.ob.reserved_4", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "OB Reserved 4 (Reserved for System)", HFILL }},
+ { &hf_s7comm_ob_reserved_4_dw,
+ { "OB Reserved 4", "s7comm.ob.reserved_4_dw", FT_UINT32, BASE_HEX, NULL, 0x0,
+ "OB Reserved 4 (Reserved for System)", HFILL }},
+ { &hf_s7comm_ob_prev_cycle,
+ { "OB Cycle time of previous OB scan (ms)", "s7comm.ob.prev_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_min_cycle,
+ { "OB Minimum cycle time of OB (ms)", "s7comm.ob.min_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_max_cycle,
+ { "OB Maximum cycle time of OB (ms)", "s7comm.ob.max_cycle", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_period_exe,
+ { "OB Period of execution", "s7comm.ob.period_exe", FT_UINT16, BASE_HEX, NULL, 0x0,
+ "OB Period of execution (once, per minute/hour/day/week/month/year)", HFILL }},
+ { &hf_s7comm_ob_sign,
+ { "OB Identifier input (SIGN) attached to SRT_DINT", "s7comm.ob.sign", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_dtime,
+ { "OB Delay time (DTIME) input to SRT_DINT instruction", "s7comm.ob.dtime", FT_UINT32, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_phase_offset,
+ { "OB Phase offset (ms)", "s7comm.ob.phase_offset", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_exec_freq,
+ { "OB Frequency of execution (ms)", "s7comm.ob.exec_freq", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_io_flag,
+ { "OB IO flags", "s7comm.ob.io_flag", FT_UINT16, BASE_DEC, NULL, 0x0,
+ "OB IO flags (0x54=input module, 0x55=output module)", HFILL }},
+ { &hf_s7comm_ob_mdl_addr,
+ { "OB Base address of module initiating interrupt", "s7comm.ob.mdl_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_point_addr,
+ { "OB Address of interrupt point on module", "s7comm.ob.point_addr", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_inf_len,
+ { "OB Length of information", "s7comm.ob.inf_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_alarm_type,
+ { "OB Type of alarm", "s7comm.ob.alarm_type", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_alarm_slot,
+ { "OB Slot", "s7comm.ob.alarm_slot", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_alarm_spec,
+ { "OB Specifier", "s7comm.ob.alarm_spec", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_error_info,
+ { "OB Error information on event", "s7comm.ob.error_info", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_err_ev_class,
+ { "OB Class of event causing error", "s7comm.ob.err_ev_class", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_err_ev_num,
+ { "OB Number of event causing error", "s7comm.ob.err_ev_num", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_err_ob_priority,
+ { "OB Priority of OB causing error", "s7comm.ob.err_ob_priority", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_err_ob_num,
+ { "OB Number of OB causing error", "s7comm.ob.err_ob_num", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_rack_cpu,
+ { "OB Rack / CPU number", "s7comm.ob.rack_cpu", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_8x_fault_flags,
+ { "OB 8x Fault flags", "s7comm.ob.8x_fault_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_mdl_type_b,
+ { "OB Type of module", "s7comm.ob.mdl_type_b", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_mdl_type_w,
+ { "OB Module type with point fault", "s7comm.ob.mdl_type_w", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_rack_num,
+ { "OB Number of rack that has module with point fault", "s7comm.ob.rack_num", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_racks_flt,
+ { "OB Racks in fault", "s7comm.ob.racks_flt", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_strtup,
+ { "OB Method of startup", "s7comm.ob.strtup", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_stop,
+ { "OB Event that caused CPU to stop", "s7comm.ob.stop", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_strt_info,
+ { "OB Information on how system started", "s7comm.ob.strt_info", FT_UINT32, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_sw_flt,
+ { "OB Software programming fault", "s7comm.ob.sw_flt", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_blk_type,
+ { "OB Type of block fault occured in", "s7comm.ob.blk_type", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_flt_reg,
+ { "OB Specific register that caused fault", "s7comm.ob.flt_reg", FT_UINT16, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_flt_blk_num,
+ { "OB Number of block that programming fault occured in", "s7comm.ob.flt_blk_num", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_prg_addr,
+ { "OB Address in block where programming fault occured", "s7comm.ob.prg_addr", FT_UINT16, BASE_DEC, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_mem_area,
+ { "OB Memory area where access error occured", "s7comm.ob.mem_area", FT_UINT8, BASE_HEX, NULL, 0x0,
+ NULL, HFILL }},
+ { &hf_s7comm_ob_mem_addr,
+ { "OB Memory address where access error occured", "s7comm.ob.mem_addr", FT_UINT16, BASE_HEX, NULL, 0x0,
NULL, HFILL }},
{ &hf_s7comm_diagdata_req_block_type,
- { "Block type", "s7comm.diagdata.req.blocktype", FT_UINT8, BASE_DEC, VALS(subblktype_names), 0x0,
+ { "Block type", "s7comm.diagdata.req.blocktype", FT_UINT16, BASE_DEC, VALS(subblktype_names), 0x0,
NULL, HFILL }},
{ &hf_s7comm_diagdata_req_block_num,
{ "Block number", "s7comm.diagdata.req.blocknumber", FT_UINT16, BASE_DEC, NULL, 0x0,
@@ -5917,12 +7395,6 @@ proto_register_s7comm (void)
{ &hf_s7comm_diagdata_req_saz,
{ "Step address counter (SAZ)", "s7comm.diagdata.req.saz", FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL }},
- { &hf_s7comm_diagdata_req_number_of_lines,
- { "Number of lines", "s7comm.diagdata.req.number_of_lines", FT_UINT8, BASE_DEC, NULL, 0x0,
- NULL, HFILL }},
- { &hf_s7comm_diagdata_req_line_address,
- { "Address", "s7comm.diagdata.req.line_address", FT_UINT16, BASE_DEC, NULL, 0x0,
- NULL, HFILL }},
/* Flags for requested registers in diagnostic data telegrams */
{ &hf_s7comm_diagdata_registerflag,
@@ -6297,12 +7769,6 @@ proto_register_s7comm (void)
NULL, HFILL }},
/* Variable status */
- { &hf_s7comm_varstat_data_type,
- { "Type of data", "s7comm.varstat.data_type", FT_UINT8, BASE_DEC, VALS(userdata_prog_vartab_type_names), 0x0,
- NULL, HFILL }},
- { &hf_s7comm_varstat_byte_count,
- { "Byte count", "s7comm.varstat.byte_count", FT_UINT16, BASE_DEC, NULL, 0x0,
- NULL, HFILL }},
{ &hf_s7comm_varstat_unknown,
{ "Unknown byte(s) varstat", "s7comm.varstat.unknown", FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL }},
@@ -6629,6 +8095,8 @@ proto_register_s7comm (void)
&ett_s7comm_piservice_parameterblock,
&ett_s7comm_data_blockcontrol_status,
&ett_s7comm_plcfilename,
+ &ett_s7comm_prog_parameter,
+ &ett_s7comm_prog_data,
&ett_s7comm_fragments,
&ett_s7comm_fragment,
};