/* bluetooth_hci_summary_dialog.cpp * * Wireshark - Network traffic analyzer * By Gerald Combs * 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 #include "bluetooth_device_dialog.h" #include "color_utils.h" #include "epan/epan.h" #include "epan/addr_resolv.h" #include "epan/to_str.h" #include "epan/epan_dissect.h" #include "epan/prefs.h" #include "epan/dissectors/packet-bluetooth.h" #include "epan/dissectors/packet-bthci_cmd.h" #include "epan/dissectors/packet-bthci_evt.h" #include #include "ui/simple_dialog.h" #include #include #include #include #include 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_subevent = 5; static const int column_number_status = 6; static const int column_number_reason = 7; static const int column_number_hardware_error = 8; static const int column_number_occurrence = 9; static gboolean bluetooth_hci_summary_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_hci_summary_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_hci_summary_tap_init(void *data) { GString *error_string; error_string = register_tap_listener("bluetooth.hci_summary", data, NULL, 0, bluetooth_hci_summary_tap_reset, bluetooth_hci_summary_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); loadGeometry(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))); connect(ui->displayFilterLineEdit, SIGNAL(returnPressed()), this, SLOT(displayFilterLineEditAccepted())); connect(ui->resultsFilterLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(resultsFilterLineEditChanged(const QString &))); for (int i = 0; i < ui->tableTreeWidget->columnCount(); i++) { ui->tableTreeWidget->resizeColumnToContents(i); } ui->tableTreeWidget->setStyleSheet("QTreeView::item:hover{background-color:lightyellow; color:black;}"); context_menu_.addActions(QList() << ui->actionMark_Unmark_Cell); context_menu_.addActions(QList() << ui->actionMark_Unmark_Row); context_menu_.addActions(QList() << ui->actionCopy_Cell); context_menu_.addActions(QList() << ui->actionCopy_Rows); context_menu_.addActions(QList() << ui->actionCopy_All); context_menu_.addActions(QList() << 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_hci_summary_tap_init(&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::keyPressEvent(QKeyEvent *event) { /* NOTE: Do nothing*, but in real it "takes focus" from button_box so allow user * to use Enter button to jump to frame from tree widget */ /* * - reimplement shortcuts from contex menu */ if (event->modifiers() & Qt::ControlModifier && event->key()== Qt::Key_M) on_actionMark_Unmark_Row_triggered(); } void BluetoothHciSummaryDialog::tableContextMenu(const QPoint &pos) { context_menu_.exec(ui->tableTreeWidget->viewport()->mapToGlobal(pos)); } void BluetoothHciSummaryDialog::tableItemExpanded(QTreeWidgetItem *) { for (int i = 0; i < ui->tableTreeWidget->columnCount(); i++) { ui->tableTreeWidget->resizeColumnToContents(i); } } void BluetoothHciSummaryDialog::tableItemCollapsed(QTreeWidgetItem *) { for (int i = 0; i < ui->tableTreeWidget->columnCount(); i++) { ui->tableTreeWidget->resizeColumnToContents(i); } } void BluetoothHciSummaryDialog::on_actionMark_Unmark_Cell_triggered() { QBrush fg; QBrush bg; if (ui->tableTreeWidget->currentItem()->background(ui->tableTreeWidget->currentColumn()) == QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) { fg = QBrush(); bg = QBrush(); } else { fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg)); bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg)); } ui->tableTreeWidget->currentItem()->setForeground(ui->tableTreeWidget->currentColumn(), fg); ui->tableTreeWidget->currentItem()->setBackground(ui->tableTreeWidget->currentColumn(), bg); } void BluetoothHciSummaryDialog::on_actionMark_Unmark_Row_triggered() { QBrush fg; QBrush bg; bool is_marked = TRUE; for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) { if (ui->tableTreeWidget->currentItem()->background(i) != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) is_marked = FALSE; } if (is_marked) { fg = QBrush(); bg = QBrush(); } else { fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg)); bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg)); } for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) { ui->tableTreeWidget->currentItem()->setForeground(i, fg); ui->tableTreeWidget->currentItem()->setBackground(i, bg); } } 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 items; QList::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_subevent), -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(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(tapinfo_ptr); BluetoothHciSummaryDialog *dialog = static_cast(tapinfo->ui); bluetooth_hci_summary_tap_t *tap_hci = static_cast(const_cast(data)); QTreeWidgetItem *main_item = NULL; QTreeWidgetItem *item = NULL; QTreeWidgetItem *frame_item = NULL; QTreeWidgetItem *meta_item = NULL; bluetooth_item_data_t *item_data = NULL; QString adapter; QString name; if (dialog->file_closed_) return FALSE; 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); item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() - 1)); } 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); item->setHidden(!name.contains(dialog->ui->resultsFilterLineEdit->text(), Qt::CaseInsensitive)); 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 believe 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->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)); if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_EVENT_OPCODE) frame_item->setText(column_number_event, QString("").sprintf("0x%02X", tap_hci->event)); item->addChild(frame_item); item_data = wmem_new(wmem_file_scope(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(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) { 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)); item->setText(column_number_occurrence, QString::number(0)); main_item->addChild(item); item->setHidden(!name.contains(dialog->ui->resultsFilterLineEdit->text(), Qt::CaseInsensitive)); main_item->sortChildren(column_number_event, Qt::AscendingOrder); main_item->setText(column_number_occurrence, QString::number(main_item->text(column_number_occurrence).toInt() + 1)); } /* I believe bthci_cmd/bthci_evt already add frame item */ if (tap_hci->type == BLUETOOTH_HCI_SUMMARY_VENDOR_EVENT) break; if (tap_hci->event == 0x3E) { /* LE Meta */ int i_item; for (i_item = 0; i_item < item->childCount(); i_item +=1) { if (item->child(i_item)->text(column_number_name) != QString(tr("Unknown"))) continue; } if (i_item >= item->childCount()) { frame_item = new QTreeWidgetItem(); frame_item->setText(column_number_name, QString(tr("Unknown"))); frame_item->setText(column_number_occurrence, QString::number(1)); item->addChild(frame_item); item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1)); item = frame_item; } else { item = item->child(i_item); item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1)); } } else { 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->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(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(item_data)); break; case BLUETOOTH_HCI_SUMMARY_SUBEVENT: main_item = dialog->item_events_; meta_item = NULL; 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)) continue; meta_item = main_item->child(i_item); break; } if (meta_item == NULL) break; item = NULL; for (int i_item = 0; i_item < meta_item->childCount(); i_item +=1) { if (meta_item->child(i_item)->text(column_number_subevent) != QString("").sprintf("0x%02X", tap_hci->subevent)) continue; item = meta_item->child(i_item); item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() + 1)); break; } if (item == NULL) { item = new QTreeWidgetItem(); item->setText(column_number_name, tap_hci->name); item->setText(column_number_subevent, QString("").sprintf("0x%02X", tap_hci->subevent)); item->setText(column_number_occurrence, QString::number(1)); meta_item->addChild(item); meta_item->setText(column_number_occurrence, QString::number(meta_item->text(column_number_occurrence).toInt() + 1)); meta_item->sortChildren(column_number_subevent, Qt::AscendingOrder); } frame_item = new QTreeWidgetItem(); frame_item->setText(column_number_name, QString(tr("Frame %1")).arg(pinfo->num)); frame_item->setText(column_number_event, QString("").sprintf("0x%02X", tap_hci->event)); frame_item->setText(column_number_subevent, QString("").sprintf("0x%02X", tap_hci->subevent)); item_data = wmem_new(wmem_file_scope(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(item_data)); item->addChild(frame_item); /* Remove item that is known now */ for (int i_item = 0; i_item < meta_item->childCount(); i_item +=1) { if (meta_item->child(i_item)->text(column_number_name) != QString(tr("Unknown"))) continue; item = meta_item->child(i_item); for (int ii_item = 0; ii_item < item->childCount(); ii_item +=1) { if (item->child(ii_item)->text(column_number_name) != QString(tr("Frame %1")).arg(pinfo->num)) continue; delete item->child(ii_item); item->setText(column_number_occurrence, QString::number(item->text(column_number_occurrence).toInt() - 1)); if (item->childCount() == 0) { delete item; meta_item->setText(column_number_occurrence, QString::number(meta_item->text(column_number_occurrence).toInt() - 1)); } break; } break; } 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); item->setHidden(!name.contains(dialog->ui->resultsFilterLineEdit->text(), Qt::CaseInsensitive)); 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->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(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(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); item->setHidden(!name.contains(dialog->ui->resultsFilterLineEdit->text(), Qt::CaseInsensitive)); 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->num)); frame_item->setText(column_number_status, QString("").sprintf("%u", tap_hci->status)); item->addChild(frame_item); item_data = wmem_new(wmem_file_scope(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(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); item->setHidden(!name.contains(dialog->ui->resultsFilterLineEdit->text(), Qt::CaseInsensitive)); 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->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(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(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); item->setHidden(!name.contains(dialog->ui->resultsFilterLineEdit->text(), Qt::CaseInsensitive)); 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->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(), bluetooth_item_data_t); item_data->interface_id = tap_hci->interface_id; item_data->adapter_id = tap_hci->adapter_id; item_data->frame_number = pinfo->num; frame_item->setData(0, Qt::UserRole, VariantPointer::asQVariant(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 (file_closed_) return; bluetooth_item_data_t *item_data = VariantPointer::asPtr(item->data(0, Qt::UserRole)); if (item_data) emit goToPacket(item_data->frame_number); } void BluetoothHciSummaryDialog::recursiveCopyTreeItems(QTreeWidgetItem *item, QString ©, int ident_level) { QTreeWidgetItem *child_item; if (!item->isExpanded()) return; for (int i_item = 0; i_item < item->childCount(); i_item += 1) { child_item = item->child(i_item); copy.append(QString(" ").repeated(ident_level)); copy += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9\n") .arg(child_item->text(column_number_name), -60 + 4 * ident_level) .arg(child_item->text(column_number_ogf), -10) .arg(child_item->text(column_number_ocf), -10) .arg(child_item->text(column_number_opcode), -10) .arg(child_item->text(column_number_event), -10) .arg(child_item->text(column_number_subevent), -10) .arg(child_item->text(column_number_status), -10) .arg(child_item->text(column_number_reason), -10) .arg(child_item->text(column_number_hardware_error), -15) .arg(child_item->text(column_number_occurrence), -10); recursiveCopyTreeItems(child_item, copy, ident_level + 1); } } void BluetoothHciSummaryDialog::on_actionCopy_All_triggered() { QClipboard *clipboard = QApplication::clipboard(); QString copy; QTreeWidgetItem *item; item = ui->tableTreeWidget->headerItem(); 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_subevent), -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); for (int i_item = 0; i_item < ui->tableTreeWidget->topLevelItemCount(); ++i_item) { 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_subevent), -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_) */ } void BluetoothHciSummaryDialog::displayFilterLineEditAccepted() { GString *error_string; remove_tap_listener(&tapinfo_); error_string = register_tap_listener("bluetooth.hci_summary", &tapinfo_, ui->displayFilterLineEdit->text().toUtf8().constData(), 0, bluetooth_hci_summary_tap_reset, bluetooth_hci_summary_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); } cap_file_.retapPackets(); } void BluetoothHciSummaryDialog::resultsFilterLineEditChanged(const QString &text) { for (int i_item = 0; i_item < ui->tableTreeWidget->topLevelItemCount(); ++i_item) { QTreeWidgetItem *item = ui->tableTreeWidget->topLevelItem(i_item); for (int i_child = 0; i_child < item->childCount(); i_child += 1) { QTreeWidgetItem *child_item = item->child(i_child); QString name = child_item->text(column_number_name); child_item->setHidden(!name.contains(text, Qt::CaseInsensitive)); } } } /* * 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: */