2 * Routines for Tinkerforge protocol packet disassembly
3 * By Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
4 * Copyright 2013 Ishraq Ibne Ashraf
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/packet.h>
29 #include <epan/dissectors/packet-usb.h>
34 #define tfp_USB_VENDOR_ID 0x16D0
35 #define tfp_USB_PRODUCT_ID 0x063D
37 #define BASE58_MAX_STR_SIZE 13
39 void proto_reg_handoff_tfp(void);
40 void proto_register_tfp(void);
42 /* variables for creating the tree */
43 static gint proto_tfp = -1;
44 static gint ett_tfp = -1;
46 /* header field variables */
47 static gint hf_tfp_uid = -1;
48 static gint hf_tfp_uid_numeric = -1;
49 static gint hf_tfp_len = -1;
50 static gint hf_tfp_fid = -1;
51 static gint hf_tfp_seq = -1;
52 static gint hf_tfp_r = -1;
53 static gint hf_tfp_a = -1;
54 static gint hf_tfp_oo = -1;
55 static gint hf_tfp_e = -1;
56 static gint hf_tfp_future_use = -1;
57 static gint hf_tfp_payload = -1;
59 /* bit and byte offsets for dissection */
60 static const gint byte_offset_len = 4;
61 static const gint byte_offset_fid = 5;
62 static const gint byte_count_tfp_uid = 4;
63 static const gint byte_count_tfp_len = 1;
64 static const gint byte_count_tfp_fid = 1;
65 static const gint byte_count_tfp_flags = 2;
66 static const gint bit_count_tfp_seq = 4;
67 static const gint bit_count_tfp_r = 1;
68 static const gint bit_count_tfp_a = 1;
69 static const gint bit_count_tfp_oo = 2;
70 static const gint bit_count_tfp_e = 2;
71 static const gint bit_count_tfp_future_use = 6;
73 /* base58 encoding variable */
74 static const char BASE58_ALPHABET[] =
75 "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
77 /* function for encoding a number to base58 string */
79 base58_encode(guint32 value, char *str) {
84 gchar reverse_str[BASE58_MAX_STR_SIZE] = {'\0'};
88 reverse_str[i] = BASE58_ALPHABET[mod];
93 reverse_str[i] = BASE58_ALPHABET[value];
95 for (k = 0; k <= i; k++) {
96 str[k] = reverse_str[i - k];
99 for (; k < BASE58_MAX_STR_SIZE; k++) {
104 /* common dissector function for dissecting TFP payloads */
106 dissect_tfp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
108 gint byte_offset = 0;
109 gint bit_offset = 48;
115 gchar tfp_uid_string[BASE58_MAX_STR_SIZE];
117 base58_encode(tvb_get_letohl(tvb, 0), &tfp_uid_string[0]);
119 hv_tfp_len = tvb_get_guint8(tvb, byte_offset_len);
120 hv_tfp_fid = tvb_get_guint8(tvb, byte_offset_fid);
121 hv_tfp_seq = tvb_get_bits8(tvb, bit_offset, bit_count_tfp_seq);
123 col_add_fstr(pinfo->cinfo, COL_INFO,
124 "UID: %s, Len: %d, FID: %d, Seq: %d",
125 &tfp_uid_string[0], hv_tfp_len, hv_tfp_fid, hv_tfp_seq);
127 /* call for details */
129 proto_tree *tfp_tree;
132 ti = proto_tree_add_protocol_format(tree, proto_tfp, tvb, 0, -1,
133 "Tinkerforge Protocol, UID: %s, Len: %d, FID: %d, Seq: %d",
134 &tfp_uid_string[0], hv_tfp_len, hv_tfp_fid, hv_tfp_seq);
135 tfp_tree = proto_item_add_subtree(ti, ett_tfp);
137 /* Use ...string_format_value() so we can show the complete generated string but specify */
138 /* the field length as being just the 4 bytes from which the string is generated. */
139 ti = proto_tree_add_string_format_value(tfp_tree,
141 tvb, byte_offset, byte_count_tfp_uid,
142 &tfp_uid_string[0], "%s", &tfp_uid_string[0]);
143 PROTO_ITEM_SET_GENERATED(ti);
145 proto_tree_add_item(tfp_tree,
152 byte_offset += byte_count_tfp_uid;
154 proto_tree_add_item(tfp_tree,
161 byte_offset += byte_count_tfp_len;
163 proto_tree_add_item(tfp_tree,
170 byte_offset += byte_count_tfp_fid;
172 proto_tree_add_bits_item(tfp_tree,
179 bit_offset += bit_count_tfp_seq;
181 proto_tree_add_bits_item(tfp_tree,
188 bit_offset += bit_count_tfp_r;
190 proto_tree_add_bits_item(tfp_tree,
197 bit_offset += bit_count_tfp_a;
199 proto_tree_add_bits_item(tfp_tree,
206 bit_offset += bit_count_tfp_oo;
208 proto_tree_add_bits_item(tfp_tree,
215 bit_offset += bit_count_tfp_e;
217 proto_tree_add_bits_item(tfp_tree,
221 bit_count_tfp_future_use,
224 /*bit_offset += bit_count_tfp_future_use;*/
226 if ((tvb_reported_length(tvb)) > 8) {
228 byte_offset += byte_count_tfp_flags;
230 proto_tree_add_item(tfp_tree, hf_tfp_payload, tvb, byte_offset, -1, ENC_NA);
235 /* dissector function for dissecting TCP payloads */
237 dissect_tfp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
239 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFP over TCP");
240 col_clear(pinfo->cinfo, COL_INFO);
242 dissect_tfp_common(tvb, pinfo, tree);
245 /* dissector function for dissecting USB payloads */
247 dissect_tfp_bulk_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
249 usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data;
251 if ((usb_conv_info != NULL) &&
252 (usb_conv_info->deviceVendor == tfp_USB_VENDOR_ID) &&
253 (usb_conv_info->deviceProduct == tfp_USB_PRODUCT_ID)) {
254 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFP over USB");
255 col_clear(pinfo->cinfo, COL_INFO);
256 dissect_tfp_common(tvb, pinfo, tree);
263 /* protocol register function */
265 proto_register_tfp(void)
267 /* defining header formats */
268 static hf_register_info hf_tfp[] = {
280 { &hf_tfp_uid_numeric,
325 { "Response Expected",
368 { &hf_tfp_future_use,
392 /* setup protocol subtree array */
393 static gint *ett[] = {
397 /* defining the protocol and its names */
398 proto_tfp = proto_register_protocol (
399 "Tinkerforge Protocol",
404 proto_register_field_array(proto_tfp, hf_tfp, array_length(hf_tfp));
405 proto_register_subtree_array(ett, array_length(ett));
408 /* handoff function */
410 proto_reg_handoff_tfp(void) {
412 dissector_handle_t tfp_handle_tcp;
414 tfp_handle_tcp = create_dissector_handle(dissect_tfp_tcp, proto_tfp);
416 dissector_add_uint("tcp.port", tfp_PORT, tfp_handle_tcp);
417 heur_dissector_add("usb.bulk", dissect_tfp_bulk_heur, proto_tfp);
421 * Editor modelines - http://www.wireshark.org/tools/modelines.html
426 * indent-tabs-mode: t
429 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
430 * :indentSize=8:tabSize=8:noTabs=false: