2 * Routines for Tinkerforge protocol packet disassembly
3 * By Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
4 * Copyright 2013 Ishraq Ibne Ashraf
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/dissectors/packet-usb.h>
36 #define tfp_USB_VENDOR_ID 0x16D0
37 #define tfp_USB_PRODUCT_ID 0x063D
39 #define BASE58_MAX_STR_SIZE 13
41 /* variables for creating the tree */
42 static gint proto_tfp
= -1;
43 static gint ett_tfp
= -1;
45 /* header field variables */
46 static gint hf_tfp_uid
= -1;
47 static gint hf_tfp_uid_numeric
= -1;
48 static gint hf_tfp_len
= -1;
49 static gint hf_tfp_fid
= -1;
50 static gint hf_tfp_seq
= -1;
51 static gint hf_tfp_r
= -1;
52 static gint hf_tfp_a
= -1;
53 static gint hf_tfp_oo
= -1;
54 static gint hf_tfp_e
= -1;
55 static gint hf_tfp_future_use
= -1;
56 static gint hf_tfp_payload
= -1;
58 /* bit and byte offsets for dissection */
59 static const gint byte_offset_len
= 4;
60 static const gint byte_offset_fid
= 5;
61 static const gint byte_count_tfp_uid
= 4;
62 static const gint byte_count_tfp_len
= 1;
63 static const gint byte_count_tfp_fid
= 1;
64 static const gint byte_count_tfp_flags
= 2;
65 static const gint bit_count_tfp_seq
= 4;
66 static const gint bit_count_tfp_r
= 1;
67 static const gint bit_count_tfp_a
= 1;
68 static const gint bit_count_tfp_oo
= 2;
69 static const gint bit_count_tfp_e
= 2;
70 static const gint bit_count_tfp_future_use
= 6;
72 /* base58 encoding variable */
73 static const char BASE58_ALPHABET
[] =
74 "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
76 /* function for encoding a number to base58 string */
78 base58_encode(guint32 value
, char *str
) {
83 gchar reverse_str
[BASE58_MAX_STR_SIZE
] = {'\0'};
87 reverse_str
[i
] = BASE58_ALPHABET
[mod
];
92 reverse_str
[i
] = BASE58_ALPHABET
[value
];
94 for (k
= 0; k
<= i
; k
++) {
95 str
[k
] = reverse_str
[i
- k
];
98 for (; k
< BASE58_MAX_STR_SIZE
; k
++) {
103 /* common dissector function for dissecting TFP payloads */
105 dissect_tfp_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
107 gint byte_offset
= 0;
108 gint bit_offset
= 48;
114 gchar tfp_uid_string
[BASE58_MAX_STR_SIZE
];
116 base58_encode(tvb_get_letohl(tvb
, 0), &tfp_uid_string
[0]);
118 hv_tfp_len
= tvb_get_guint8(tvb
, byte_offset_len
);
119 hv_tfp_fid
= tvb_get_guint8(tvb
, byte_offset_fid
);
120 hv_tfp_seq
= tvb_get_bits8(tvb
, bit_offset
, bit_count_tfp_seq
);
122 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
123 "UID: %s, Len: %d, FID: %d, Seq: %d",
124 &tfp_uid_string
[0], hv_tfp_len
, hv_tfp_fid
, hv_tfp_seq
);
126 /* call for details */
128 proto_tree
*tfp_tree
;
131 ti
= proto_tree_add_protocol_format(tree
, proto_tfp
, tvb
, 0, -1,
132 "Tinkerforge Protocol, UID: %s, Len: %d, FID: %d, Seq: %d",
133 &tfp_uid_string
[0], hv_tfp_len
, hv_tfp_fid
, hv_tfp_seq
);
134 tfp_tree
= proto_item_add_subtree(ti
, ett_tfp
);
136 /* Use ...string_format_value() so we can show the complete generated string but specify */
137 /* the field length as being just the 4 bytes from which the string is generated. */
138 ti
= proto_tree_add_string_format_value(tfp_tree
,
140 tvb
, byte_offset
, byte_count_tfp_uid
,
141 &tfp_uid_string
[0], "%s", &tfp_uid_string
[0]);
142 PROTO_ITEM_SET_GENERATED(ti
);
144 proto_tree_add_item(tfp_tree
,
151 byte_offset
+= byte_count_tfp_uid
;
153 proto_tree_add_item(tfp_tree
,
160 byte_offset
+= byte_count_tfp_len
;
162 proto_tree_add_item(tfp_tree
,
169 byte_offset
+= byte_count_tfp_fid
;
171 proto_tree_add_bits_item(tfp_tree
,
178 bit_offset
+= bit_count_tfp_seq
;
180 proto_tree_add_bits_item(tfp_tree
,
187 bit_offset
+= bit_count_tfp_r
;
189 proto_tree_add_bits_item(tfp_tree
,
196 bit_offset
+= bit_count_tfp_a
;
198 proto_tree_add_bits_item(tfp_tree
,
205 bit_offset
+= bit_count_tfp_oo
;
207 proto_tree_add_bits_item(tfp_tree
,
214 bit_offset
+= bit_count_tfp_e
;
216 proto_tree_add_bits_item(tfp_tree
,
220 bit_count_tfp_future_use
,
223 /*bit_offset += bit_count_tfp_future_use;*/
225 if ((tvb_reported_length(tvb
)) > 8) {
227 byte_offset
+= byte_count_tfp_flags
;
229 proto_tree_add_item(tfp_tree
, hf_tfp_payload
, tvb
, byte_offset
, -1, ENC_NA
);
234 /* dissector function for dissecting TCP payloads */
236 dissect_tfp_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
238 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TFP over TCP");
239 col_clear(pinfo
->cinfo
, COL_INFO
);
241 dissect_tfp_common(tvb
, pinfo
, tree
);
244 /* dissector function for dissecting USB payloads */
246 dissect_tfp_bulk_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
248 usb_conv_info_t
*usb_conv_info
= (usb_conv_info_t
*)data
;
250 if ((usb_conv_info
!= NULL
) &&
251 (usb_conv_info
->deviceVendor
== tfp_USB_VENDOR_ID
) &&
252 (usb_conv_info
->deviceProduct
== tfp_USB_PRODUCT_ID
)) {
253 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TFP over USB");
254 col_clear(pinfo
->cinfo
, COL_INFO
);
255 dissect_tfp_common(tvb
, pinfo
, tree
);
262 /* protocol register function */
264 proto_register_tfp(void)
266 /* defining header formats */
267 static hf_register_info hf_tfp
[] = {
279 { &hf_tfp_uid_numeric
,
324 { "Response Expected",
367 { &hf_tfp_future_use
,
391 /* setup protocol subtree array */
392 static gint
*ett
[] = {
396 /* defining the protocol and its names */
397 proto_tfp
= proto_register_protocol (
398 "Tinkerforge Protocol",
403 proto_register_field_array(proto_tfp
, hf_tfp
, array_length(hf_tfp
));
404 proto_register_subtree_array(ett
, array_length(ett
));
407 /* handoff function */
409 proto_reg_handoff_tfp(void) {
411 dissector_handle_t tfp_handle_tcp
;
413 tfp_handle_tcp
= create_dissector_handle(dissect_tfp_tcp
, proto_tfp
);
415 dissector_add_uint("tcp.port", tfp_PORT
, tfp_handle_tcp
);
416 heur_dissector_add("usb.bulk", dissect_tfp_bulk_heur
, proto_tfp
);
420 * Editor modelines - http://www.wireshark.org/tools/modelines.html
425 * indent-tabs-mode: t
428 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
429 * :indentSize=8:tabSize=8:noTabs=false: