2 * Routines for Bluetooth HID dissection
4 * Copyright 2012, Michal Labedzki for Tieto Corporation
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.
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31 #include <epan/expert.h>
33 #include "packet-btl2cap.h"
34 #include "packet-btsdp.h"
36 static int proto_bthid
= -1;
37 static int hf_bthid_transaction_type
= -1;
38 static int hf_bthid_parameter_reserved
= -1;
39 static int hf_bthid_parameter_reserved_31
= -1;
40 static int hf_bthid_parameter_reserved_32
= -1;
41 static int hf_bthid_parameter_reserved_2
= -1;
42 static int hf_bthid_parameter_result_code
= -1;
43 static int hf_bthid_parameter_control_operation
= -1;
44 static int hf_bthid_parameter_size
= -1;
45 static int hf_bthid_protocol
= -1;
46 static int hf_bthid_idle_rate
= -1;
47 static int hf_bthid_parameter_report_type
= -1;
48 static int hf_bthid_report_id
= -1;
49 static int hf_bthid_buffer_size
= -1;
50 static int hf_bthid_protocol_code
= -1;
51 static int hf_bthid_data_keyboard_modifier_right_gui
= -1;
52 static int hf_bthid_data_keyboard_modifier_right_alt
= -1;
53 static int hf_bthid_data_keyboard_modifier_right_shift
= -1;
54 static int hf_bthid_data_keyboard_modifier_right_ctrl
= -1;
55 static int hf_bthid_data_keyboard_modifier_left_gui
= -1;
56 static int hf_bthid_data_keyboard_modifier_left_alt
= -1;
57 static int hf_bthid_data_keyboard_modifier_left_shift
= -1;
58 static int hf_bthid_data_keyboard_modifier_left_ctrl
= -1;
59 static int hf_bthid_data_keyboard_reserved
= -1;
60 static int hf_bthid_data_keyboard_keycode_1
= -1;
61 static int hf_bthid_data_keyboard_keycode_2
= -1;
62 static int hf_bthid_data_keyboard_keycode_3
= -1;
63 static int hf_bthid_data_keyboard_keycode_4
= -1;
64 static int hf_bthid_data_keyboard_keycode_5
= -1;
65 static int hf_bthid_data_keyboard_keycode_6
= -1;
66 static int hf_bthid_data_keyboard_leds_constants
= -1;
67 static int hf_bthid_data_keyboard_leds_kana
= -1;
68 static int hf_bthid_data_keyboard_leds_compose
= -1;
69 static int hf_bthid_data_keyboard_leds_scroll_lock
= -1;
70 static int hf_bthid_data_keyboard_leds_caps_lock
= -1;
71 static int hf_bthid_data_keyboard_leds_num_lock
= -1;
72 static int hf_bthid_data_mouse_button_8
= -1;
73 static int hf_bthid_data_mouse_button_7
= -1;
74 static int hf_bthid_data_mouse_button_6
= -1;
75 static int hf_bthid_data_mouse_button_5
= -1;
76 static int hf_bthid_data_mouse_button_4
= -1;
77 static int hf_bthid_data_mouse_button_middle
= -1;
78 static int hf_bthid_data_mouse_button_right
= -1;
79 static int hf_bthid_data_mouse_button_left
= -1;
80 static int hf_bthid_data_mouse_x_displacement
= -1;
81 static int hf_bthid_data_mouse_y_displacement
= -1;
82 static int hf_bthid_data_mouse_horizontal_scroll_wheel
= -1;
83 static int hf_bthid_data_mouse_vertical_scroll_wheel
= -1;
85 static int hf_bthid_data
= -1;
87 static gint ett_bthid
= -1;
89 static expert_field ei_bthid_parameter_control_operation_deprecated
= EI_INIT
;
90 static expert_field ei_bthid_transaction_type_deprecated
= EI_INIT
;
92 static gboolean show_deprecated
= FALSE
;
94 static const value_string transaction_type_vals
[] = {
95 { 0x00, "HANDSHAKE" },
96 { 0x01, "HID_CONTROL" },
99 { 0x04, "GET_REPORT" },
100 { 0x05, "SET_REPORT" },
101 { 0x06, "GET_PROTOCOL" },
102 { 0x07, "SET_PROTOCOL" },
103 { 0x08, "GET_IDLE" },
104 { 0x09, "SET_IDLE" },
107 { 0x0C, "reserved" },
108 { 0x0D, "reserved" },
109 { 0x0E, "reserved" },
110 { 0x0F, "reserved" },
114 static const value_string report_type_vals
[] = {
122 static const value_string result_code_vals
[] = {
123 { 0x00, "Successful" },
124 { 0x01, "Not Ready" },
125 { 0x02, "Error, Invalid Report ID" },
126 { 0x03, "Error, Unsupported Request" },
127 { 0x04, "Error, Invalid Parameters" },
128 { 0x0E, "Error, Unknown " },
129 { 0x0F, "Error, Fatal " },
133 static const value_string control_operation_vals
[] = {
135 { 0x01, "Hard Reset" },
136 { 0x02, "Soft Reset" },
138 { 0x04, "Exit Suspend" },
139 { 0x05, "Virtual Cable Unplug" },
143 static const value_string size_vals
[] = {
144 { 0x00, "Buffer equal to report size" },
145 { 0x01, "BufferSize field follows the Report ID" },
149 static const value_string protocol_vals
[] = {
155 static const value_string protocol_code_vals
[] = {
157 { 0x01, "Keyboard" },
162 static const value_string keycode_vals
[] = {
163 { 0x00, "<ACTION KEY UP>" },
164 { 0x01, "ErrorRollOver" },
165 { 0x02, "POSTFail" },
166 { 0x03, "ErrorUndefined" },
208 { 0x2A, "Backspace" },
210 { 0x2C, "Spacebar" },
217 { 0x32, "NonUS #/~" },
224 { 0x39, "CapsLock" },
237 { 0x46, "PrintScreen" },
238 { 0x47, "ScrollLock" },
243 { 0x4C, "DeleteForward" },
245 { 0x4E, "PageDown" },
246 { 0x4F, "RightArrow" },
247 { 0x50, "LeftArrow" },
248 { 0x51, "DownArrow" },
253 { 0x54, "Keypad /" },
254 { 0x55, "Keypad *" },
255 { 0x56, "Keypad -" },
256 { 0x57, "Keypad +" },
257 { 0x58, "Keypad ENTER" },
258 { 0x59, "Keypad 1" },
259 { 0x5A, "Keypad 2" },
260 { 0x5B, "Keypad 3" },
261 { 0x5C, "Keypad 4" },
262 { 0x5D, "Keypad 5" },
263 { 0x5E, "Keypad 6" },
264 { 0x5F, "Keypad 7" },
265 { 0x60, "Keypad 8" },
266 { 0x61, "Keypad 9" },
267 { 0x62, "Keypad 0" },
268 { 0x63, "Keypad ." },
271 { 0x64, "NonUS \\/|" },
272 { 0x65, "Application" },
274 { 0x67, "Keypad =" },
301 { 0x80, "VolumeUp" },
302 { 0x81, "VolumeDown" },
303 { 0x82, "Locking CapsLock" },
304 { 0x83, "Locking NumLock" },
305 { 0x84, "Locking ScrollLock" },
306 { 0x85, "Keypad Comma" },
307 { 0x86, "Keypad EqualSign" },
308 { 0x87, "International1" },
309 { 0x88, "International2" },
310 { 0x89, "International3" },
311 { 0x8A, "International4" },
312 { 0x8B, "International5" },
313 { 0x8C, "International6" },
314 { 0x8D, "International7" },
315 { 0x8E, "International8" },
316 { 0x8F, "International9" },
327 { 0x99, "AlternateErase" },
328 { 0x9A, "SysReq/Attention" },
333 { 0x9F, "Separator" },
337 { 0xA2, "Clear/Again" },
338 { 0xA3, "CrSel/Props" },
340 /* 0xA5..0xAF - reserved */
341 { 0xB0, "Keypad 00" },
342 { 0xB1, "Keypad 000" },
343 { 0xB2, "ThousandsSeparator" },
344 { 0xB3, "DecimalSeparator" },
345 { 0xB4, "CurrencyUnit" },
346 { 0xB5, "CurrencySubunit" },
347 { 0xB6, "Keypad (" },
348 { 0xB7, "Keypad )" },
349 { 0xB8, "Keypad {" },
350 { 0xB9, "Keypad }" },
351 { 0xBA, "Keypad Tab" },
352 { 0xBB, "Keypad Backspace" },
353 { 0xBC, "Keypad A" },
354 { 0xBD, "Keypad B" },
355 { 0xBE, "Keypad C" },
356 { 0xBF, "Keypad D" },
358 { 0xC0, "Keypad E" },
359 { 0xC1, "Keypad F" },
360 { 0xC2, "Keypad XOR" },
361 { 0xC3, "Keypad ^" },
362 { 0xC4, "Keypad %" },
363 { 0xC5, "Keypad <" },
364 { 0xC6, "Keypad >" },
365 { 0xC7, "Keypad &" },
366 { 0xC8, "Keypad &&" },
367 { 0xC9, "Keypad |" },
368 { 0xCA, "Keypad ||" },
369 { 0xCB, "Keypad :" },
370 { 0xCC, "Keypad #" },
371 { 0xCD, "Keypad Space" },
372 { 0xCE, "Keypad @" },
373 { 0xCF, "Keypad !" },
375 { 0xD0, "Keypad Memory Store" },
376 { 0xD1, "Keypad Memory Recall" },
377 { 0xD2, "Keypad Memory Clear" },
378 { 0xD3, "Keypad Memory Add" },
379 { 0xD4, "Keypad Memory Subtract" },
380 { 0xD5, "Keypad Memory Multiply" },
381 { 0xD6, "Keypad Memory Divide" },
382 { 0xD7, "Keypad +/-" },
383 { 0xD8, "Keypad Clear" },
384 { 0xD9, "Keypad Clear Entry" },
385 { 0xDA, "Keypad Binary" },
386 { 0xDB, "Keypad Octal" },
387 { 0xDC, "Keypad Decimal" },
388 { 0xDD, "Keypad Hexadecimal" },
389 /* 0xDE..0xDF - reserved, */
390 { 0xE0, "LeftControl" },
391 { 0xE1, "LeftShift" },
394 { 0xE4, "RightControl" },
395 { 0xE5, "RightShift" },
396 { 0xE6, "RightAlt" },
397 { 0xE7, "RightGUI" },
402 value_string_ext keycode_vals_ext
= VALUE_STRING_EXT_INIT(keycode_vals
);
404 void proto_register_bthid(void);
405 void proto_reg_handoff_bthid(void);
408 dissect_hid_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
409 gint offset
, guint report_type
)
411 gboolean shortcut_helper
= FALSE
;
412 unsigned int protocol_code
;
413 unsigned int modifier
;
414 unsigned int keycode
;
416 unsigned int buttons
;
418 proto_tree_add_item(tree
, hf_bthid_protocol_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
419 protocol_code
= tvb_get_guint8(tvb
, offset
);
420 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - %s", val_to_str_const(protocol_code
, protocol_code_vals
, "unknown type"));
423 switch (protocol_code
) {
424 case 0x01: /* Keyboard */
425 if (report_type
== 0x02) { /* Output - LEDs */
426 proto_tree_add_item(tree
, hf_bthid_data_keyboard_leds_constants
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
427 proto_tree_add_item(tree
, hf_bthid_data_keyboard_leds_kana
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
428 proto_tree_add_item(tree
, hf_bthid_data_keyboard_leds_compose
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
429 proto_tree_add_item(tree
, hf_bthid_data_keyboard_leds_scroll_lock
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
430 proto_tree_add_item(tree
, hf_bthid_data_keyboard_leds_caps_lock
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
431 proto_tree_add_item(tree
, hf_bthid_data_keyboard_leds_num_lock
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
432 leds
= tvb_get_guint8(tvb
, offset
);
434 col_append_str(pinfo
->cinfo
, COL_INFO
, " - LEDs: ");
436 col_append_str(pinfo
->cinfo
, COL_INFO
, "NumLock");
437 shortcut_helper
= TRUE
;
440 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
441 col_append_str(pinfo
->cinfo
, COL_INFO
, "CapsLock");
442 shortcut_helper
= TRUE
;
445 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
446 col_append_str(pinfo
->cinfo
, COL_INFO
, "ScrollLock");
447 shortcut_helper
= TRUE
;
450 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
451 col_append_str(pinfo
->cinfo
, COL_INFO
, "Compose");
452 shortcut_helper
= TRUE
;
455 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
456 col_append_str(pinfo
->cinfo
, COL_INFO
, "Kana");
457 shortcut_helper
= TRUE
;
460 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
461 col_append_str(pinfo
->cinfo
, COL_INFO
, "Constant1");
462 shortcut_helper
= TRUE
;
465 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
466 col_append_str(pinfo
->cinfo
, COL_INFO
, "Constant2");
467 shortcut_helper
= TRUE
;
470 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, ", ");
471 col_append_str(pinfo
->cinfo
, COL_INFO
, "Constant3");
472 /*shortcut_helper = TRUE;*/
475 col_append_str(pinfo
->cinfo
, COL_INFO
, "none");
480 } else if (report_type
!= 0x01) {/* is not Input (Keys) */
484 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_right_gui
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
485 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_right_alt
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
486 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_right_shift
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
487 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_right_ctrl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
488 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_left_gui
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
489 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_left_alt
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
490 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_left_shift
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
491 proto_tree_add_item(tree
, hf_bthid_data_keyboard_modifier_left_ctrl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
492 modifier
= tvb_get_guint8(tvb
, offset
);
494 col_append_str(pinfo
->cinfo
, COL_INFO
, " - ");
495 if (modifier
& 0x80) {
496 col_append_str(pinfo
->cinfo
, COL_INFO
, "RIGHT GUI");
497 shortcut_helper
= TRUE
;
499 if (modifier
& 0x40) {
500 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
501 col_append_str(pinfo
->cinfo
, COL_INFO
, "RIGHT ALT");
502 shortcut_helper
= TRUE
;
504 if (modifier
& 0x20) {
505 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
506 col_append_str(pinfo
->cinfo
, COL_INFO
, "RIGHT SHIFT");
507 shortcut_helper
= TRUE
;
509 if (modifier
& 0x10) {
510 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
511 col_append_str(pinfo
->cinfo
, COL_INFO
, "RIGHT CTRL");
512 shortcut_helper
= TRUE
;
514 if (modifier
& 0x08) {
515 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
516 col_append_str(pinfo
->cinfo
, COL_INFO
, "LEFT GUI");
517 shortcut_helper
= TRUE
;
519 if (modifier
& 0x04) {
520 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
521 col_append_str(pinfo
->cinfo
, COL_INFO
, "LEFT ALT");
522 shortcut_helper
= TRUE
;
524 if (modifier
& 0x02) {
525 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
526 col_append_str(pinfo
->cinfo
, COL_INFO
, "LEFT SHIFT");
527 shortcut_helper
= TRUE
;
529 if (modifier
& 0x01) {
530 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
531 col_append_str(pinfo
->cinfo
, COL_INFO
, "LEFT CTRL");
532 shortcut_helper
= TRUE
;
536 proto_tree_add_item(tree
, hf_bthid_data_keyboard_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
539 proto_tree_add_item(tree
, hf_bthid_data_keyboard_keycode_1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
540 keycode
= tvb_get_guint8(tvb
, offset
);
544 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
545 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", val_to_str_ext(keycode
, &keycode_vals_ext
, "Unknown"));
546 shortcut_helper
= TRUE
;
549 proto_tree_add_item(tree
, hf_bthid_data_keyboard_keycode_2
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
550 keycode
= tvb_get_guint8(tvb
, offset
);
554 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
555 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", val_to_str_ext(keycode
, &keycode_vals_ext
, "Unknown"));
556 shortcut_helper
= TRUE
;
559 proto_tree_add_item(tree
, hf_bthid_data_keyboard_keycode_3
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
560 keycode
= tvb_get_guint8(tvb
, offset
);
564 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
565 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", val_to_str_ext(keycode
, &keycode_vals_ext
, "Unknown"));
566 shortcut_helper
= TRUE
;
569 proto_tree_add_item(tree
, hf_bthid_data_keyboard_keycode_4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
570 keycode
= tvb_get_guint8(tvb
, offset
);
574 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
575 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", val_to_str_ext(keycode
, &keycode_vals_ext
, "Unknown"));
576 shortcut_helper
= TRUE
;
579 proto_tree_add_item(tree
, hf_bthid_data_keyboard_keycode_5
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
580 keycode
= tvb_get_guint8(tvb
, offset
);
584 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
585 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", val_to_str_ext(keycode
, &keycode_vals_ext
, "Unknown"));
586 shortcut_helper
= TRUE
;
589 proto_tree_add_item(tree
, hf_bthid_data_keyboard_keycode_6
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
590 keycode
= tvb_get_guint8(tvb
, offset
);
594 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
595 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s", val_to_str_ext(keycode
, &keycode_vals_ext
, "Unknown"));
596 shortcut_helper
= TRUE
;
599 if (shortcut_helper
== FALSE
) {
600 col_append_str(pinfo
->cinfo
, COL_INFO
, "<action key up>");
604 case 0x02: /* Mouse */
605 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
606 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_7
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
607 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_6
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
608 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_5
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
609 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
610 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_middle
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
611 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_right
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
612 proto_tree_add_item(tree
, hf_bthid_data_mouse_button_left
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
613 buttons
= tvb_get_guint8(tvb
, offset
);
616 if (buttons
) col_append_str(pinfo
->cinfo
, COL_INFO
, " - ");
617 if (buttons
& 0x01) {
618 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button LEFT");
619 shortcut_helper
= TRUE
;
621 if (buttons
& 0x02) {
622 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
623 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button RIGHT");
624 shortcut_helper
= TRUE
;
626 if (buttons
& 0x04) {
627 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
628 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button MIDDLE");
630 if (buttons
& 0x08) {
631 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
632 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button 4");
633 shortcut_helper
= TRUE
;
635 if (buttons
& 0x10) {
636 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
637 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button 5");
638 shortcut_helper
= TRUE
;
640 if (buttons
& 0x20) {
641 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
642 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button 6");
643 shortcut_helper
= TRUE
;
645 if (buttons
& 0x40) {
646 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
647 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button 7");
648 shortcut_helper
= TRUE
;
650 if (buttons
& 0x80) {
651 if (shortcut_helper
) col_append_str(pinfo
->cinfo
, COL_INFO
, " + ");
652 col_append_str(pinfo
->cinfo
, COL_INFO
, "Button 8");
653 /* Not necessary, this is the last case where it is used
654 * shortcut_helper = TRUE;
658 proto_tree_add_item(tree
, hf_bthid_data_mouse_x_displacement
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
661 proto_tree_add_item(tree
, hf_bthid_data_mouse_y_displacement
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
664 /* not really in HID Specification */
665 if (tvb_length_remaining(tvb
, offset
)) {
666 proto_tree_add_item(tree
, hf_bthid_data_mouse_horizontal_scroll_wheel
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
670 /* not really in HID Specification */
671 if (tvb_length_remaining(tvb
, offset
)) {
672 proto_tree_add_item(tree
, hf_bthid_data_mouse_vertical_scroll_wheel
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
676 if (tvb_length_remaining(tvb
, offset
)) {
677 proto_tree_add_item(tree
, hf_bthid_data
, tvb
, offset
, -1, ENC_NA
);
678 offset
+= tvb_length_remaining(tvb
, offset
);
687 dissect_bthid(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
690 proto_tree
*bthid_tree
;
692 guint transaction_type
;
696 guint8 control_operation
;
699 ti
= proto_tree_add_item(tree
, proto_bthid
, tvb
, offset
, -1, ENC_NA
);
700 bthid_tree
= proto_item_add_subtree(ti
, ett_bthid
);
702 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "HID");
703 col_clear(pinfo
->cinfo
, COL_INFO
);
705 switch (pinfo
->p2p_dir
) {
707 col_set_str(pinfo
->cinfo
, COL_INFO
, "Sent ");
710 col_set_str(pinfo
->cinfo
, COL_INFO
, "Rcvd ");
713 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Unknown direction %d ",
718 pitem
= proto_tree_add_item(bthid_tree
, hf_bthid_transaction_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
719 transaction_type
= tvb_get_guint8(tvb
, offset
);
720 parameter
= transaction_type
& 0x0F;
721 transaction_type
= transaction_type
>> 4;
723 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(transaction_type
, transaction_type_vals
, "Unknown TransactionType"));
725 switch(transaction_type
) {
726 case 0x00: /* HANDSHAKE */
727 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_result_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
729 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Result Code: %s", val_to_str_const(parameter
, result_code_vals
, "reserved"));
731 case 0x01: /* HID_CONTROL */
732 pitem
= proto_tree_add_item(bthid_tree
, hf_bthid_parameter_control_operation
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
733 control_operation
= tvb_get_guint8(tvb
, offset
);
734 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Control Operation: %s", val_to_str_const(parameter
, control_operation_vals
, "reserved"));
735 if (control_operation
< 3 && show_deprecated
)
736 expert_add_info(pinfo
, pitem
, &ei_bthid_parameter_control_operation_deprecated
);
739 case 0x04: /* GET_REPORT */
740 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
741 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_reserved_2
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
742 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_report_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
744 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Size: %s, Report Type: %s",
745 val_to_str_const(parameter
>> 3 , size_vals
, "reserved"),
746 val_to_str_const(parameter
& 0x03, report_type_vals
, "reserved"));
748 /* XXX: This is workaround, this should come from SDP:
749 "This field is required in Report Protocol Mode when any Report ID
750 Global Items are declared in the report descriptor, and in
751 Boot Protocol Mode. Otherwise the field does not exist."
753 if (((parameter
>> 3) && tvb_length_remaining(tvb
, offset
) >= 3) ||
754 (!(parameter
>> 3) && tvb_length_remaining(tvb
, offset
) >= 1)) {
755 proto_tree_add_item(bthid_tree
, hf_bthid_report_id
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
759 if (parameter
>> 3) {
760 proto_tree_add_item(bthid_tree
, hf_bthid_buffer_size
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
764 case 0x05: /* SET_REPORT */
765 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_reserved_32
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
766 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_report_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
769 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Report Type: %s",
770 val_to_str_const(parameter
& 0x03, report_type_vals
, "reserved"));
773 proto_tree_add_item(bthid_tree
, hf_bthid_data
, tvb
, offset
, -1, ENC_NA
);
774 offset
+= tvb_length_remaining(tvb
, offset
);
776 case 0x06: /* GET_PROTOCOL */
777 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
780 proto_tree_add_item(bthid_tree
, hf_bthid_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
781 protocol
= tvb_get_guint8(tvb
, offset
) & 0x01;
784 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Protocol: %s",
785 val_to_str_const(protocol
, protocol_vals
, "reserved"));
788 case 0x07: /* SET_PROTOCOL */
789 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_reserved_31
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
790 proto_tree_add_item(bthid_tree
, hf_bthid_protocol
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
793 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Protocol: %s",
794 val_to_str_const(parameter
& 0x01, protocol_vals
, "reserved"));
796 case 0x08: /* GET_IDLE */
797 case 0x09: /* SET_IDLE */
799 expert_add_info(pinfo
, pitem
, &ei_bthid_transaction_type_deprecated
);
801 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
804 pitem
= proto_tree_add_item(bthid_tree
, hf_bthid_idle_rate
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
805 idle_rate
= tvb_get_guint8(tvb
, offset
);
806 proto_item_append_text(pitem
, " (%u.%03u ms)", idle_rate
* 4 / 1000, idle_rate
* 4 % 1000);
807 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - Idle Rate: %u.%03u ms", idle_rate
*4/1000, idle_rate
*4%1000);
810 case 0x0B: /* DATC */
812 expert_add_info(pinfo
, pitem
, &ei_bthid_transaction_type_deprecated
);
813 case 0x0A: /* DATA */
814 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_reserved_32
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
815 proto_tree_add_item(bthid_tree
, hf_bthid_parameter_report_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
817 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " - %s", val_to_str_const(parameter
, report_type_vals
, "reserved"));
820 offset
= dissect_hid_data(tvb
, pinfo
, bthid_tree
, offset
, parameter
& 0x03);
829 proto_register_bthid(void)
832 expert_module_t
* expert_bthid
;
834 static hf_register_info hf
[] = {
835 { &hf_bthid_transaction_type
,
836 { "Transaction Type", "bthid.transaction_type",
837 FT_UINT8
, BASE_HEX
, VALS(transaction_type_vals
), 0xF0,
840 { &hf_bthid_parameter_reserved
,
841 { "Parameter reserved", "bthid.parameter.reserved",
842 FT_UINT8
, BASE_HEX
, NULL
, 0x0F,
845 { &hf_bthid_parameter_reserved_32
,
846 { "Parameter reserved", "bthid.parameter.reserved_32",
847 FT_UINT8
, BASE_HEX
, NULL
, 0x0C,
850 { &hf_bthid_parameter_reserved_31
,
851 { "Parameter reserved", "bthid.parameter.reserved_31",
852 FT_UINT8
, BASE_HEX
, NULL
, 0x0E,
855 { &hf_bthid_parameter_reserved_2
,
856 { "Parameter reserved", "bthid.parameter.reserved_2",
857 FT_UINT8
, BASE_HEX
, NULL
, 0x04,
860 { &hf_bthid_parameter_report_type
,
861 { "Report Type", "bthid.parameter.report_type",
862 FT_UINT8
, BASE_HEX
, VALS(report_type_vals
), 0x03,
865 { &hf_bthid_parameter_size
,
866 { "Size", "bthid.parameter.size",
867 FT_UINT8
, BASE_HEX
, VALS(size_vals
), 0x08,
870 { &hf_bthid_parameter_result_code
,
871 { "Result Code", "bthid.result_code",
872 FT_UINT8
, BASE_HEX
, VALS(result_code_vals
), 0x0F,
875 { &hf_bthid_parameter_control_operation
,
876 { "Control Operation", "bthid.control_operation",
877 FT_UINT8
, BASE_HEX
, VALS(control_operation_vals
), 0x0F,
880 { &hf_bthid_protocol
,
881 { "Protocol", "bthid.protocol",
882 FT_UINT8
, BASE_HEX
, VALS(protocol_vals
), 0x01,
885 { &hf_bthid_idle_rate
,
886 { "Idle Rate", "bthid.idle_rate",
887 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
890 { &hf_bthid_report_id
,
891 { "Report Id", "bthid.report_id",
892 FT_UINT8
, BASE_HEX
, VALS(protocol_code_vals
), 0x00,
895 { &hf_bthid_buffer_size
,
896 { "Buffer Size", "bthid.buffer_size",
897 FT_UINT16
, BASE_HEX
, NULL
, 0x00,
900 { &hf_bthid_protocol_code
,
901 { "Protocol Code", "bthid.data.protocol_code",
902 FT_UINT8
, BASE_HEX
, VALS(protocol_code_vals
), 0x00,
905 { &hf_bthid_data_keyboard_reserved
,
906 { "Reserved", "bthid.data.keyboard.reserved",
907 FT_UINT8
, BASE_HEX
, NULL
, 0x00,
910 { &hf_bthid_data_keyboard_keycode_1
,
911 { "Keycode 1", "bthid.data.keyboard.keycode_1",
912 FT_UINT8
, BASE_HEX
|BASE_EXT_STRING
, &keycode_vals_ext
, 0x00,
915 { &hf_bthid_data_keyboard_keycode_2
,
916 { "Keycode 2", "bthid.data.keyboard.keycode_2",
917 FT_UINT8
, BASE_HEX
|BASE_EXT_STRING
, &keycode_vals_ext
, 0x00,
920 { &hf_bthid_data_keyboard_keycode_3
,
921 { "Keycode 3", "bthid.data.keyboard.keycode_3",
922 FT_UINT8
, BASE_HEX
|BASE_EXT_STRING
, &keycode_vals_ext
, 0x00,
925 { &hf_bthid_data_keyboard_keycode_4
,
926 { "Keycode 4", "bthid.data.keyboard.keycode_4",
927 FT_UINT8
, BASE_HEX
|BASE_EXT_STRING
, &keycode_vals_ext
, 0x00,
930 { &hf_bthid_data_keyboard_keycode_5
,
931 { "Keycode 5", "bthid.data.keyboard.keycode_5",
932 FT_UINT8
, BASE_HEX
|BASE_EXT_STRING
, &keycode_vals_ext
, 0x00,
935 { &hf_bthid_data_keyboard_keycode_6
,
936 { "Keycode 6", "bthid.data.keyboard.keycode_6",
937 FT_UINT8
, BASE_HEX
|BASE_EXT_STRING
, &keycode_vals_ext
, 0x00,
940 { &hf_bthid_data_keyboard_modifier_right_gui
,
941 { "Modifier: RIGHT GUI", "bthid.data.keyboard.modifier.right_gui",
942 FT_BOOLEAN
, 8, NULL
, 0x80,
945 { &hf_bthid_data_keyboard_modifier_right_alt
,
946 { "Modifier: RIGHT ALT", "bthid.data.keyboard.modifier.right_alt",
947 FT_BOOLEAN
, 8, NULL
, 0x40,
950 { &hf_bthid_data_keyboard_modifier_right_shift
,
951 { "Modifier: RIGHT SHIFT", "bthid.data.keyboard.modifier.right_shift",
952 FT_BOOLEAN
, 8, NULL
, 0x20,
955 { &hf_bthid_data_keyboard_modifier_right_ctrl
,
956 { "Modifier: RIGHT CTRL", "bthid.data.keyboard.modifier.right_ctrl",
957 FT_BOOLEAN
, 8, NULL
, 0x10,
960 { &hf_bthid_data_keyboard_modifier_left_gui
,
961 { "Modifier: LEFT GUI", "bthid.data.keyboard.modifier.left_gui",
962 FT_BOOLEAN
, 8, NULL
, 0x08,
965 { &hf_bthid_data_keyboard_modifier_left_alt
,
966 { "Modifier: LEFT ALT", "bthid.data.keyboard.modifier.left_alt",
967 FT_BOOLEAN
, 8, NULL
, 0x04,
970 { &hf_bthid_data_keyboard_modifier_left_shift
,
971 { "Modifier: LEFT SHIFT", "bthid.data.keyboard.modifier.left_shift",
972 FT_BOOLEAN
, 8, NULL
, 0x02,
975 { &hf_bthid_data_keyboard_modifier_left_ctrl
,
976 { "Modifier: LEFT CTRL", "bthid.data.keyboard.modifier.left_ctrl",
977 FT_BOOLEAN
, 8, NULL
, 0x01,
980 { &hf_bthid_data_keyboard_leds_constants
,
981 { "Constants", "bthid.data.keyboard.leds.constants",
982 FT_UINT8
, BASE_HEX
, NULL
, 0xE0,
985 { &hf_bthid_data_keyboard_leds_kana
,
986 { "KANA", "bthid.data.keyboard.leds.kana",
987 FT_BOOLEAN
, 8, NULL
, 0x10,
990 { &hf_bthid_data_keyboard_leds_compose
,
991 { "COMPOSE", "bthid.data.keyboard.leds.compose",
992 FT_BOOLEAN
, 8, NULL
, 0x08,
995 { &hf_bthid_data_keyboard_leds_scroll_lock
,
996 { "SCROLL LOCK", "bthid.data.keyboard.leds.scroll_lock",
997 FT_BOOLEAN
, 8, NULL
, 0x04,
1000 { &hf_bthid_data_keyboard_leds_caps_lock
,
1001 { "CAPS LOCK", "bthid.data.keyboard.leds.caps_lock",
1002 FT_BOOLEAN
, 8, NULL
, 0x02,
1005 { &hf_bthid_data_keyboard_leds_num_lock
,
1006 { "NUM LOCK", "bthid.data.keyboard.leds.num_lock",
1007 FT_BOOLEAN
, 8, NULL
, 0x01,
1010 { &hf_bthid_data_mouse_button_8
,
1011 { "Button 8", "bthid.data.mouse.button.8",
1012 FT_BOOLEAN
, 8, NULL
, 0x80,
1015 { &hf_bthid_data_mouse_button_7
,
1016 { "Button 7", "bthid.data.mouse.button.7",
1017 FT_BOOLEAN
, 8, NULL
, 0x40,
1020 { &hf_bthid_data_mouse_button_6
,
1021 { "Button 6", "bthid.data.mouse.button.6",
1022 FT_BOOLEAN
, 8, NULL
, 0x20,
1025 { &hf_bthid_data_mouse_button_5
,
1026 { "Button 5", "bthid.data.mouse.button.5",
1027 FT_BOOLEAN
, 8, NULL
, 0x10,
1030 { &hf_bthid_data_mouse_button_4
,
1031 { "Button 4", "bthid.data.mouse.button.4",
1032 FT_BOOLEAN
, 8, NULL
, 0x08,
1035 { &hf_bthid_data_mouse_button_middle
,
1036 { "Button Middle", "bthid.data.mouse.button.middle",
1037 FT_BOOLEAN
, 8, NULL
, 0x04,
1040 { &hf_bthid_data_mouse_button_right
,
1041 { "Button Right", "bthid.data.mouse.button.right",
1042 FT_BOOLEAN
, 8, NULL
, 0x02,
1045 { &hf_bthid_data_mouse_button_left
,
1046 { "Button Left", "bthid.data.mouse.button.left",
1047 FT_BOOLEAN
, 8, NULL
, 0x01,
1050 { &hf_bthid_data_mouse_x_displacement
,
1051 { "X Displacement", "bthid.data.mouse.x_displacement",
1052 FT_INT8
, BASE_DEC
, NULL
, 0x00,
1055 { &hf_bthid_data_mouse_y_displacement
,
1056 { "Y Displacement", "bthid.data.mouse.y_displacement",
1057 FT_INT8
, BASE_DEC
, NULL
, 0x00,
1060 { &hf_bthid_data_mouse_horizontal_scroll_wheel
,
1061 { "Horizontal Scroll Wheel", "bthid.data.mouse.scroll_wheel.horizontal",
1062 FT_INT8
, BASE_DEC
, NULL
, 0x00,
1065 { &hf_bthid_data_mouse_vertical_scroll_wheel
,
1066 { "Vertical Scroll Wheel", "bthid.data.mouse.scroll_wheel.vertical",
1067 FT_INT8
, BASE_DEC
, NULL
, 0x00,
1071 { "Data", "bthid.data",
1072 FT_NONE
, BASE_NONE
, NULL
, 0x00,
1078 static gint
*ett
[] = {
1082 static ei_register_info ei
[] = {
1083 { &ei_bthid_parameter_control_operation_deprecated
, { "bthid.control_operation.deprecated", PI_PROTOCOL
, PI_WARN
, "This value of Control Operation is deprecated by HID 1.1", EXPFILL
}},
1084 { &ei_bthid_transaction_type_deprecated
, { "bthid.transaction_type.deprecated", PI_PROTOCOL
, PI_WARN
, "This Transaction Type is deprecated by HID 1.1", EXPFILL
}},
1087 proto_bthid
= proto_register_protocol("Bluetooth HID Profile", "BT HID", "bthid");
1088 new_register_dissector("bthid", dissect_bthid
, proto_bthid
);
1090 proto_register_field_array(proto_bthid
, hf
, array_length(hf
));
1091 proto_register_subtree_array(ett
, array_length(ett
));
1092 expert_bthid
= expert_register_protocol(proto_bthid
);
1093 expert_register_field_array(expert_bthid
, ei
, array_length(ei
));
1095 module
= prefs_register_protocol(proto_bthid
, NULL
);
1096 prefs_register_static_text_preference(module
, "hid.version",
1097 "Bluetooth Profile HID version: 1.1",
1098 "Version of profile supported by this dissector.");
1100 prefs_register_bool_preference(module
, "hid.deprecated",
1101 "Show what is deprecated in HID 1.1",
1102 "Show what is deprecated in HID 1.1", &show_deprecated
);
1107 proto_reg_handoff_bthid(void)
1109 dissector_handle_t bthid_handle
;
1111 bthid_handle
= find_dissector("bthid");
1113 dissector_add_uint("btl2cap.service", BTSDP_HID_SERVICE_UUID
, bthid_handle
);
1114 dissector_add_uint("btl2cap.service", BTSDP_HIDP_PROTOCOL_UUID
, bthid_handle
);
1116 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_HID_CTRL
, bthid_handle
);
1117 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_HID_INTR
, bthid_handle
);
1118 dissector_add_handle("btl2cap.cid", bthid_handle
);
1122 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1127 * indent-tabs-mode: nil
1130 * vi: set shiftwidth=4 tabstop=8 expandtab:
1131 * :indentSize=4:tabSize=8:noTabs=true: