1 /* bluetooth_hci_summary_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "bluetooth_hci_summary_dialog.h"
11 #include <ui_bluetooth_hci_summary_dialog.h>
13 #include "bluetooth_device_dialog.h"
15 #include <ui/qt/utils/color_utils.h>
17 #include "epan/epan.h"
18 #include "epan/addr_resolv.h"
19 #include "epan/to_str.h"
20 #include "epan/epan_dissect.h"
21 #include "epan/prefs.h"
22 #include "epan/dissectors/packet-bluetooth.h"
23 #include "epan/dissectors/packet-bthci_cmd.h"
24 #include "epan/dissectors/packet-bthci_evt.h"
26 #include <ui/qt/utils/variant_pointer.h>
28 #include "ui/simple_dialog.h"
29 #include "ui/qt/widgets/wireshark_file_dialog.h"
32 #include <QContextMenuEvent>
33 #include <QPushButton>
34 #include <QTreeWidget>
36 static const int column_number_name
= 0;
37 static const int column_number_ogf
= 1;
38 static const int column_number_ocf
= 2;
39 static const int column_number_opcode
= 3;
40 static const int column_number_event
= 4;
41 static const int column_number_subevent
= 5;
42 static const int column_number_status
= 6;
43 static const int column_number_reason
= 7;
44 static const int column_number_hardware_error
= 8;
45 static const int column_number_occurrence
= 9;
47 static tap_packet_status
48 bluetooth_hci_summary_tap_packet(void *tapinfo_ptr
, packet_info
*pinfo
, epan_dissect_t
*edt
, const void* data
, tap_flags_t flags
)
50 bluetooth_hci_summary_tapinfo_t
*tapinfo
= (bluetooth_hci_summary_tapinfo_t
*) tapinfo_ptr
;
52 if (tapinfo
->tap_packet
)
53 tapinfo
->tap_packet(tapinfo
, pinfo
, edt
, data
, flags
);
55 return TAP_PACKET_REDRAW
;
59 bluetooth_hci_summary_tap_reset(void *tapinfo_ptr
)
61 bluetooth_hci_summary_tapinfo_t
*tapinfo
= (bluetooth_hci_summary_tapinfo_t
*) tapinfo_ptr
;
63 if (tapinfo
->tap_reset
)
64 tapinfo
->tap_reset(tapinfo
);
68 bluetooth_hci_summary_tap_init(void *data
)
70 GString
*error_string
;
72 error_string
= register_tap_listener("bluetooth.hci_summary", data
, NULL
,
74 bluetooth_hci_summary_tap_reset
,
75 bluetooth_hci_summary_tap_packet
,
80 if (error_string
!= NULL
) {
81 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
82 "%s", error_string
->str
);
83 g_string_free(error_string
, TRUE
);
88 BluetoothHciSummaryDialog::BluetoothHciSummaryDialog(QWidget
&parent
, CaptureFile
&cf
) :
89 WiresharkDialog(parent
, cf
),
90 ui(new Ui::BluetoothHciSummaryDialog
)
93 loadGeometry(parent
.width() * 4 / 5, parent
.height() * 2 / 3);
95 connect(ui
->tableTreeWidget
, SIGNAL(customContextMenuRequested(const QPoint
&)), this, SLOT(tableContextMenu(const QPoint
&)));
96 connect(ui
->tableTreeWidget
, SIGNAL(itemExpanded(QTreeWidgetItem
*)), this, SLOT(tableItemExpanded(QTreeWidgetItem
*)));
97 connect(ui
->tableTreeWidget
, SIGNAL(itemCollapsed(QTreeWidgetItem
*)), this, SLOT(tableItemCollapsed(QTreeWidgetItem
*)));
99 connect(ui
->interfaceComboBox
, SIGNAL(currentIndexChanged(int)), this, SLOT(interfaceCurrentIndexChanged(int)));
100 connect(ui
->adapterComboBox
, SIGNAL(currentIndexChanged(int)), this, SLOT(adapterCurrentIndexChanged(int)));
101 connect(ui
->displayFilterLineEdit
, SIGNAL(returnPressed()), this, SLOT(displayFilterLineEditAccepted()));
102 connect(ui
->resultsFilterLineEdit
, SIGNAL(textChanged(const QString
&)), this, SLOT(resultsFilterLineEditChanged(const QString
&)));
104 for (int i
= 0; i
< ui
->tableTreeWidget
->columnCount(); i
++) {
105 ui
->tableTreeWidget
->resizeColumnToContents(i
);
108 ui
->tableTreeWidget
->setStyleSheet("QTreeView::item:hover{background-color:lightyellow; color:black;}");
110 context_menu_
.addActions(QList
<QAction
*>() << ui
->actionMark_Unmark_Cell
);
111 context_menu_
.addActions(QList
<QAction
*>() << ui
->actionMark_Unmark_Row
);
112 context_menu_
.addActions(QList
<QAction
*>() << ui
->actionCopy_Cell
);
113 context_menu_
.addActions(QList
<QAction
*>() << ui
->actionCopy_Rows
);
114 context_menu_
.addActions(QList
<QAction
*>() << ui
->actionCopy_All
);
115 context_menu_
.addActions(QList
<QAction
*>() << ui
->actionSave_as_image
);
117 tapinfo_
.tap_packet
= tapPacket
;
118 tapinfo_
.tap_reset
= tapReset
;
121 item_link_control_
= ui
->tableTreeWidget
->topLevelItem(0);
122 item_link_policy_
= ui
->tableTreeWidget
->topLevelItem(1);
123 item_controller_and_baseband_
= ui
->tableTreeWidget
->topLevelItem(2);
124 item_informational_
= ui
->tableTreeWidget
->topLevelItem(3);
125 item_status_parameters_
= ui
->tableTreeWidget
->topLevelItem(4);
126 item_testing_
= ui
->tableTreeWidget
->topLevelItem(5);
127 item_low_energy_
= ui
->tableTreeWidget
->topLevelItem(6);
128 item_logo_testing_
= ui
->tableTreeWidget
->topLevelItem(7);
129 item_vendor_
= ui
->tableTreeWidget
->topLevelItem(8);
130 item_unknown_ogf_
= ui
->tableTreeWidget
->topLevelItem(9);
131 item_events_
= ui
->tableTreeWidget
->topLevelItem(10);
132 item_status_
= ui
->tableTreeWidget
->topLevelItem(11);
133 item_reason_
= ui
->tableTreeWidget
->topLevelItem(12);
134 item_hardware_errors_
= ui
->tableTreeWidget
->topLevelItem(13);
136 bluetooth_hci_summary_tap_init(&tapinfo_
);
138 cap_file_
.retapPackets();
142 BluetoothHciSummaryDialog::~BluetoothHciSummaryDialog()
146 remove_tap_listener(&tapinfo_
);
150 void BluetoothHciSummaryDialog::captureFileClosing()
152 remove_tap_listener(&tapinfo_
);
154 WiresharkDialog::captureFileClosing();
158 void BluetoothHciSummaryDialog::captureFileClosed()
160 ui
->interfaceComboBox
->setEnabled(false);
161 ui
->adapterComboBox
->setEnabled(false);
163 WiresharkDialog::captureFileClosed();
167 void BluetoothHciSummaryDialog::changeEvent(QEvent
*event
)
171 switch (event
->type())
173 case QEvent::LanguageChange
:
174 ui
->retranslateUi(this);
180 QDialog::changeEvent(event
);
184 void BluetoothHciSummaryDialog::keyPressEvent(QKeyEvent
*event
)
186 /* NOTE: Do nothing*, but in real it "takes focus" from button_box so allow user
187 * to use Enter button to jump to frame from tree widget */
188 /* * - reimplement shortcuts from context menu */
190 if (event
->modifiers() & Qt::ControlModifier
&& event
->key()== Qt::Key_M
)
191 on_actionMark_Unmark_Row_triggered();
195 void BluetoothHciSummaryDialog::tableContextMenu(const QPoint
&pos
)
197 context_menu_
.popup(ui
->tableTreeWidget
->viewport()->mapToGlobal(pos
));
200 void BluetoothHciSummaryDialog::tableItemExpanded(QTreeWidgetItem
*)
202 for (int i
= 0; i
< ui
->tableTreeWidget
->columnCount(); i
++) {
203 ui
->tableTreeWidget
->resizeColumnToContents(i
);
207 void BluetoothHciSummaryDialog::tableItemCollapsed(QTreeWidgetItem
*)
209 for (int i
= 0; i
< ui
->tableTreeWidget
->columnCount(); i
++) {
210 ui
->tableTreeWidget
->resizeColumnToContents(i
);
214 void BluetoothHciSummaryDialog::on_actionMark_Unmark_Cell_triggered()
219 if (ui
->tableTreeWidget
->currentItem()->background(ui
->tableTreeWidget
->currentColumn()) == QBrush(ColorUtils::fromColorT(&prefs
.gui_marked_bg
))) {
223 fg
= QBrush(ColorUtils::fromColorT(&prefs
.gui_marked_fg
));
224 bg
= QBrush(ColorUtils::fromColorT(&prefs
.gui_marked_bg
));
227 ui
->tableTreeWidget
->currentItem()->setForeground(ui
->tableTreeWidget
->currentColumn(), fg
);
228 ui
->tableTreeWidget
->currentItem()->setBackground(ui
->tableTreeWidget
->currentColumn(), bg
);
231 void BluetoothHciSummaryDialog::on_actionMark_Unmark_Row_triggered()
235 bool is_marked
= true;
237 for (int i
= 0; i
< ui
->tableTreeWidget
->columnCount(); i
+= 1) {
238 if (ui
->tableTreeWidget
->currentItem()->background(i
) != QBrush(ColorUtils::fromColorT(&prefs
.gui_marked_bg
)))
246 fg
= QBrush(ColorUtils::fromColorT(&prefs
.gui_marked_fg
));
247 bg
= QBrush(ColorUtils::fromColorT(&prefs
.gui_marked_bg
));
250 for (int i
= 0; i
< ui
->tableTreeWidget
->columnCount(); i
+= 1) {
251 ui
->tableTreeWidget
->currentItem()->setForeground(i
, fg
);
252 ui
->tableTreeWidget
->currentItem()->setBackground(i
, bg
);
256 void BluetoothHciSummaryDialog::on_actionCopy_Cell_triggered()
258 QClipboard
*clipboard
= QApplication::clipboard();
261 copy
= QString(ui
->tableTreeWidget
->currentItem()->text(ui
->tableTreeWidget
->currentColumn()));
263 clipboard
->setText(copy
);
267 void BluetoothHciSummaryDialog::on_actionCopy_Rows_triggered()
269 QClipboard
*clipboard
= QApplication::clipboard();
271 QList
<QTreeWidgetItem
*> items
;
272 QList
<QTreeWidgetItem
*>::iterator i_item
;
274 items
= ui
->tableTreeWidget
->selectedItems();
276 for (i_item
= items
.begin(); i_item
!= items
.end(); ++i_item
) {
277 copy
+= QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
278 .arg((*i_item
)->text(column_number_name
), -60)
279 .arg((*i_item
)->text(column_number_ogf
), -10)
280 .arg((*i_item
)->text(column_number_ocf
), -10)
281 .arg((*i_item
)->text(column_number_opcode
), -10)
282 .arg((*i_item
)->text(column_number_event
), -10)
283 .arg((*i_item
)->text(column_number_subevent
), -10)
284 .arg((*i_item
)->text(column_number_status
), -10)
285 .arg((*i_item
)->text(column_number_reason
), -10)
286 .arg((*i_item
)->text(column_number_hardware_error
), -15)
287 .arg((*i_item
)->text(column_number_occurrence
), -10);
290 clipboard
->setText(copy
);
293 void BluetoothHciSummaryDialog::tapReset(void *tapinfo_ptr
)
295 bluetooth_hci_summary_tapinfo_t
*tapinfo
= (bluetooth_hci_summary_tapinfo_t
*) tapinfo_ptr
;
296 BluetoothHciSummaryDialog
*dialog
= static_cast<BluetoothHciSummaryDialog
*>(tapinfo
->ui
);
298 dialog
->item_link_control_
->takeChildren();
299 dialog
->item_link_control_
->setText(column_number_occurrence
, "0");
301 dialog
->item_link_policy_
->takeChildren();
302 dialog
->item_link_policy_
->setText(column_number_occurrence
, "0");
304 dialog
->item_controller_and_baseband_
->takeChildren();
305 dialog
->item_controller_and_baseband_
->setText(column_number_occurrence
, "0");
307 dialog
->item_informational_
->takeChildren();
308 dialog
->item_informational_
->setText(column_number_occurrence
, "0");
310 dialog
->item_status_parameters_
->takeChildren();
311 dialog
->item_status_parameters_
->setText(column_number_occurrence
, "0");
313 dialog
->item_testing_
->takeChildren();
314 dialog
->item_testing_
->setText(column_number_occurrence
, "0");
316 dialog
->item_low_energy_
->takeChildren();
317 dialog
->item_low_energy_
->setText(column_number_occurrence
, "0");
319 dialog
->item_logo_testing_
->takeChildren();
320 dialog
->item_logo_testing_
->setText(column_number_occurrence
, "0");
322 dialog
->item_vendor_
->takeChildren();
323 dialog
->item_vendor_
->setText(column_number_occurrence
, "0");
325 dialog
->item_unknown_ogf_
->takeChildren();
326 dialog
->item_unknown_ogf_
->setText(column_number_occurrence
, "0");
328 dialog
->item_events_
->takeChildren();
329 dialog
->item_events_
->setText(column_number_occurrence
, "0");
331 dialog
->item_status_
->takeChildren();
332 dialog
->item_status_
->setText(column_number_occurrence
, "0");
334 dialog
->item_reason_
->takeChildren();
335 dialog
->item_reason_
->setText(column_number_occurrence
, "0");
337 dialog
->item_hardware_errors_
->takeChildren();
338 dialog
->item_hardware_errors_
->setText(column_number_occurrence
, "0");
341 tap_packet_status
BluetoothHciSummaryDialog::tapPacket(void *tapinfo_ptr
, packet_info
*pinfo
, epan_dissect_t
*, const void *data
, tap_flags_t
)
343 bluetooth_hci_summary_tapinfo_t
*tapinfo
= static_cast<bluetooth_hci_summary_tapinfo_t
*>(tapinfo_ptr
);
344 BluetoothHciSummaryDialog
*dialog
= static_cast<BluetoothHciSummaryDialog
*>(tapinfo
->ui
);
345 bluetooth_hci_summary_tap_t
*tap_hci
= static_cast<bluetooth_hci_summary_tap_t
*>(const_cast<void *>(data
));
346 QTreeWidgetItem
*main_item
= NULL
;
347 QTreeWidgetItem
*item
= NULL
;
348 QTreeWidgetItem
*frame_item
= NULL
;
349 QTreeWidgetItem
*meta_item
= NULL
;
350 bluetooth_item_data_t
*item_data
= NULL
;
354 if (dialog
->file_closed_
)
355 return TAP_PACKET_DONT_REDRAW
;
357 if (pinfo
->rec
->rec_type
!= REC_TYPE_PACKET
)
358 return TAP_PACKET_DONT_REDRAW
;
360 name
= tr("Unknown");
362 if (pinfo
->rec
->presence_flags
& WTAP_HAS_INTERFACE_ID
) {
364 const char *interface_name
;
366 unsigned section_number
= pinfo
->rec
->presence_flags
& WTAP_HAS_SECTION_NUMBER
? pinfo
->rec
->section_number
: 0;
367 interface_name
= epan_get_interface_name(pinfo
->epan
, pinfo
->rec
->rec_header
.packet_header
.interface_id
, section_number
);
368 interface
= wmem_strdup_printf(pinfo
->pool
, "%u: %s", pinfo
->rec
->rec_header
.packet_header
.interface_id
, interface_name
);
370 if (dialog
->ui
->interfaceComboBox
->findText(interface
) == -1)
371 dialog
->ui
->interfaceComboBox
->addItem(interface
);
373 if (interface
&& dialog
->ui
->interfaceComboBox
->currentIndex() > 0) {
374 if (dialog
->ui
->interfaceComboBox
->currentText() != interface
)
375 return TAP_PACKET_REDRAW
;
379 adapter
= tr("Adapter %1").arg(tap_hci
->adapter_id
);
381 if (dialog
->ui
->adapterComboBox
->findText(adapter
) == -1) {
382 dialog
->ui
->adapterComboBox
->addItem(adapter
);
385 if (dialog
->ui
->adapterComboBox
->currentIndex() > 0) {
386 if (dialog
->ui
->adapterComboBox
->currentText() != adapter
)
387 return TAP_PACKET_REDRAW
;
390 switch (tap_hci
->type
) {
391 case BLUETOOTH_HCI_SUMMARY_OPCODE
:
392 case BLUETOOTH_HCI_SUMMARY_EVENT_OPCODE
:
393 case BLUETOOTH_HCI_SUMMARY_VENDOR_OPCODE
:
394 case BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT_OPCODE
:
395 switch (tap_hci
->ogf
) {
396 case HCI_OGF_LINK_CONTROL
:
397 main_item
= dialog
->item_link_control_
;
399 case HCI_OGF_LINK_POLICY
:
400 main_item
= dialog
->item_link_policy_
;
402 case HCI_OGF_HOST_CONTROLLER
:
403 main_item
= dialog
->item_controller_and_baseband_
;
405 case HCI_OGF_INFORMATIONAL
:
406 main_item
= dialog
->item_informational_
;
409 main_item
= dialog
->item_status_parameters_
;
411 case HCI_OGF_TESTING
:
412 main_item
= dialog
->item_testing_
;
414 case HCI_OGF_LOW_ENERGY
:
415 main_item
= dialog
->item_low_energy_
;
417 case HCI_OGF_LOGO_TESTING
:
418 main_item
= dialog
->item_logo_testing_
;
420 case HCI_OGF_VENDOR_SPECIFIC
:
421 main_item
= dialog
->item_vendor_
;
424 main_item
= dialog
->item_unknown_ogf_
;
427 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
428 if (main_item
->child(i_item
)->text(column_number_opcode
) ==
429 QStringLiteral("0x%1").arg(tap_hci
->ogf
<< 10 | tap_hci
->ocf
, 4, 16, QChar('0'))) {
430 item
= main_item
->child(i_item
);
431 if (tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_VENDOR_OPCODE
&& tap_hci
->name
) {
432 item
->setText(column_number_name
, tap_hci
->name
);
433 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() - 1));
440 item
= new QTreeWidgetItem();
442 name
= tap_hci
->name
;
444 item
->setText(column_number_name
, name
);
445 item
->setText(column_number_ogf
, QStringLiteral("0x%1").arg(tap_hci
->ogf
, 2, 16, QChar('0')));
446 item
->setText(column_number_ocf
, QStringLiteral("0x%1").arg(tap_hci
->ocf
, 4, 16, QChar('0')));
447 item
->setText(column_number_opcode
,
448 QStringLiteral("0x%1").arg(tap_hci
->ogf
<< 10 | tap_hci
->ocf
, 4, 16, QChar('0')));
449 if (tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_OPCODE
)
450 item
->setText(column_number_occurrence
, "0");
452 item
->setText(column_number_occurrence
, "1");
454 main_item
->addChild(item
);
455 item
->setHidden(!name
.contains(dialog
->ui
->resultsFilterLineEdit
->text(), Qt::CaseInsensitive
));
456 main_item
->sortChildren(column_number_opcode
, Qt::AscendingOrder
);
458 main_item
->setText(column_number_occurrence
, QString::number(main_item
->text(column_number_occurrence
).toInt() + 1));
461 if (tap_hci
->type
!= BLUETOOTH_HCI_SUMMARY_EVENT_OPCODE
&& tap_hci
->type
!= BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT_OPCODE
)
462 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
464 /* I believe bthci_cmd/bthci_evt already add frame item */
465 if (tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_VENDOR_OPCODE
||
466 tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT_OPCODE
)
469 frame_item
= new QTreeWidgetItem();
470 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
471 frame_item
->setText(column_number_ogf
, QStringLiteral("0x%1").arg(tap_hci
->ogf
, 2, 16, QChar('0')));
472 frame_item
->setText(column_number_ocf
, QStringLiteral("0x%1").arg(tap_hci
->ocf
, 4, 16, QChar('0')));
473 frame_item
->setText(column_number_opcode
, QStringLiteral("0x%1")
474 .arg(tap_hci
->ogf
<< 10 | tap_hci
->ocf
, 4, 16, QChar('0')));
475 if (tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_EVENT_OPCODE
)
476 frame_item
->setText(column_number_event
, QStringLiteral("0x%1").arg(tap_hci
->event
, 2, 16, QChar('0')));
477 item
->addChild(frame_item
);
479 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
480 item_data
->interface_id
= tap_hci
->interface_id
;
481 item_data
->adapter_id
= tap_hci
->adapter_id
;
482 item_data
->frame_number
= pinfo
->num
;
483 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
486 case BLUETOOTH_HCI_SUMMARY_EVENT
:
487 case BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT
:
488 main_item
= dialog
->item_events_
;
490 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
491 if (main_item
->child(i_item
)->text(column_number_event
) ==
492 QStringLiteral("0x%1").arg(tap_hci
->event
, 2, 16, QChar('0'))) {
493 item
= main_item
->child(i_item
);
494 if (tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT
&& tap_hci
->name
)
495 item
->setText(column_number_name
, tap_hci
->name
);
501 item
= new QTreeWidgetItem();
503 name
= tap_hci
->name
;
505 item
->setText(column_number_name
, name
);
506 item
->setText(column_number_event
, QStringLiteral("0x%1").arg(tap_hci
->event
, 2, 16, QChar('0')));
507 item
->setText(column_number_occurrence
, QString::number(0));
509 main_item
->addChild(item
);
510 item
->setHidden(!name
.contains(dialog
->ui
->resultsFilterLineEdit
->text(), Qt::CaseInsensitive
));
511 main_item
->sortChildren(column_number_event
, Qt::AscendingOrder
);
512 main_item
->setText(column_number_occurrence
, QString::number(main_item
->text(column_number_occurrence
).toInt() + 1));
515 /* I believe bthci_cmd/bthci_evt already add frame item */
516 if (tap_hci
->type
== BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT
)
519 if (tap_hci
->event
== 0x3E) { /* LE Meta */
521 for (i_item
= 0; i_item
< item
->childCount(); i_item
+=1) {
522 if (item
->child(i_item
)->text(column_number_name
) != tr("Unknown"))
526 if (i_item
>= item
->childCount()) {
527 frame_item
= new QTreeWidgetItem();
528 frame_item
->setText(column_number_name
, tr("Unknown"));
529 frame_item
->setText(column_number_occurrence
, QString::number(1));
530 item
->addChild(frame_item
);
531 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
535 item
= item
->child(i_item
);
536 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
539 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
542 frame_item
= new QTreeWidgetItem();
543 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
544 frame_item
->setText(column_number_event
, QStringLiteral("0x%1").arg(tap_hci
->event
, 2, 16, QChar('0')));
545 item
->addChild(frame_item
);
547 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
548 item_data
->interface_id
= tap_hci
->interface_id
;
549 item_data
->adapter_id
= tap_hci
->adapter_id
;
550 item_data
->frame_number
= pinfo
->num
;
551 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
554 case BLUETOOTH_HCI_SUMMARY_SUBEVENT
:
555 main_item
= dialog
->item_events_
;
559 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
560 if (main_item
->child(i_item
)->text(column_number_event
) !=
561 QStringLiteral("0x%1").arg(tap_hci
->event
, 2, 16, QChar('0'))) {
565 meta_item
= main_item
->child(i_item
);
569 if (meta_item
== NULL
)
574 for (int i_item
= 0; i_item
< meta_item
->childCount(); i_item
+=1) {
575 if (meta_item
->child(i_item
)->text(column_number_subevent
) !=
576 QStringLiteral("0x%1").arg(tap_hci
->subevent
, 2, 16, QChar('0'))) {
580 item
= meta_item
->child(i_item
);
581 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
587 item
= new QTreeWidgetItem();
588 item
->setText(column_number_name
, tap_hci
->name
);
589 item
->setText(column_number_subevent
, QStringLiteral("0x%1").arg(tap_hci
->subevent
, 2, 16, QChar('0')));
590 item
->setText(column_number_occurrence
, QString::number(1));
592 meta_item
->addChild(item
);
593 meta_item
->setText(column_number_occurrence
, QString::number(meta_item
->text(column_number_occurrence
).toInt() + 1));
594 meta_item
->sortChildren(column_number_subevent
, Qt::AscendingOrder
);
597 frame_item
= new QTreeWidgetItem();
598 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
599 frame_item
->setText(column_number_event
, QStringLiteral("0x%1").arg(tap_hci
->event
, 2, 16, QChar('0')));
600 frame_item
->setText(column_number_subevent
, QStringLiteral("0x%1").arg(tap_hci
->subevent
, 2, 16, QChar('0')));
602 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
603 item_data
->interface_id
= tap_hci
->interface_id
;
604 item_data
->adapter_id
= tap_hci
->adapter_id
;
605 item_data
->frame_number
= pinfo
->num
;
607 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
609 item
->addChild(frame_item
);
611 /* Remove item that is known now */
612 for (int i_item
= 0; i_item
< meta_item
->childCount(); i_item
+=1) {
613 if (meta_item
->child(i_item
)->text(column_number_name
) != tr("Unknown"))
616 item
= meta_item
->child(i_item
);
617 for (int ii_item
= 0; ii_item
< item
->childCount(); ii_item
+=1) {
618 if (item
->child(ii_item
)->text(column_number_name
) != tr("Frame %1").arg(pinfo
->num
))
621 delete item
->child(ii_item
);
622 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() - 1));
623 if (item
->childCount() == 0) {
625 meta_item
->setText(column_number_occurrence
, QString::number(meta_item
->text(column_number_occurrence
).toInt() - 1));
634 case BLUETOOTH_HCI_SUMMARY_STATUS
:
635 main_item
= dialog
->item_status_
;
637 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
638 if (main_item
->child(i_item
)->text(column_number_status
) ==
639 QStringLiteral("0x%1").arg(tap_hci
->status
, 2, 16, QChar('0'))) {
640 item
= main_item
->child(i_item
);
647 name
= tap_hci
->name
;
649 item
= new QTreeWidgetItem();
650 item
->setText(column_number_name
, name
);
651 item
->setText(column_number_status
, QStringLiteral("0x%1").arg(tap_hci
->status
, 2, 16, QChar('0')));
653 main_item
->addChild(item
);
654 item
->setHidden(!name
.contains(dialog
->ui
->resultsFilterLineEdit
->text(), Qt::CaseInsensitive
));
655 main_item
->sortChildren(column_number_event
, Qt::AscendingOrder
);
656 main_item
->setText(column_number_occurrence
, QString::number(main_item
->text(column_number_occurrence
).toInt() + 1));
659 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
661 frame_item
= new QTreeWidgetItem();
662 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
663 frame_item
->setText(column_number_status
, QStringLiteral("0x%1").arg(tap_hci
->status
, 2, 16, QChar('0')));
664 item
->addChild(frame_item
);
666 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
667 item_data
->interface_id
= tap_hci
->interface_id
;
668 item_data
->adapter_id
= tap_hci
->adapter_id
;
669 item_data
->frame_number
= pinfo
->num
;
670 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
673 case BLUETOOTH_HCI_SUMMARY_STATUS_PENDING
:
674 main_item
= dialog
->item_status_
;
676 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
677 if (main_item
->child(i_item
)->text(column_number_status
) == QString::number(tap_hci
->status
)) {
678 item
= main_item
->child(i_item
);
684 item
= new QTreeWidgetItem();
685 item
->setText(column_number_name
, tr("Pending"));
686 item
->setText(column_number_status
, QString::number(tap_hci
->status
));
688 main_item
->addChild(item
);
689 item
->setHidden(!name
.contains(dialog
->ui
->resultsFilterLineEdit
->text(), Qt::CaseInsensitive
));
690 main_item
->sortChildren(column_number_event
, Qt::AscendingOrder
);
691 main_item
->setText(column_number_occurrence
, QString::number(main_item
->text(column_number_occurrence
).toInt() + 1));
694 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
696 frame_item
= new QTreeWidgetItem();
697 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
698 frame_item
->setText(column_number_status
, QString::number(tap_hci
->status
));
699 item
->addChild(frame_item
);
701 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
702 item_data
->interface_id
= tap_hci
->interface_id
;
703 item_data
->adapter_id
= tap_hci
->adapter_id
;
704 item_data
->frame_number
= pinfo
->num
;
705 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
708 case BLUETOOTH_HCI_SUMMARY_REASON
:
709 main_item
= dialog
->item_reason_
;
711 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
712 if (main_item
->child(i_item
)->text(column_number_reason
) ==
713 QStringLiteral("0x%1").arg(tap_hci
->reason
, 2, 16, QChar('0'))) {
714 item
= main_item
->child(i_item
);
721 name
= tap_hci
->name
;
723 item
= new QTreeWidgetItem();
724 item
->setText(column_number_name
, name
);
725 item
->setText(column_number_reason
, QStringLiteral("0x%1").arg(tap_hci
->reason
, 2, 16, QChar('0')));
727 main_item
->addChild(item
);
728 item
->setHidden(!name
.contains(dialog
->ui
->resultsFilterLineEdit
->text(), Qt::CaseInsensitive
));
729 main_item
->sortChildren(column_number_event
, Qt::AscendingOrder
);
730 main_item
->setText(column_number_occurrence
, QString::number(main_item
->text(column_number_occurrence
).toInt() + 1));
733 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
735 frame_item
= new QTreeWidgetItem();
736 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
737 frame_item
->setText(column_number_reason
, QStringLiteral("0x%1").arg(tap_hci
->reason
, 2, 16, QChar('0')));
738 item
->addChild(frame_item
);
740 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
741 item_data
->interface_id
= tap_hci
->interface_id
;
742 item_data
->adapter_id
= tap_hci
->adapter_id
;
743 item_data
->frame_number
= pinfo
->num
;
744 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
747 case BLUETOOTH_HCI_SUMMARY_HARDWARE_ERROR
:
748 main_item
= dialog
->item_hardware_errors_
;
750 for (int i_item
= 0; i_item
< main_item
->childCount(); i_item
+=1) {
751 if (main_item
->child(i_item
)->text(column_number_hardware_error
) ==
752 QStringLiteral("0x%1").arg(tap_hci
->hardware_error
, 2, 16, QChar('0'))) {
753 item
= main_item
->child(i_item
);
759 item
= new QTreeWidgetItem();
760 const QString error
= QStringLiteral("0x%1").arg(tap_hci
->hardware_error
, 2, 16, QChar('0'));
761 item
->setText(column_number_name
, QStringLiteral("Hardware error %1").arg(error
));
762 item
->setText(column_number_hardware_error
, error
);
764 main_item
->addChild(item
);
765 item
->setHidden(!name
.contains(dialog
->ui
->resultsFilterLineEdit
->text(), Qt::CaseInsensitive
));
766 main_item
->sortChildren(column_number_event
, Qt::AscendingOrder
);
767 main_item
->setText(column_number_occurrence
, QString::number(main_item
->text(column_number_occurrence
).toInt() + 1));
770 item
->setText(column_number_occurrence
, QString::number(item
->text(column_number_occurrence
).toInt() + 1));
772 frame_item
= new QTreeWidgetItem();
773 frame_item
->setText(column_number_name
, tr("Frame %1").arg(pinfo
->num
));
774 frame_item
->setText(column_number_hardware_error
, QStringLiteral("0x%1").arg(tap_hci
->hardware_error
, 2, 16, QChar('0')));
775 item
->addChild(frame_item
);
777 item_data
= wmem_new(wmem_file_scope(), bluetooth_item_data_t
);
778 item_data
->interface_id
= tap_hci
->interface_id
;
779 item_data
->adapter_id
= tap_hci
->adapter_id
;
780 item_data
->frame_number
= pinfo
->num
;
781 frame_item
->setData(0, Qt::UserRole
, VariantPointer
<bluetooth_item_data_t
>::asQVariant(item_data
));
786 for (int i
= 0; i
< dialog
->ui
->tableTreeWidget
->columnCount(); i
++) {
787 dialog
->ui
->tableTreeWidget
->resizeColumnToContents(i
);
790 return TAP_PACKET_REDRAW
;
793 void BluetoothHciSummaryDialog::interfaceCurrentIndexChanged(int)
795 cap_file_
.retapPackets();
798 void BluetoothHciSummaryDialog::adapterCurrentIndexChanged(int)
800 cap_file_
.retapPackets();
803 void BluetoothHciSummaryDialog::on_tableTreeWidget_itemActivated(QTreeWidgetItem
*item
, int)
808 bluetooth_item_data_t
*item_data
= VariantPointer
<bluetooth_item_data_t
>::asPtr(item
->data(0, Qt::UserRole
));
811 emit
goToPacket(item_data
->frame_number
);
815 void BluetoothHciSummaryDialog::recursiveCopyTreeItems(QTreeWidgetItem
*item
, QString
©
, int ident_level
)
817 QTreeWidgetItem
*child_item
;
819 if (!item
->isExpanded()) return;
821 for (int i_item
= 0; i_item
< item
->childCount(); i_item
+= 1) {
822 child_item
= item
->child(i_item
);
824 copy
.append(QStringLiteral(" ").repeated(ident_level
));
825 copy
+= QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
826 .arg(child_item
->text(column_number_name
), -60 + 4 * ident_level
)
827 .arg(child_item
->text(column_number_ogf
), -10)
828 .arg(child_item
->text(column_number_ocf
), -10)
829 .arg(child_item
->text(column_number_opcode
), -10)
830 .arg(child_item
->text(column_number_event
), -10)
831 .arg(child_item
->text(column_number_subevent
), -10)
832 .arg(child_item
->text(column_number_status
), -10)
833 .arg(child_item
->text(column_number_reason
), -10)
834 .arg(child_item
->text(column_number_hardware_error
), -15)
835 .arg(child_item
->text(column_number_occurrence
), -10);
837 recursiveCopyTreeItems(child_item
, copy
, ident_level
+ 1);
841 void BluetoothHciSummaryDialog::on_actionCopy_All_triggered()
843 QClipboard
*clipboard
= QApplication::clipboard();
845 QTreeWidgetItem
*item
;
847 item
= ui
->tableTreeWidget
->headerItem();
849 copy
+= QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10\n")
850 .arg(item
->text(column_number_name
), -60)
851 .arg(item
->text(column_number_ogf
), -10)
852 .arg(item
->text(column_number_ocf
), -10)
853 .arg(item
->text(column_number_opcode
), -10)
854 .arg(item
->text(column_number_event
), -10)
855 .arg(item
->text(column_number_subevent
), -10)
856 .arg(item
->text(column_number_status
), -10)
857 .arg(item
->text(column_number_reason
), -10)
858 .arg(item
->text(column_number_hardware_error
), -15)
859 .arg(item
->text(column_number_occurrence
), -10);
861 for (int i_item
= 0; i_item
< ui
->tableTreeWidget
->topLevelItemCount(); ++i_item
) {
862 item
= ui
->tableTreeWidget
->topLevelItem(i_item
);
864 copy
+= QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9 %10\n")
865 .arg(item
->text(column_number_name
), -60)
866 .arg(item
->text(column_number_ogf
), -10)
867 .arg(item
->text(column_number_ocf
), -10)
868 .arg(item
->text(column_number_opcode
), -10)
869 .arg(item
->text(column_number_event
), -10)
870 .arg(item
->text(column_number_subevent
), -10)
871 .arg(item
->text(column_number_status
), -10)
872 .arg(item
->text(column_number_reason
), -10)
873 .arg(item
->text(column_number_hardware_error
), -15)
874 .arg(item
->text(column_number_occurrence
), -10);
876 recursiveCopyTreeItems(ui
->tableTreeWidget
->topLevelItem(i_item
), copy
, 1);
879 clipboard
->setText(copy
);
882 void BluetoothHciSummaryDialog::on_actionSave_as_image_triggered()
886 QString fileName
= WiresharkFileDialog::getSaveFileName(this,
887 tr("Save Table Image"),
888 "bluetooth_hci_summary.png",
889 tr("PNG Image (*.png)"));
891 if (fileName
.isEmpty()) return;
893 image
= ui
->tableTreeWidget
->grab();
894 image
.save(fileName
, "PNG");
897 void BluetoothHciSummaryDialog::on_buttonBox_clicked(QAbstractButton
*)
899 /* if (button == foo_button_) */
902 void BluetoothHciSummaryDialog::displayFilterLineEditAccepted()
904 GString
*error_string
;
906 remove_tap_listener(&tapinfo_
);
907 error_string
= register_tap_listener("bluetooth.hci_summary", &tapinfo_
,
908 ui
->displayFilterLineEdit
->text().toUtf8().constData(),
910 bluetooth_hci_summary_tap_reset
,
911 bluetooth_hci_summary_tap_packet
,
916 if (error_string
!= NULL
) {
917 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
918 "%s", error_string
->str
);
919 g_string_free(error_string
, TRUE
);
922 cap_file_
.retapPackets();
925 void BluetoothHciSummaryDialog::resultsFilterLineEditChanged(const QString
&text
)
927 for (int i_item
= 0; i_item
< ui
->tableTreeWidget
->topLevelItemCount(); ++i_item
) {
928 QTreeWidgetItem
*item
= ui
->tableTreeWidget
->topLevelItem(i_item
);
930 for (int i_child
= 0; i_child
< item
->childCount(); i_child
+= 1) {
931 QTreeWidgetItem
*child_item
= item
->child(i_child
);
932 QString name
= child_item
->text(column_number_name
);
933 child_item
->setHidden(!name
.contains(text
, Qt::CaseInsensitive
));