HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-tfp.c
blobe8b50d85c844f8dcd3dce5a2f4164a44fe264313
1 /* packet-tfp.c
2 * Routines for Tinkerforge protocol packet disassembly
3 * By Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
4 * Copyright 2013 Ishraq Ibne Ashraf
6 * $Id$
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.
27 #include "config.h"
29 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/dissectors/packet-usb.h>
33 /* defines */
34 #define tfp_PORT 4223
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 */
77 static void
78 base58_encode(guint32 value, char *str) {
80 guint32 mod;
81 gint i = 0;
82 gint k;
83 gchar reverse_str[BASE58_MAX_STR_SIZE] = {'\0'};
85 while (value >= 58) {
86 mod = value % 58;
87 reverse_str[i] = BASE58_ALPHABET[mod];
88 value = value / 58;
89 ++i;
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++) {
99 str[k] = '\0';
103 /* common dissector function for dissecting TFP payloads */
104 static void
105 dissect_tfp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
107 gint byte_offset = 0;
108 gint bit_offset = 48;
110 guint8 hv_tfp_len;
111 guint8 hv_tfp_fid;
112 guint8 hv_tfp_seq;
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 */
127 if (tree) {
128 proto_tree *tfp_tree;
129 proto_item *ti;
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,
139 hf_tfp_uid,
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,
145 hf_tfp_uid_numeric,
146 tvb,
147 byte_offset,
148 byte_count_tfp_uid,
149 ENC_LITTLE_ENDIAN);
151 byte_offset += byte_count_tfp_uid;
153 proto_tree_add_item(tfp_tree,
154 hf_tfp_len,
155 tvb,
156 byte_offset,
157 byte_count_tfp_len,
158 ENC_LITTLE_ENDIAN);
160 byte_offset += byte_count_tfp_len;
162 proto_tree_add_item(tfp_tree,
163 hf_tfp_fid,
164 tvb,
165 byte_offset,
166 byte_count_tfp_fid,
167 ENC_LITTLE_ENDIAN);
169 byte_offset += byte_count_tfp_fid;
171 proto_tree_add_bits_item(tfp_tree,
172 hf_tfp_seq,
173 tvb,
174 bit_offset,
175 bit_count_tfp_seq,
176 ENC_LITTLE_ENDIAN);
178 bit_offset += bit_count_tfp_seq;
180 proto_tree_add_bits_item(tfp_tree,
181 hf_tfp_r,
182 tvb,
183 bit_offset,
184 bit_count_tfp_r,
185 ENC_LITTLE_ENDIAN);
187 bit_offset += bit_count_tfp_r;
189 proto_tree_add_bits_item(tfp_tree,
190 hf_tfp_a,
191 tvb,
192 bit_offset,
193 bit_count_tfp_a,
194 ENC_LITTLE_ENDIAN);
196 bit_offset += bit_count_tfp_a;
198 proto_tree_add_bits_item(tfp_tree,
199 hf_tfp_oo,
200 tvb,
201 bit_offset,
202 bit_count_tfp_oo,
203 ENC_LITTLE_ENDIAN);
205 bit_offset += bit_count_tfp_oo;
207 proto_tree_add_bits_item(tfp_tree,
208 hf_tfp_e,
209 tvb,
210 bit_offset,
211 bit_count_tfp_e,
212 ENC_LITTLE_ENDIAN);
214 bit_offset += bit_count_tfp_e;
216 proto_tree_add_bits_item(tfp_tree,
217 hf_tfp_future_use,
218 tvb,
219 bit_offset,
220 bit_count_tfp_future_use,
221 ENC_LITTLE_ENDIAN);
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 */
235 static void
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 */
245 static gboolean
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);
256 return TRUE;
259 return FALSE;
262 /* protocol register function */
263 void
264 proto_register_tfp(void)
266 /* defining header formats */
267 static hf_register_info hf_tfp[] = {
268 { &hf_tfp_uid,
269 { "UID (String)",
270 "tfp.uid",
271 FT_STRINGZ,
272 BASE_NONE,
273 NULL,
274 0x0,
275 NULL,
276 HFILL
279 { &hf_tfp_uid_numeric,
280 { "UID (Numeric)",
281 "tfp.uid_numeric",
282 FT_UINT32,
283 BASE_DEC,
284 NULL,
285 0x0,
286 NULL,
287 HFILL
290 { &hf_tfp_len,
291 { "Length",
292 "tfp.len",
293 FT_UINT8,
294 BASE_DEC,
295 NULL,
296 0x0,
297 NULL,
298 HFILL
301 { &hf_tfp_fid,
302 { "Function ID",
303 "tfp.fid",
304 FT_UINT8,
305 BASE_DEC,
306 NULL,
307 0x0,
308 NULL,
309 HFILL
312 { &hf_tfp_seq,
313 { "Sequence Number",
314 "tfp.seq",
315 FT_UINT8,
316 BASE_DEC,
317 NULL,
318 0x0,
319 NULL,
320 HFILL
323 { &hf_tfp_r,
324 { "Response Expected",
325 "tfp.r",
326 FT_UINT8,
327 BASE_DEC,
328 NULL,
329 0x0,
330 NULL,
331 HFILL
334 { &hf_tfp_a,
335 { "Authentication",
336 "tfp.a",
337 FT_UINT8,
338 BASE_DEC,
339 NULL,
340 0x0,
341 NULL,
342 HFILL
345 { &hf_tfp_oo,
346 { "Other Options",
347 "tfp.oo",
348 FT_UINT8,
349 BASE_DEC,
350 NULL,
351 0x0,
352 NULL,
353 HFILL
356 { &hf_tfp_e,
357 { "Error Code",
358 "tfp.e",
359 FT_UINT8,
360 BASE_DEC,
361 NULL,
362 0x0,
363 NULL,
364 HFILL
367 { &hf_tfp_future_use,
368 { "Future Use",
369 "tfp.future_use",
370 FT_UINT8,
371 BASE_DEC,
372 NULL,
373 0x0,
374 NULL,
375 HFILL
378 { &hf_tfp_payload,
379 { "Payload",
380 "tfp.payload",
381 FT_BYTES,
382 BASE_NONE,
383 NULL,
384 0x0,
385 NULL,
386 HFILL
391 /* setup protocol subtree array */
392 static gint *ett[] = {
393 &ett_tfp
396 /* defining the protocol and its names */
397 proto_tfp = proto_register_protocol (
398 "Tinkerforge Protocol",
399 "TFP",
400 "tfp"
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 */
408 void
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
422 * Local variables:
423 * c-basic-offset: 8
424 * tab-width: 8
425 * indent-tabs-mode: t
426 * End:
428 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
429 * :indentSize=8:tabSize=8:noTabs=false: