For proto_tree_add_item(..., proto_xxx, ...)use ENC_NA as the encoding arg.
[obnox/wireshark/wip.git] / epan / dissectors / packet-slimp3.c
index 89071840eb9f8a5a5a87084e2380a341bc43f694..41052074641e5f4a6bbb39afe86729bbae39d98f 100644 (file)
@@ -8,8 +8,8 @@
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
 
 #include <glib.h>
 #include <string.h>
+#include <ctype.h>
 #include <epan/packet.h>
 
+#include "isprint.h"
+
 static int proto_slimp3 = -1;
 static int hf_slimp3_opcode = -1;
 static int hf_slimp3_ir = -1;
@@ -50,8 +53,6 @@ static int hf_slimp3_data_ack = -1;
 
 static gint ett_slimp3 = -1;
 
-static dissector_handle_t slimp3_handle;
-
 #define UDP_PORT_SLIMP3_V1    1069
 #define UDP_PORT_SLIMP3_V2    3483
 
@@ -219,36 +220,47 @@ static const value_string slimp3_mpg_control[] = {
     { 0, NULL }
 };
 
-static void
+#define MAX_LCD_STR_LEN 128
+static int
 dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-    proto_tree *slimp3_tree = NULL;
-    proto_item *ti = NULL;
+    const char         *opcode_str;
+    proto_tree         *slimp3_tree = NULL;
+    proto_item         *ti = NULL, *hidden_item;
     gint               i1;
     gint               offset = 0;
     guint16            opcode;
-    char addc_str[101];
-    char *addc_strp;
+    guchar             lcd_char;
+    char               lcd_str[MAX_LCD_STR_LEN + 1];
     int                        to_server = FALSE;
     int                        old_protocol = FALSE;
     address            tmp_addr;
-
-    if (check_col(pinfo->cinfo, COL_PROTOCOL))
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "SliMP3");
-
+    gboolean           in_str;
+    int                        lcd_strlen;
+
+    /*
+     * If it doesn't begin with a known opcode, reject it, so that
+     * traffic that happens to be do or from one of our ports
+     * doesn't get misidentified as SliMP3 traffic.
+     */
+    if (!tvb_bytes_exist(tvb, offset, 1))
+       return 0;       /* not even an opcode */
     opcode = tvb_get_guint8(tvb, offset);
+    opcode_str = match_strval(opcode, slimp3_opcode_vals);
+    if (opcode_str == NULL)
+       return 0;
+
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SliMP3");
 
     if (check_col(pinfo->cinfo, COL_INFO)) {
 
-       col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
-                    val_to_str(opcode, slimp3_opcode_vals, "Unknown (%c)"));
+       col_add_str(pinfo->cinfo, COL_INFO, opcode_str);
 
     }
 
-    addc_strp = addc_str;
     if (tree) {
 
-       ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, FALSE);
+       ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, ENC_NA);
        slimp3_tree = proto_item_add_subtree(ti, ett_slimp3);
 
        proto_tree_add_uint(slimp3_tree, hf_slimp3_opcode, tvb,
@@ -294,7 +306,8 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        * [12..17]   reserved
        */
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
 
            i1 = tvb_get_ntohl(tvb, offset+2);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 4, "Uptime: %u sec (%u ticks)",
@@ -345,44 +358,43 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     case SLIMP3_DISPLAY:
        if (tree) {
-           gboolean in_str;
-           int str_len;
 
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_display,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_display,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
 
            /* Loop through the commands */
            i1 = 18;
            in_str = FALSE;
-           str_len = 0;
+           lcd_strlen = 0;
            while (i1 < tvb_reported_length_remaining(tvb, offset)) {
                switch(tvb_get_guint8(tvb, offset + i1)) {
                case 0:
                    in_str = FALSE;
-                   str_len = 0;
+                   lcd_strlen = 0;
                    proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                        "Delay (%d ms)", tvb_get_guint8(tvb, offset + i1 + 1));
                    i1 += 2;
                    break;
                case 3:
+                   lcd_char = tvb_get_guint8(tvb, offset + i1 + 1);
+                   if (!isprint(lcd_char)) lcd_char = '.';
                    if (ti && in_str) {
-                       str_len += 2;
-                       proto_item_append_text(ti, "%c",
-                                              tvb_get_guint8(tvb, offset + i1 + 1));
-                       proto_item_set_len(ti, str_len);
+                       lcd_strlen += 2;
+                       proto_item_append_text(ti, "%c", lcd_char);
+                       proto_item_set_len(ti, lcd_strlen);
                    } else {
                        ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
-                                                "String: %c",
-                                                tvb_get_guint8(tvb, offset + i1 + 1));
+                                                "String: %c", lcd_char);
                        in_str = TRUE;
-                       str_len = 2;
+                       lcd_strlen = 2;
                    }
                    i1 += 2;
                    break;
 
                case 2:
                    in_str = FALSE;
-                   str_len = 0;
+                   lcd_strlen = 0;
                    ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                             "Command: %s",
                                             val_to_str(tvb_get_guint8(tvb, offset + i1 + 1),
@@ -411,16 +423,17 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        if (check_col(pinfo->cinfo, COL_INFO)) {
            i1 = 18;
-           addc_strp = addc_str;
-           while (tvb_offset_exists(tvb, offset + i1)) {
+           lcd_strlen = 0;
+           while (tvb_offset_exists(tvb, offset + i1) &&
+                   lcd_strlen < MAX_LCD_STR_LEN) {
                switch (tvb_get_guint8(tvb, offset + i1)) {
 
                case 0:
-                   *addc_strp++ = '.';
+                   lcd_str[lcd_strlen++] = '.';
                    break;
 
                case 2:
-                   *addc_strp++ = '|';
+                   lcd_str[lcd_strlen++] = '|';
                    if (tvb_offset_exists(tvb, offset + i1 + 1) &&
                          (tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30)
                        i1 += 2;
@@ -428,25 +441,28 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
                case 3:
                    if (tvb_offset_exists(tvb, offset + i1 + 1)) {
-                       if (addc_strp == addc_str ||
-                             *(addc_strp-1) != ' ' ||
-                             tvb_get_guint8(tvb, offset + i1 + 1) != ' ')
-                           *addc_strp++ = tvb_get_guint8(tvb, offset + i1 + 1);
+                       if (lcd_strlen < 1 ||
+                             lcd_str[lcd_strlen-1] != ' ' ||
+                             tvb_get_guint8(tvb, offset + i1 + 1) != ' ') {
+                           lcd_char = tvb_get_guint8(tvb, offset + i1 + 1);
+                           lcd_str[lcd_strlen++] = isprint(lcd_char) ? lcd_char : '.';
+                       }
                    }
                }
                i1 += 2;
            }
-           *addc_strp = 0;
-           if (addc_strp - addc_str > 0)
-               col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", addc_str);
+           lcd_str[lcd_strlen] = '\0';
+           if (lcd_strlen > 0)
+               col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", lcd_str);
        }
 
        break;
 
     case SLIMP3_CONTROL:
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_control,
-                                      tvb, offset+1, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_control,
+                                      tvb, offset+1, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
                                val_to_str(tvb_get_guint8(tvb, offset+1),
                                           slimp3_stream_control, "Unknown (0x%0x)"));
@@ -461,8 +477,9 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     case SLIMP3_HELLO:
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_hello,
-                                      tvb, offset+1, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_hello,
+                                      tvb, offset+1, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (to_server) {
                guint8 fw_ver = 0;
                /* Hello response; client->server */
@@ -481,8 +498,9 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     case SLIMP3_I2C:
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_i2c,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_i2c,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (to_server) {
                /* Hello response; client->server */
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
@@ -496,17 +514,18 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        if (check_col(pinfo->cinfo, COL_INFO)) {
            if (to_server) {
-               col_append_fstr(pinfo->cinfo, COL_INFO, ", Response");
+               col_append_str(pinfo->cinfo, COL_INFO, ", Response");
            } else {
-               col_append_fstr(pinfo->cinfo, COL_INFO, ", Request");
+               col_append_str(pinfo->cinfo, COL_INFO, ", Request");
            }
        }
        break;
 
     case SLIMP3_DATA_REQ:
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_data_request,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data_request,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
                                "Requested offset: %d bytes.",
                                tvb_get_ntohs(tvb, offset+2)*2);
@@ -530,11 +549,12 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        *  [18..]    MPEG data
        */
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_data,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (old_protocol) {
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
-                                   "Length: %d bytes", 
+                                   "Length: %d bytes",
                                    tvb_reported_length_remaining(tvb, offset+18));
                proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
                                    "Buffer offset: %d bytes.",
@@ -545,7 +565,7 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                    val_to_str(tvb_get_guint8(tvb, offset+1),
                                               slimp3_mpg_control, "Unknown (0x%0x)"));
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
-                                   "Length: %d bytes", 
+                                   "Length: %d bytes",
                                    tvb_reported_length_remaining(tvb, offset+18));
                proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
                                    "Write Pointer: %d",
@@ -558,13 +578,13 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        if (check_col(pinfo->cinfo, COL_INFO)) {
            if (old_protocol) {
-               col_append_fstr(pinfo->cinfo, COL_INFO, 
+               col_append_fstr(pinfo->cinfo, COL_INFO,
                                ", Length: %d bytes, Offset: %d bytes.",
                                tvb_reported_length_remaining(tvb, offset+18),
                                tvb_get_ntohs(tvb, offset+2) * 2);
            }
            else {
-               col_append_fstr(pinfo->cinfo, COL_INFO, 
+               col_append_fstr(pinfo->cinfo, COL_INFO,
                                ", %s, %d bytes at %d, Sequence: %d",
                                val_to_str(tvb_get_guint8(tvb, offset+1),
                                           slimp3_mpg_control, "Unknown (0x%0x)"),
@@ -578,8 +598,9 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     case SLIMP3_DISC_REQ:
        if (tree) {
            guint8 fw_ver;
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_discover_request,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_discover_request,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+1, 1,
                                "Device ID: %d.", tvb_get_guint8(tvb, offset+1));
            fw_ver = tvb_get_guint8(tvb, offset+2);
@@ -596,18 +617,19 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     case SLIMP3_DISC_RSP:
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_discover_response,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_discover_response,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 4,
                                "Server Address: %s.",
-                               ip_to_str(tvb_get_ptr(tvb, offset+2, 4)));
+                               tvb_ip_to_str(tvb, offset+2));
            proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
                                "Server Port: %d", tvb_get_ntohs(tvb, offset + 6));
        }
 
        if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Server Address: %s. Server Port: %d",
-                           ip_to_str(tvb_get_ptr(tvb, offset+2, 4)),
+                           tvb_ip_to_str(tvb, offset+2),
                            tvb_get_ntohs(tvb, offset + 6));
        }
        break;
@@ -616,15 +638,16 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        /* Acknowledge MPEG data
        *
        *  [0]       'a'
-       *  [1..5]    
+       *  [1..5]
        *  [6..7]    Write pointer (in words)
        *  [8..9]    Read pointer (in words)
        *  [10..11]  Sequence number
        *  [12..17]  client MAC address (v1.3 and later)
        */
        if (tree) {
-           proto_tree_add_item_hidden(slimp3_tree, hf_slimp3_data_ack,
-                                      tvb, offset, 1, FALSE);
+           hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data_ack,
+                                      tvb, offset, 1, ENC_BIG_ENDIAN);
+           PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
                                "Write Pointer: %d",
                                tvb_get_ntohs(tvb, offset+6) * 2);
@@ -649,6 +672,7 @@ dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        break;
 
     }
+    return tvb_length(tvb);
 }
 
 void
@@ -667,47 +691,47 @@ proto_register_slimp3(void)
 
     { &hf_slimp3_control,
       { "Control Packet",   "slimp3.control",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 control", HFILL }},
 
     { &hf_slimp3_display,
       { "Display",                   "slimp3.display",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 display", HFILL }},
 
     { &hf_slimp3_hello,
       { "Hello",                     "slimp3.hello",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 hello", HFILL }},
 
     { &hf_slimp3_i2c,
       { "I2C",               "slimp3.i2c",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 I2C", HFILL }},
 
     { &hf_slimp3_data,
       { "Data",              "slimp3.data",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 Data", HFILL }},
 
     { &hf_slimp3_data_request,
       { "Data Request",      "slimp3.data_req",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 Data Request", HFILL }},
 
     { &hf_slimp3_discover_request,
       { "Discovery Request", "slimp3.discovery_req",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 Discovery Request", HFILL }},
 
     { &hf_slimp3_discover_response,
       { "Discovery Response", "slimp3.discovery_response",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 Discovery Response", HFILL }},
 
     { &hf_slimp3_data_ack,
       { "Data Ack",      "slimp3.data_ack",
-       FT_BOOLEAN, BASE_DEC, NULL, 0x0,
+       FT_BOOLEAN, BASE_NONE, NULL, 0x0,
        "SLIMP3 Data Ack", HFILL }},
 
   };
@@ -719,13 +743,14 @@ proto_register_slimp3(void)
                                       "SliMP3", "slimp3");
   proto_register_field_array(proto_slimp3, hf, array_length(hf));
   proto_register_subtree_array(ett, array_length(ett));
-
-  slimp3_handle = create_dissector_handle(dissect_slimp3, proto_slimp3);
 }
 
 void
 proto_reg_handoff_slimp3(void)
 {
-  dissector_add("udp.port", UDP_PORT_SLIMP3_V1, slimp3_handle);
-  dissector_add("udp.port", UDP_PORT_SLIMP3_V2, slimp3_handle);
+  dissector_handle_t slimp3_handle;
+
+  slimp3_handle = new_create_dissector_handle(dissect_slimp3, proto_slimp3);
+  dissector_add_uint("udp.port", UDP_PORT_SLIMP3_V1, slimp3_handle);
+  dissector_add_uint("udp.port", UDP_PORT_SLIMP3_V2, slimp3_handle);
 }