diff options
Diffstat (limited to 'ui/qt/bluetooth_devices_dialog.cpp')
-rw-r--r-- | ui/qt/bluetooth_devices_dialog.cpp | 412 |
1 files changed, 412 insertions, 0 deletions
diff --git a/ui/qt/bluetooth_devices_dialog.cpp b/ui/qt/bluetooth_devices_dialog.cpp new file mode 100644 index 0000000000..73efe791bb --- /dev/null +++ b/ui/qt/bluetooth_devices_dialog.cpp @@ -0,0 +1,412 @@ +/* bluetooth_devices_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_devices_dialog.h" +#include "ui_bluetooth_devices_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_evt.h" + +#include "ui/simple_dialog.h" + +#include <QClipboard> +#include <QContextMenuEvent> +#include <QPushButton> +#include <QTreeWidget> +#include <QFileDialog> + +static const int column_number_bd_addr = 0; +static const int column_number_bd_addr_oui = 1; +static const int column_number_name = 2; +static const int column_number_lmp_version = 3; +static const int column_number_lmp_subversion = 4; +static const int column_number_manufacturer = 5; +static const int column_number_hci_version = 6; +static const int column_number_hci_revision = 7; +static const int column_number_is_local_adapter = 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_devices_tapinfo_t *tapinfo = (bluetooth_devices_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_devices_tapinfo_t *tapinfo = (bluetooth_devices_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.device", 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); + } +} + + +BluetoothDevicesDialog::BluetoothDevicesDialog(QWidget &parent, CaptureFile &cf) : + WiresharkDialog(parent, cf), + ui(new Ui::BluetoothDevicesDialog) +{ + 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->interfaceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(interfaceCurrentIndexChanged(int))); + connect(ui->showInformationStepsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showInformationStepsChanged(int))); + + ui->tableTreeWidget->sortByColumn(column_number_bd_addr, Qt::AscendingOrder); + + 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; + + bluetooth_devices_tap(&tapinfo_); + + cap_file_.retapPackets(); +} + + +BluetoothDevicesDialog::~BluetoothDevicesDialog() +{ + delete ui; + + remove_tap_listener(&tapinfo_); +} + + +void BluetoothDevicesDialog::captureFileClosing() +{ + remove_tap_listener(&tapinfo_); + + ui->interfaceComboBox->setEnabled(FALSE); + ui->showInformationStepsCheckBox->setEnabled(FALSE); + + WiresharkDialog::captureFileClosing(); +} + + +void BluetoothDevicesDialog::changeEvent(QEvent *event) +{ + if (0 != event) + { + switch (event->type()) + { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } + } + QDialog::changeEvent(event); +} + + +void BluetoothDevicesDialog::tableContextMenu(const QPoint &pos) +{ + context_menu_.exec(ui->tableTreeWidget->viewport()->mapToGlobal(pos)); +} + + +void BluetoothDevicesDialog::on_actionCopy_Cell_triggered() +{ + QClipboard *clipboard = QApplication::clipboard(); + QString copy; + + copy = QString(ui->tableTreeWidget->currentItem()->text(ui->tableTreeWidget->currentColumn())); + + clipboard->setText(copy); +} + + +void BluetoothDevicesDialog::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_bd_addr), -20) + .arg((*i_item)->text(column_number_bd_addr_oui), -20) + .arg((*i_item)->text(column_number_name), -30) + .arg((*i_item)->text(column_number_lmp_version), -20) + .arg((*i_item)->text(column_number_lmp_subversion), -20) + .arg((*i_item)->text(column_number_manufacturer), -30) + .arg((*i_item)->text(column_number_hci_version), -20) + .arg((*i_item)->text(column_number_hci_revision), -20) + .arg((*i_item)->text(column_number_is_local_adapter), -20); + } + + clipboard->setText(copy); +} + +void BluetoothDevicesDialog::tapReset(void *tapinfo_ptr ) +{ + bluetooth_devices_tapinfo_t *tapinfo = (bluetooth_devices_tapinfo_t *) tapinfo_ptr; + BluetoothDevicesDialog *bluetooth_devices_dialog = static_cast<BluetoothDevicesDialog *>(tapinfo->ui); + + + bluetooth_devices_dialog->ui->tableTreeWidget->clear(); +} + +gboolean BluetoothDevicesDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data) +{ + bluetooth_devices_tapinfo_t *tapinfo = static_cast<bluetooth_devices_tapinfo_t *>(tapinfo_ptr); + BluetoothDevicesDialog *dialog = static_cast<BluetoothDevicesDialog *>(tapinfo->ui); + bluetooth_device_tap_t *tap_device = static_cast<bluetooth_device_tap_t *>(const_cast<void *>(data)); + QString bd_addr; + QString bd_addr_oui; + QString name; + const gchar *manuf; + QTreeWidgetItem *item = NULL; + + 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; + } + } + + if (tap_device->has_bd_addr) { + bd_addr.sprintf("%02x:%02x:%02x:%02x:%02x:%02x", tap_device->bd_addr[0], tap_device->bd_addr[1], tap_device->bd_addr[2], tap_device->bd_addr[3], tap_device->bd_addr[4], tap_device->bd_addr[5]); + + manuf = get_ether_name(tap_device->bd_addr); + if (manuf) { + int pos; + + bd_addr_oui = QString(manuf); + pos = bd_addr_oui.indexOf('_'); + if (pos < 0) { + manuf = NULL; + } else { + bd_addr_oui.remove(pos, bd_addr_oui.size()); + } + } + + if (!manuf) + bd_addr_oui = ""; + } + + if (dialog->ui->showInformationStepsCheckBox->checkState() != Qt::Checked) { + QTreeWidgetItemIterator i_item(dialog->ui->tableTreeWidget); + + while (*i_item) { + QTreeWidgetItem *current_item = static_cast<QTreeWidgetItem*>(*i_item); + item_data_t *item_data = current_item->data(0, Qt::UserRole).value<item_data_t *>(); + + if ((tap_device->has_bd_addr && current_item->text(column_number_bd_addr) == bd_addr) || + (tap_device->is_local && + item_data->interface_id == tap_device->interface_id && + item_data->adapter_id == tap_device->adapter_id && + !current_item->text(column_number_is_local_adapter).isEmpty())) { + item = current_item; + break; + } + i_item += 1; + } + } + + if (!item) { + item = new QTreeWidgetItem(dialog->ui->tableTreeWidget); + item->setText(column_number_bd_addr, bd_addr); + item->setText(column_number_bd_addr_oui, bd_addr_oui); + if (tap_device->is_local) { + item->setText(column_number_is_local_adapter, tr("true")); + } + + item_data_t *item_data = wmem_new(wmem_file_scope(), item_data_t); + item_data->interface_id = tap_device->interface_id; + item_data->adapter_id = tap_device->adapter_id; + item_data->frame_number = pinfo->fd->num; + item->setData(0, Qt::UserRole, QVariant::fromValue<item_data_t *>(item_data)); + } + + if (tap_device->type == BLUETOOTH_DEVICE_BD_ADDR) { + item->setText(column_number_bd_addr, bd_addr); + item->setText(column_number_bd_addr_oui, bd_addr_oui); + } + + if (tap_device->type == BLUETOOTH_DEVICE_NAME) + item->setText(column_number_name, tap_device->data.name); + + if (tap_device->type == BLUETOOTH_DEVICE_LOCAL_ADAPTER) + item->setText(column_number_is_local_adapter, tr("true")); + + if (tap_device->type == BLUETOOTH_DEVICE_LOCAL_VERSION) { + item->setText(column_number_hci_version, val_to_str_const(tap_device->data.local_version.hci_version, bthci_evt_hci_version, "Unknown 0x%02x")); + item->setText(column_number_hci_revision, QString("").sprintf("%u", tap_device->data.local_version.hci_revision)); + item->setText(column_number_lmp_version, val_to_str_const(tap_device->data.local_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x")); + item->setText(column_number_lmp_subversion, QString("").sprintf("%u", tap_device->data.local_version.lmp_subversion)); + item->setText(column_number_manufacturer, val_to_str_ext_const(tap_device->data.local_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x")); + } + if (tap_device->type == BLUETOOTH_DEVICE_REMOTE_VERSION) { + item->setText(column_number_lmp_version, val_to_str_const(tap_device->data.remote_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x")); + item->setText(column_number_lmp_subversion, QString("").sprintf("%u", tap_device->data.remote_version.lmp_subversion)); + item->setText(column_number_manufacturer, val_to_str_ext_const(tap_device->data.remote_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x")); + } + + for (int i = 0; i < dialog->ui->tableTreeWidget->columnCount(); i++) { + dialog->ui->tableTreeWidget->resizeColumnToContents(i); + } + + return TRUE; +} + +void BluetoothDevicesDialog::interfaceCurrentIndexChanged(int) +{ + cap_file_.retapPackets(); +} + +void BluetoothDevicesDialog::showInformationStepsChanged(int) +{ + cap_file_.retapPackets(); +} + +void BluetoothDevicesDialog::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 *>(); + + emit goToPacket(item_data->frame_number); + +} + +void BluetoothDevicesDialog::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_bd_addr), -20) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_bd_addr_oui), -20) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_name), -30) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_lmp_version), -20) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_lmp_subversion), -20) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_manufacturer), -30) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_hci_version), -20) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_hci_revision), -20) + .arg(ui->tableTreeWidget->headerItem()->text(column_number_is_local_adapter), -20); + + while (*i_item) { + QTreeWidgetItem *item = static_cast<QTreeWidgetItem*>(*i_item); + copy += QString("%1 %2 %3 %4 %5 %6 %7 %8 %9\n") + .arg(item->text(column_number_bd_addr), -20) + .arg(item->text(column_number_bd_addr_oui), -20) + .arg(item->text(column_number_name), -30) + .arg(item->text(column_number_lmp_version), -20) + .arg(item->text(column_number_lmp_subversion), -20) + .arg(item->text(column_number_manufacturer), -30) + .arg(item->text(column_number_hci_version), -20) + .arg(item->text(column_number_hci_revision), -20) + .arg(item->text(column_number_is_local_adapter), -20); + i_item += 1; + } + + clipboard->setText(copy); +} + +void BluetoothDevicesDialog::on_actionSave_as_image_triggered() +{ + QPixmap image; + + QString fileName = QFileDialog::getSaveFileName(this, tr("Save Table Image"), + "bluetooth_devices_table.png", + tr("PNG Image (*.png)")); + + if (fileName.isEmpty()) return; + + image = QPixmap::grabWidget(ui->tableTreeWidget); + image.save(fileName, "PNG"); +} + +void BluetoothDevicesDialog::on_buttonBox_clicked(QAbstractButton *button _U_) +{ +/* 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: + */ |