aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/bluetooth_hci_summary_dialog.cpp
diff options
context:
space:
mode:
authorMichal Labedzki <michal.labedzki@tieto.com>2015-06-08 19:38:48 +0200
committerMichal Labedzki <michal.labedzki@tieto.com>2015-07-17 13:54:43 +0000
commit3faec795e9c5b5f153f66960c11673c2f53e4243 (patch)
tree4df5f704a41290a0a0694c3896a8a7e6521001ac /ui/qt/bluetooth_hci_summary_dialog.cpp
parent6514dece0c755854081a0a0ccb525e6bc9dbbaff (diff)
Qt/Bluetooth: Add HCI Summary dialogue
HCI Summary dialogue collect HCI Opcodes, HCI Events, Hardware Errors, Statuses and Reasons. Also show occurrence of them. The top level item is group of items (by OGF or types), the second level item is in real command, event, hardware error, status or reason. The third level items are direct link to packet that contains second level item type. Change-Id: I6b6bd02533c4605a2dd2c1f5dfee46f72a0f3fdc Reviewed-on: https://code.wireshark.org/review/9676 Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Petri-Dish: Michal Labedzki <michal.labedzki@tieto.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michal Labedzki <michal.labedzki@tieto.com>
Diffstat (limited to 'ui/qt/bluetooth_hci_summary_dialog.cpp')
-rw-r--r--ui/qt/bluetooth_hci_summary_dialog.cpp727
1 files changed, 727 insertions, 0 deletions
diff --git a/ui/qt/bluetooth_hci_summary_dialog.cpp b/ui/qt/bluetooth_hci_summary_dialog.cpp
new file mode 100644
index 0000000000..23d68e6e00
--- /dev/null
+++ b/ui/qt/bluetooth_hci_summary_dialog.cpp
@@ -0,0 +1,727 @@
+/* bluetooth_hci_summary_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "bluetooth_hci_summary_dialog.h"
+#include "ui_bluetooth_hci_summary_dialog.h"
+
+#include "epan/epan.h"
+#include "epan/addr_resolv.h"
+#include "epan/to_str.h"
+#include "epan/epan_dissect.h"
+#include "epan/dissectors/packet-bluetooth.h"
+#include "epan/dissectors/packet-bthci_cmd.h"
+#include "epan/dissectors/packet-bthci_evt.h"
+
+#include "ui/simple_dialog.h"
+
+#include <QClipboard>
+#include <QContextMenuEvent>
+#include <QPushButton>
+#include <QTreeWidget>
+#include <QFileDialog>
+
+static const int column_number_name = 0;
+static const int column_number_ogf = 1;
+static const int column_number_ocf = 2;
+static const int column_number_opcode = 3;
+static const int column_number_event = 4;
+static const int column_number_status = 5;
+static const int column_number_reason = 6;
+static const int column_number_hardware_error = 7;
+static const int column_number_occurrence = 8;
+
+typedef struct _item_data_t {
+ guint32 interface_id;
+ guint32 adapter_id;
+ guint32 frame_number;
+} item_data_t;
+
+Q_DECLARE_METATYPE(item_data_t *)
+
+static gboolean
+bluetooth_device_tap_packet(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *edt, const void* data)
+{
+ bluetooth_hci_summary_tapinfo_t *tapinfo = (bluetooth_hci_summary_tapinfo_t *) tapinfo_ptr;
+
+ if (tapinfo->tap_packet)
+ tapinfo->tap_packet(tapinfo, pinfo, edt, data);
+
+ return TRUE;
+}
+
+static void
+bluetooth_device_tap_reset(void *tapinfo_ptr)
+{
+ bluetooth_hci_summary_tapinfo_t *tapinfo = (bluetooth_hci_summary_tapinfo_t *) tapinfo_ptr;
+
+ if (tapinfo->tap_reset)
+ tapinfo->tap_reset(tapinfo);
+}
+
+static void
+bluetooth_devices_tap(void *data)
+{
+ GString *error_string;
+
+ error_string = register_tap_listener("bluetooth.hci_summary", data, NULL,
+ 0,
+ bluetooth_device_tap_reset,
+ bluetooth_device_tap_packet,
+ NULL
+ );
+
+ if (error_string != NULL) {
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "%s", error_string->str);
+ g_string_free(error_string, TRUE);
+ }
+}
+
+
+BluetoothHciSummaryDialog::BluetoothHciSummaryDialog(QWidget &parent, CaptureFile &cf) :
+ WiresharkDialog(parent, cf),
+ ui(new Ui::BluetoothHciSummaryDialog)
+{
+ ui->setupUi(this);
+ resize(parent.width() * 4 / 5, parent.height() * 2 / 3);
+
+ connect(ui->tableTreeWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(tableContextMenu(const QPoint &)));
+ connect(ui->tableTreeWidget, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(tableItemExpanded(QTreeWidgetItem *)));
+ connect(ui->tableTreeWidget, SIGNAL(itemCollapsed(QTreeWidgetItem *)), this, SLOT(tableItemCollapsed(QTreeWidgetItem *)));
+
+ connect(ui->interfaceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(interfaceCurrentIndexChanged(int)));
+ connect(ui->adapterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(adapterCurrentIndexChanged(int)));
+
+ for (int i = 0; i < ui->tableTreeWidget->columnCount(); i++) {
+ ui->tableTreeWidget->resizeColumnToContents(i);
+ }
+
+ context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Cell);
+ context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Rows);
+ context_menu_.addActions(QList<QAction *>() << ui->actionCopy_All);
+ context_menu_.addActions(QList<QAction *>() << ui->actionSave_as_image);
+
+ tapinfo_.tap_packet = tapPacket;
+ tapinfo_.tap_reset = tapReset;
+ tapinfo_.ui = this;
+
+ item_link_control_ = ui->tableTreeWidget->topLevelItem(0);
+ item_link_policy_ = ui->tableTreeWidget->topLevelItem(1);
+ item_controller_and_baseband_ = ui->tableTreeWidget->topLevelItem(2);
+ item_informational_ = ui->tableTreeWidget->topLevelItem(3);
+ item_status_parameters_ = ui->tableTreeWidget->topLevelItem(4);
+ item_testing_ = ui->tableTreeWidget->topLevelItem(5);
+ item_low_energy_ = ui->tableTreeWidget->topLevelItem(6);
+ item_logo_testing_ = ui->tableTreeWidget->topLevelItem(7);
+ item_vendor_ = ui->tableTreeWidget->topLevelItem(8);
+ item_unknown_ogf_ = ui->tableTreeWidget->topLevelItem(9);
+ item_events_ = ui->tableTreeWidget->topLevelItem(10);
+ item_status_ = ui->tableTreeWidget->topLevelItem(11);
+ item_reason_ = ui->tableTreeWidget->topLevelItem(12);
+ item_hardware_errors_ = ui->tableTreeWidget->topLevelItem(13);
+
+ bluetooth_devices_tap(&tapinfo_);
+
+ cap_file_.retapPackets();
+}
+
+
+BluetoothHciSummaryDialog::~BluetoothHciSummaryDialog()
+{
+ delete ui;
+
+ remove_tap_listener(&tapinfo_);
+}
+
+
+void BluetoothHciSummaryDialog::captureFileClosing()
+{
+ remove_tap_listener(&tapinfo_);
+
+ ui->interfaceComboBox->setEnabled(FALSE);
+ ui->adapterComboBox->setEnabled(FALSE);
+
+ WiresharkDialog::captureFileClosing();
+}
+
+
+void BluetoothHciSummaryDialog::changeEvent(QEvent *event)
+{
+ if (0 != event)
+ {
+ switch (event->type())
+ {
+ case QEvent::LanguageChange:
+ ui->retranslateUi(this);
+ break;
+ default:
+ break;
+ }
+ }
+ QDialog::changeEvent(event);
+}
+
+
+void BluetoothHciSummaryDialog::tableContextMenu(const QPoint &pos)
+{
+ context_menu_.exec(ui->tableTreeWidget->viewport()->mapToGlobal(pos));
+}
+
+void BluetoothHciSummaryDialog::tableItemExpanded(QTreeWidgetItem *item)
+{
+ Q_UNUSED(item);
+
+ for (int i = 0; i < ui->tableTreeWidget->columnCount(); i++) {
+ ui->tableTreeWidget->resizeColumnToContents(i);
+ }
+}
+
+void BluetoothHciSummaryDialog::tableItemCollapsed(QTreeWidgetItem *item)
+{
+ Q_UNUSED(item);
+
+ for (int i = 0; i < ui->tableTreeWidget->columnCount(); i++) {
+ ui->tableTreeWidget->resizeColumnToContents(i);
+ }
+}
+
+void BluetoothHciSummaryDialog::on_actionCopy_Cell_triggered()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ QString copy;
+
+ copy = QString(ui->tableTreeWidget->currentItem()->text(ui->tableTreeWidget->currentColumn()));
+
+ clipboard->setText(copy);
+}
+
+
+void BluetoothHciSummaryDialog::on_actionCopy_Rows_triggered()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ QString copy;
+ QList<QTreeWidgetItem *> items;
+ QList<QTreeWidgetItem *>::iterator i_item;
+
+ items = ui->tableTreeWidget->selectedItems();
+
+ for (i_item = items.begin(); i_item != items.end(); ++i_item) {
+ copy += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
+ .arg((*i_item)->text(column_number_name), -60)
+ .arg((*i_item)->text(column_number_ogf), -10)
+ .arg((*i_item)->text(column_number_ocf), -10)
+ .arg((*i_item)->text(column_number_opcode), -10)
+ .arg((*i_item)->text(column_number_event), -10)
+ .arg((*i_item)->text(column_number_status), -10)
+ .arg((*i_item)->text(column_number_reason), -10)
+ .arg((*i_item)->text(column_number_hardware_error), -15)
+ .arg((*i_item)->text(column_number_occurrence), -10);
+ }
+
+ clipboard->setText(copy);
+}
+
+void BluetoothHciSummaryDialog::tapReset(void *tapinfo_ptr )
+{
+ bluetooth_hci_summary_tapinfo_t *tapinfo = (bluetooth_hci_summary_tapinfo_t *) tapinfo_ptr;
+ BluetoothHciSummaryDialog *dialog = static_cast<BluetoothHciSummaryDialog *>(tapinfo->ui);
+
+ dialog->item_link_control_->takeChildren();
+ dialog->item_link_control_->setText(column_number_occurrence, "0");
+
+ dialog->item_link_policy_->takeChildren();
+ dialog->item_link_policy_->setText(column_number_occurrence, "0");
+
+ dialog->item_controller_and_baseband_->takeChildren();
+ dialog->item_controller_and_baseband_->setText(column_number_occurrence, "0");
+
+ dialog->item_informational_->takeChildren();
+ dialog->item_informational_->setText(column_number_occurrence, "0");
+
+ dialog->item_status_parameters_->takeChildren();
+ dialog->item_status_parameters_->setText(column_number_occurrence, "0");
+
+ dialog->item_testing_->takeChildren();
+ dialog->item_testing_->setText(column_number_occurrence, "0");
+
+ dialog->item_low_energy_->takeChildren();
+ dialog->item_low_energy_->setText(column_number_occurrence, "0");
+
+ dialog->item_logo_testing_->takeChildren();
+ dialog->item_logo_testing_->setText(column_number_occurrence, "0");
+
+ dialog->item_vendor_->takeChildren();
+ dialog->item_vendor_->setText(column_number_occurrence, "0");
+
+ dialog->item_unknown_ogf_->takeChildren();
+ dialog->item_unknown_ogf_->setText(column_number_occurrence, "0");
+
+ dialog->item_events_->takeChildren();
+ dialog->item_events_->setText(column_number_occurrence, "0");
+
+ dialog->item_status_->takeChildren();
+ dialog->item_status_->setText(column_number_occurrence, "0");
+
+ dialog->item_reason_->takeChildren();
+ dialog->item_reason_->setText(column_number_occurrence, "0");
+
+ dialog->item_hardware_errors_->takeChildren();
+ dialog->item_hardware_errors_->setText(column_number_occurrence, "0");
+}
+
+gboolean BluetoothHciSummaryDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data)
+{
+ bluetooth_hci_summary_tapinfo_t *tapinfo = static_cast<bluetooth_hci_summary_tapinfo_t *>(tapinfo_ptr);
+ BluetoothHciSummaryDialog *dialog = static_cast<BluetoothHciSummaryDialog *>(tapinfo->ui);
+ bluetooth_hci_summary_tap_t *tap_hci = static_cast<bluetooth_hci_summary_tap_t *>(const_cast<void *>(data));
+ QTreeWidgetItem *main_item = NULL;
+ QTreeWidgetItem *item = NULL;
+ QTreeWidgetItem *frame_item = NULL;
+ item_data_t *item_data = NULL;
+ QString adapter;
+ QString name;
+
+ name = tr("Unknown");
+
+ if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) {
+ gchar *interface;
+ const char *interface_name;
+
+ interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id);
+ interface = wmem_strdup_printf(wmem_packet_scope(), "%u: %s", pinfo->phdr->interface_id, interface_name);
+
+ if (dialog->ui->interfaceComboBox->findText(interface) == -1)
+ dialog->ui->interfaceComboBox->addItem(interface);
+
+ if (interface && dialog->ui->interfaceComboBox->currentIndex() > 0) {
+ if (dialog->ui->interfaceComboBox->currentText() != interface)
+ return TRUE;
+ }
+ }
+
+ adapter = QString(tr("Adapter %1")).arg(tap_hci->adapter_id);
+
+ if (dialog->ui->adapterComboBox->findText(adapter) == -1) {
+ dialog->ui->adapterComboBox->addItem(adapter);
+ }
+
+ if (dialog->ui->adapterComboBox->currentIndex() > 0) {
+ if (dialog->ui->adapterComboBox->currentText() != adapter)
+ return TRUE;
+ }
+
+ switch (tap_hci->type) {
+ case BLUETOOTH_HCI_SUMMARY_OPCODE:
+ case BLUETOOTH_HCI_SUMMARY_EVENT_OPCODE:
+ case BLUETOOTH_HCI_SUMMARY_VENDOR_OPCODE:
+ case BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT_OPCODE:
+ switch (tap_hci->ogf) {
+ case HCI_OGF_LINK_CONTROL:
+ main_item = dialog->item_link_control_;
+ break;
+ case HCI_OGF_LINK_POLICY:
+ main_item = dialog->item_link_policy_;
+ break;
+ case HCI_OGF_HOST_CONTROLLER:
+ main_item = dialog->item_controller_and_baseband_;
+ break;
+ case HCI_OGF_INFORMATIONAL:
+ main_item = dialog->item_informational_;
+ break;
+ case HCI_OGF_STATUS:
+ main_item = dialog->item_status_parameters_;
+ break;
+ case HCI_OGF_TESTING:
+ main_item = dialog->item_testing_;
+ break;
+ case HCI_OGF_LOW_ENERGY:
+ main_item = dialog->item_low_energy_;
+ break;
+ case HCI_OGF_LOGO_TESTING:
+ main_item = dialog->item_logo_testing_;
+ break;
+ case HCI_OGF_VENDOR_SPECIFIC:
+ main_item = dialog->item_vendor_;
+ break;
+ default:
+ main_item = dialog->item_unknown_ogf_;
+ }
+
+ for (int i_item = 0; i_item < main_item->childCount(); i_item +=1) {
+ if (main_item->child(i_item)->text(column_number_opcode) == QString("").sprintf("0x%04X", tap_hci->ogf << 10 | tap_hci->ocf)) {
+ item = main_item->child(i_item);
+ if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_VENDOR_OPCODE && tap_hci->name)
+ item->setText(column_number_name, tap_hci->name);
+ break;
+ }
+ }
+
+ if (!item) {
+ item = new QTreeWidgetItem();
+ if (tap_hci->name)
+ name = tap_hci->name;
+
+ item->setText(column_number_name, name);
+ item->setText(column_number_ogf, QString("").sprintf("0x%02X", tap_hci->ogf));
+ item->setText(column_number_ocf, QString("").sprintf("0x%04X", tap_hci->ocf));
+ item->setText(column_number_opcode, QString("").sprintf("0x%04X", tap_hci->ogf << 10 | tap_hci->ocf));
+ if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_OPCODE)
+ item->setText(column_number_occurrence, "0");
+ else
+ item->setText(column_number_occurrence, "1");
+
+ main_item->addChild(item);
+ main_item->sortChildren(column_number_opcode, Qt::AscendingOrder);
+
+ main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1));
+ }
+
+ if (tap_hci->type != BLUETOOTH_HCI_SUMMARY_EVENT_OPCODE && tap_hci->type != BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT_OPCODE)
+ item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1));
+
+ /* I belive bthci_cmd/bthci_evt already add frame item */
+ if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_VENDOR_OPCODE ||
+ tap_hci->type == BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT_OPCODE)
+ break;
+
+ frame_item = new QTreeWidgetItem();
+ frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->fd->num));
+ frame_item->setText(column_number_ogf, QString("").sprintf("0x%02X", tap_hci->ogf));
+ frame_item->setText(column_number_ocf, QString("").sprintf("0x%04X", tap_hci->ocf));
+ frame_item->setText(column_number_opcode, QString("").sprintf("0x%04X", tap_hci->ogf << 10 | tap_hci->ocf));
+ item->addChild(frame_item);
+
+ item_data = wmem_new(wmem_file_scope(), item_data_t);
+ item_data->interface_id = tap_hci->interface_id;
+ item_data->adapter_id = tap_hci->adapter_id;
+ item_data->frame_number = pinfo->fd->num;
+ frame_item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data));
+
+ break;
+ case BLUETOOTH_HCI_SUMMARY_EVENT:
+ case BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT:
+ main_item = dialog->item_events_;
+
+ for (int i_item = 0; i_item < main_item->childCount(); i_item +=1) {
+ if (main_item->child(i_item)->text(column_number_event) == QString("").sprintf("0x%02X", tap_hci->event)) {
+ item = main_item->child(i_item);
+ if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT && tap_hci->name)
+ item->setText(column_number_name, tap_hci->name);
+ break;
+ }
+ }
+
+ if (!item) {
+ QString name;
+
+ item = new QTreeWidgetItem();
+ if (tap_hci->name)
+ name = tap_hci->name;
+
+ item->setText(column_number_name, name);
+ item->setText(column_number_event, QString("").sprintf("0x%02X", tap_hci->event));
+
+ main_item->addChild(item);
+ main_item->sortChildren(column_number_event, Qt::AscendingOrder);
+ main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1));
+ }
+
+ item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1));
+
+ /* I belive bthci_cmd/bthci_evt already add frame item */
+ if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT)
+ break;
+
+ frame_item = new QTreeWidgetItem();
+ frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->fd->num));
+ frame_item->setText(column_number_event, QString("").sprintf("0x%02X", tap_hci->event));
+ item->addChild(frame_item);
+
+ item_data = wmem_new(wmem_file_scope(), item_data_t);
+ item_data->interface_id = tap_hci->interface_id;
+ item_data->adapter_id = tap_hci->adapter_id;
+ item_data->frame_number = pinfo->fd->num;
+ frame_item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data));
+
+ break;
+ case BLUETOOTH_HCI_SUMMARY_STATUS:
+ main_item = dialog->item_status_;
+
+ for (int i_item = 0; i_item < main_item->childCount(); i_item +=1) {
+ if (main_item->child(i_item)->text(column_number_status) == QString("").sprintf("0x%02X", tap_hci->status)) {
+ item = main_item->child(i_item);
+ break;
+ }
+ }
+
+ if (!item) {
+ if (tap_hci->name)
+ name = tap_hci->name;
+
+ item = new QTreeWidgetItem();
+ item->setText(column_number_name, name);
+ item->setText(column_number_status, QString("").sprintf("0x%02X", tap_hci->status));
+
+ main_item->addChild(item);
+ main_item->sortChildren(column_number_event, Qt::AscendingOrder);
+ main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1));
+ }
+
+ item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1));
+
+ frame_item = new QTreeWidgetItem();
+ frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->fd->num));
+ frame_item->setText(column_number_status, QString("").sprintf("0x%02X", tap_hci->status));
+ item->addChild(frame_item);
+
+ item_data = wmem_new(wmem_file_scope(), item_data_t);
+ item_data->interface_id = tap_hci->interface_id;
+ item_data->adapter_id = tap_hci->adapter_id;
+ item_data->frame_number = pinfo->fd->num;
+ frame_item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data));
+
+ break;
+ case BLUETOOTH_HCI_SUMMARY_STATUS_PENDING:
+ main_item = dialog->item_status_;
+
+ for (int i_item = 0; i_item < main_item->childCount(); i_item +=1) {
+ if (main_item->child(i_item)->text(column_number_status) == QString("").sprintf("%u", tap_hci->status)) {
+ item = main_item->child(i_item);
+ break;
+ }
+ }
+
+ if (!item) {
+ item = new QTreeWidgetItem();
+ item->setText(column_number_name, tr("Pending"));
+ item->setText(column_number_status, QString("").sprintf("%u", tap_hci->status));
+
+ main_item->addChild(item);
+ main_item->sortChildren(column_number_event, Qt::AscendingOrder);
+ main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1));
+ }
+
+ item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1));
+
+ frame_item = new QTreeWidgetItem();
+ frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->fd->num));
+ frame_item->setText(column_number_status, QString("").sprintf("%u", tap_hci->status));
+ item->addChild(frame_item);
+
+ item_data = wmem_new(wmem_file_scope(), item_data_t);
+ item_data->interface_id = tap_hci->interface_id;
+ item_data->adapter_id = tap_hci->adapter_id;
+ item_data->frame_number = pinfo->fd->num;
+ frame_item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data));
+
+ break;
+ case BLUETOOTH_HCI_SUMMARY_REASON:
+ main_item = dialog->item_reason_;
+
+ for (int i_item = 0; i_item < main_item->childCount(); i_item +=1) {
+ if (main_item->child(i_item)->text(column_number_reason) == QString("").sprintf("0x%02X", tap_hci->reason)) {
+ item = main_item->child(i_item);
+ break;
+ }
+ }
+
+ if (!item) {
+ if (tap_hci->name)
+ name = tap_hci->name;
+
+ item = new QTreeWidgetItem();
+ item->setText(column_number_name, name);
+ item->setText(column_number_reason, QString("").sprintf("0x%02X", tap_hci->reason));
+
+ main_item->addChild(item);
+ main_item->sortChildren(column_number_event, Qt::AscendingOrder);
+ main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1));
+ }
+
+ item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1));
+
+ frame_item = new QTreeWidgetItem();
+ frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->fd->num));
+ frame_item->setText(column_number_reason, QString("").sprintf("0x%02X", tap_hci->reason));
+ item->addChild(frame_item);
+
+ item_data = wmem_new(wmem_file_scope(), item_data_t);
+ item_data->interface_id = tap_hci->interface_id;
+ item_data->adapter_id = tap_hci->adapter_id;
+ item_data->frame_number = pinfo->fd->num;
+ frame_item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data));
+
+ break;
+ case BLUETOOTH_HCI_SUMMARY_HARDWARE_ERROR:
+ main_item = dialog->item_hardware_errors_;
+
+ for (int i_item = 0; i_item < main_item->childCount(); i_item +=1) {
+ if (main_item->child(i_item)->text(column_number_hardware_error) == QString("").sprintf("0x%02X", tap_hci->hardware_error)) {
+ item = main_item->child(i_item);
+ break;
+ }
+ }
+
+ if (!item) {
+ item = new QTreeWidgetItem();
+ item->setText(column_number_name, QString("").sprintf("Hardware error 0x%02X", tap_hci->hardware_error));
+ item->setText(column_number_hardware_error, QString("").sprintf("0x%02X", tap_hci->hardware_error));
+
+ main_item->addChild(item);
+ main_item->sortChildren(column_number_event, Qt::AscendingOrder);
+ main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1));
+ }
+
+ item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1));
+
+ frame_item = new QTreeWidgetItem();
+ frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->fd->num));
+ frame_item->setText(column_number_hardware_error, QString("").sprintf("0x%02X", tap_hci->hardware_error));
+ item->addChild(frame_item);
+
+ item_data = wmem_new(wmem_file_scope(), item_data_t);
+ item_data->interface_id = tap_hci->interface_id;
+ item_data->adapter_id = tap_hci->adapter_id;
+ item_data->frame_number = pinfo->fd->num;
+ frame_item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data));
+
+ break;
+ }
+
+ for (int i = 0; i < dialog->ui->tableTreeWidget->columnCount(); i++) {
+ dialog->ui->tableTreeWidget->resizeColumnToContents(i);
+ }
+
+ return TRUE;
+}
+
+void BluetoothHciSummaryDialog::interfaceCurrentIndexChanged(int)
+{
+ cap_file_.retapPackets();
+}
+
+void BluetoothHciSummaryDialog::adapterCurrentIndexChanged(int)
+{
+ cap_file_.retapPackets();
+}
+
+void BluetoothHciSummaryDialog::on_tableTreeWidget_itemActivated(QTreeWidgetItem *item, int)
+{
+ if (!cap_file_.isValid())
+ return;
+
+ item_data_t *item_data = item->data(0, Qt::UserRole).value<item_data_t *>();
+
+ if (item_data)
+ emit goToPacket(item_data->frame_number);
+}
+
+
+void BluetoothHciSummaryDialog::recursiveCopyTreeItems(QTreeWidgetItem *item, QString &copy, int ident_level)
+{
+ if (!item->isExpanded()) return;
+
+ for (int i_item = 0; i_item < item->childCount(); i_item += 1) {
+ copy.append(QString(" ").repeated(ident_level));
+ copy += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
+ .arg(item->child(i_item)->text(column_number_name), -60 + 4 * ident_level)
+ .arg(item->child(i_item)->text(column_number_ogf), -10)
+ .arg(item->child(i_item)->text(column_number_ocf), -10)
+ .arg(item->child(i_item)->text(column_number_opcode), -10)
+ .arg(item->child(i_item)->text(column_number_event), -10)
+ .arg(item->child(i_item)->text(column_number_status), -10)
+ .arg(item->child(i_item)->text(column_number_reason), -10)
+ .arg(item->child(i_item)->text(column_number_hardware_error), -15)
+ .arg(item->child(i_item)->text(column_number_occurrence), -10);
+
+ recursiveCopyTreeItems(item->child(i_item), copy, ident_level + 1);
+ }
+}
+
+void BluetoothHciSummaryDialog::on_actionCopy_All_triggered()
+{
+ QClipboard *clipboard = QApplication::clipboard();
+ QString copy;
+ QTreeWidgetItemIterator i_item(ui->tableTreeWidget);
+
+ copy += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_name), -60)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_ogf), -10)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_ocf), -10)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_opcode), -10)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_event), -10)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_status), -10)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_reason), -10)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_hardware_error), -15)
+ .arg(ui->tableTreeWidget->headerItem()->text(column_number_occurrence), -10);
+
+ for (int i_item = 0; i_item < ui->tableTreeWidget->topLevelItemCount(); i_item += 1) {
+ QTreeWidgetItem *item = ui->tableTreeWidget->topLevelItem(i_item);
+
+ copy += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
+ .arg(item->text(column_number_name), -60)
+ .arg(item->text(column_number_ogf), -10)
+ .arg(item->text(column_number_ocf), -10)
+ .arg(item->text(column_number_opcode), -10)
+ .arg(item->text(column_number_event), -10)
+ .arg(item->text(column_number_status), -10)
+ .arg(item->text(column_number_reason), -10)
+ .arg(item->text(column_number_hardware_error), -15)
+ .arg(item->text(column_number_occurrence), -10);
+
+ recursiveCopyTreeItems(ui->tableTreeWidget->topLevelItem(i_item), copy, 1);
+ }
+
+ clipboard->setText(copy);
+}
+
+void BluetoothHciSummaryDialog::on_actionSave_as_image_triggered()
+{
+ QPixmap image;
+
+ QString fileName = QFileDialog::getSaveFileName(this,
+ tr("Save Table Image"),
+ "bluetooth_hci_summary.png",
+ tr("PNG Image (*.png)"));
+
+ if (fileName.isEmpty()) return;
+
+ image = QPixmap::grabWidget(ui->tableTreeWidget);
+ image.save(fileName, "PNG");
+}
+
+void BluetoothHciSummaryDialog::on_buttonBox_clicked(QAbstractButton *)
+{
+/* if (button == foo_button_) */
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */