LATER... ei_kerberos_kdc_session_key ...
[wireshark-sm.git] / ui / qt / bluetooth_devices_dialog.cpp
blob17912409f6b2fd1bc23689086dc519a838a51d5e
1 /* bluetooth_devices_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
8 */
10 #include "bluetooth_devices_dialog.h"
11 #include <ui_bluetooth_devices_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_evt.h"
25 #include <ui/qt/utils/variant_pointer.h>
27 #include "ui/simple_dialog.h"
28 #include "ui/qt/widgets/wireshark_file_dialog.h"
30 #include <QClipboard>
31 #include <QContextMenuEvent>
32 #include <QPushButton>
33 #include <QTreeWidget>
35 static const int column_number_bd_addr = 0;
36 static const int column_number_bd_addr_oui = 1;
37 static const int column_number_name = 2;
38 static const int column_number_lmp_version = 3;
39 static const int column_number_lmp_subversion = 4;
40 static const int column_number_manufacturer = 5;
41 static const int column_number_hci_version = 6;
42 static const int column_number_hci_revision = 7;
43 static const int column_number_is_local_adapter = 8;
46 static tap_packet_status
47 bluetooth_device_tap_packet(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *edt, const void* data, tap_flags_t flags)
49 bluetooth_devices_tapinfo_t *tapinfo = (bluetooth_devices_tapinfo_t *) tapinfo_ptr;
51 if (tapinfo->tap_packet)
52 tapinfo->tap_packet(tapinfo, pinfo, edt, data, flags);
54 return TAP_PACKET_REDRAW;
57 static void
58 bluetooth_device_tap_reset(void *tapinfo_ptr)
60 bluetooth_devices_tapinfo_t *tapinfo = (bluetooth_devices_tapinfo_t *) tapinfo_ptr;
62 if (tapinfo->tap_reset)
63 tapinfo->tap_reset(tapinfo);
66 BluetoothDevicesDialog::BluetoothDevicesDialog(QWidget &parent, CaptureFile &cf, PacketList *packet_list) :
67 WiresharkDialog(parent, cf),
68 ui(new Ui::BluetoothDevicesDialog)
70 ui->setupUi(this);
71 loadGeometry(parent.width() * 4 / 5, parent.height() * 2 / 3);
73 packet_list_ = packet_list;
75 connect(ui->tableTreeWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(tableContextMenu(const QPoint &)));
76 connect(ui->tableTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(tableItemDoubleClicked(QTreeWidgetItem *, int)));
77 connect(ui->interfaceComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(interfaceCurrentIndexChanged(int)));
78 connect(ui->showInformationStepsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(showInformationStepsChanged(int)));
80 ui->tableTreeWidget->sortByColumn(column_number_bd_addr, Qt::AscendingOrder);
82 ui->tableTreeWidget->setStyleSheet("QTreeView::item:hover{background-color:lightyellow; color:black;}");
84 context_menu_.addActions(QList<QAction *>() << ui->actionMark_Unmark_Cell);
85 context_menu_.addActions(QList<QAction *>() << ui->actionMark_Unmark_Row);
86 context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Cell);
87 context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Rows);
88 context_menu_.addActions(QList<QAction *>() << ui->actionCopy_All);
89 context_menu_.addActions(QList<QAction *>() << ui->actionSave_as_image);
91 tapinfo_.tap_packet = tapPacket;
92 tapinfo_.tap_reset = tapReset;
93 tapinfo_.ui = this;
95 registerTapListener("bluetooth.device", &tapinfo_, NULL,
97 bluetooth_device_tap_reset,
98 bluetooth_device_tap_packet,
99 NULL
101 ui->hintLabel->setText(ui->hintLabel->text().arg(0));
103 cap_file_.retapPackets();
107 BluetoothDevicesDialog::~BluetoothDevicesDialog()
109 delete ui;
113 void BluetoothDevicesDialog::captureFileClosed()
115 ui->interfaceComboBox->setEnabled(false);
116 ui->showInformationStepsCheckBox->setEnabled(false);
118 WiresharkDialog::captureFileClosed();
122 void BluetoothDevicesDialog::changeEvent(QEvent *event)
124 if (0 != event)
126 switch (event->type())
128 case QEvent::LanguageChange:
129 ui->retranslateUi(this);
130 break;
131 default:
132 break;
135 QDialog::changeEvent(event);
139 void BluetoothDevicesDialog::keyPressEvent(QKeyEvent *event)
141 /* NOTE: Do nothing*, but in real it "takes focus" from button_box so allow user
142 * to use Enter button to jump to frame from tree widget */
143 /* * - reimplement shortcuts from contex menu */
145 if (event->modifiers() & Qt::ControlModifier && event->key()== Qt::Key_M)
146 on_actionMark_Unmark_Row_triggered();
150 void BluetoothDevicesDialog::tableContextMenu(const QPoint &pos)
152 context_menu_.popup(ui->tableTreeWidget->viewport()->mapToGlobal(pos));
155 void BluetoothDevicesDialog::tableItemDoubleClicked(QTreeWidgetItem *item, int)
157 bluetooth_item_data_t *item_data;
158 BluetoothDeviceDialog *bluetooth_device_dialog;
160 item_data = VariantPointer<bluetooth_item_data_t>::asPtr(item->data(0, Qt::UserRole));
161 bluetooth_device_dialog = new BluetoothDeviceDialog(*this, cap_file_, item->text(column_number_bd_addr), item->text(column_number_name), item_data->interface_id, item_data->adapter_id, !item->text(column_number_is_local_adapter).isEmpty());
162 connect(bluetooth_device_dialog, SIGNAL(goToPacket(int)),
163 packet_list_, SLOT(goToPacket(int)));
164 bluetooth_device_dialog->show();
168 void BluetoothDevicesDialog::on_actionMark_Unmark_Cell_triggered()
170 QBrush fg;
171 QBrush bg;
173 if (ui->tableTreeWidget->currentItem()->background(ui->tableTreeWidget->currentColumn()) == QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) {
174 fg = QBrush();
175 bg = QBrush();
176 } else {
177 fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg));
178 bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg));
181 ui->tableTreeWidget->currentItem()->setForeground(ui->tableTreeWidget->currentColumn(), fg);
182 ui->tableTreeWidget->currentItem()->setBackground(ui->tableTreeWidget->currentColumn(), bg);
186 void BluetoothDevicesDialog::on_actionMark_Unmark_Row_triggered()
188 QBrush fg;
189 QBrush bg;
190 bool is_marked = true;
192 for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) {
193 if (ui->tableTreeWidget->currentItem()->background(i) != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg)))
194 is_marked = false;
197 if (is_marked) {
198 fg = QBrush();
199 bg = QBrush();
200 } else {
201 fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg));
202 bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg));
205 for (int i = 0; i < ui->tableTreeWidget->columnCount(); i += 1) {
206 ui->tableTreeWidget->currentItem()->setForeground(i, fg);
207 ui->tableTreeWidget->currentItem()->setBackground(i, bg);
212 void BluetoothDevicesDialog::on_actionCopy_Cell_triggered()
214 QClipboard *clipboard = QApplication::clipboard();
215 QString copy;
217 copy = QString(ui->tableTreeWidget->currentItem()->text(ui->tableTreeWidget->currentColumn()));
219 clipboard->setText(copy);
223 void BluetoothDevicesDialog::on_actionCopy_Rows_triggered()
225 QClipboard *clipboard = QApplication::clipboard();
226 QString copy;
227 QList<QTreeWidgetItem *> items;
228 QList<QTreeWidgetItem *>::iterator i_item;
230 items = ui->tableTreeWidget->selectedItems();
232 for (i_item = items.begin(); i_item != items.end(); ++i_item) {
233 copy += QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
234 .arg((*i_item)->text(column_number_bd_addr), -20)
235 .arg((*i_item)->text(column_number_bd_addr_oui), -20)
236 .arg((*i_item)->text(column_number_name), -30)
237 .arg((*i_item)->text(column_number_lmp_version), -20)
238 .arg((*i_item)->text(column_number_lmp_subversion), -20)
239 .arg((*i_item)->text(column_number_manufacturer), -30)
240 .arg((*i_item)->text(column_number_hci_version), -20)
241 .arg((*i_item)->text(column_number_hci_revision), -20)
242 .arg((*i_item)->text(column_number_is_local_adapter), -20);
245 clipboard->setText(copy);
248 void BluetoothDevicesDialog::tapReset(void *tapinfo_ptr)
250 bluetooth_devices_tapinfo_t *tapinfo = (bluetooth_devices_tapinfo_t *) tapinfo_ptr;
251 BluetoothDevicesDialog *bluetooth_devices_dialog = static_cast<BluetoothDevicesDialog *>(tapinfo->ui);
253 bluetooth_devices_dialog->ui->tableTreeWidget->clear();
256 tap_packet_status BluetoothDevicesDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data, tap_flags_t)
258 bluetooth_devices_tapinfo_t *tapinfo = static_cast<bluetooth_devices_tapinfo_t *>(tapinfo_ptr);
259 BluetoothDevicesDialog *dialog = static_cast<BluetoothDevicesDialog *>(tapinfo->ui);
260 bluetooth_device_tap_t *tap_device = static_cast<bluetooth_device_tap_t *>(const_cast<void *>(data));
261 QString bd_addr;
262 QString bd_addr_oui;
263 const char *manuf;
264 QTreeWidgetItem *item = NULL;
266 if (dialog->file_closed_)
267 return TAP_PACKET_DONT_REDRAW;
269 if (pinfo->rec->rec_type != REC_TYPE_PACKET)
270 return TAP_PACKET_DONT_REDRAW;
272 if (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) {
273 char *interface;
274 const char *interface_name;
276 unsigned section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0;
277 interface_name = epan_get_interface_name(pinfo->epan, pinfo->rec->rec_header.packet_header.interface_id, section_number);
278 interface = wmem_strdup_printf(pinfo->pool, "%u: %s", pinfo->rec->rec_header.packet_header.interface_id, interface_name);
280 if (dialog->ui->interfaceComboBox->findText(interface) == -1)
281 dialog->ui->interfaceComboBox->addItem(interface);
283 if (interface && dialog->ui->interfaceComboBox->currentIndex() > 0) {
284 if (dialog->ui->interfaceComboBox->currentText() != interface)
285 return TAP_PACKET_REDRAW;
289 if (tap_device->has_bd_addr) {
290 for (int i = 0; i < 6; ++i) {
291 bd_addr += QStringLiteral("%1:").arg(tap_device->bd_addr[i], 2, 16, QChar('0'));
293 bd_addr.chop(1); // remove extra character ":" from the end of the string
294 manuf = get_ether_name(tap_device->bd_addr);
295 if (manuf) {
296 int pos;
298 bd_addr_oui = QString(manuf);
299 pos = static_cast<int>(bd_addr_oui.indexOf('_'));
300 if (pos < 0) {
301 manuf = NULL;
302 } else {
303 bd_addr_oui.remove(pos, bd_addr_oui.size());
307 if (!manuf)
308 bd_addr_oui = "";
311 if (dialog->ui->showInformationStepsCheckBox->checkState() != Qt::Checked) {
312 QTreeWidgetItemIterator i_item(dialog->ui->tableTreeWidget);
314 while (*i_item) {
315 QTreeWidgetItem *current_item = static_cast<QTreeWidgetItem*>(*i_item);
316 bluetooth_item_data_t *item_data = VariantPointer<bluetooth_item_data_t>::asPtr(current_item->data(0, Qt::UserRole));
318 if ((tap_device->has_bd_addr && current_item->text(column_number_bd_addr) == bd_addr) ||
319 (tap_device->is_local &&
320 item_data->interface_id == tap_device->interface_id &&
321 item_data->adapter_id == tap_device->adapter_id &&
322 !current_item->text(column_number_is_local_adapter).isEmpty())) {
323 item = current_item;
324 break;
326 ++i_item;
330 if (!item) {
331 item = new QTreeWidgetItem(dialog->ui->tableTreeWidget);
332 item->setText(column_number_bd_addr, bd_addr);
333 item->setText(column_number_bd_addr_oui, bd_addr_oui);
334 if (tap_device->is_local) {
335 item->setText(column_number_is_local_adapter, tr("true"));
338 bluetooth_item_data_t *item_data = wmem_new(wmem_file_scope(), bluetooth_item_data_t);
339 item_data->interface_id = tap_device->interface_id;
340 item_data->adapter_id = tap_device->adapter_id;
341 item_data->frame_number = pinfo->num;
342 item->setData(0, Qt::UserRole, VariantPointer<bluetooth_item_data_t>::asQVariant(item_data));
345 if (tap_device->type == BLUETOOTH_DEVICE_BD_ADDR) {
346 item->setText(column_number_bd_addr, bd_addr);
347 item->setText(column_number_bd_addr_oui, bd_addr_oui);
350 if (tap_device->type == BLUETOOTH_DEVICE_NAME) {
351 item->setText(column_number_name, tap_device->data.name);
354 if (tap_device->type == BLUETOOTH_DEVICE_LOCAL_ADAPTER)
355 item->setText(column_number_is_local_adapter, tr("true"));
357 if (tap_device->type == BLUETOOTH_DEVICE_LOCAL_VERSION) {
358 item->setText(column_number_hci_version, val_to_str_const(tap_device->data.local_version.hci_version, bthci_evt_hci_version, "Unknown 0x%02x"));
359 item->setText(column_number_hci_revision, QString::number(tap_device->data.local_version.hci_revision));
360 item->setText(column_number_lmp_version, val_to_str_const(tap_device->data.local_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x"));
361 item->setText(column_number_lmp_subversion, QString::number(tap_device->data.local_version.lmp_subversion));
362 item->setText(column_number_manufacturer, val_to_str_ext_const(tap_device->data.local_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x"));
364 if (tap_device->type == BLUETOOTH_DEVICE_REMOTE_VERSION) {
365 item->setText(column_number_lmp_version, val_to_str_const(tap_device->data.remote_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x"));
366 item->setText(column_number_lmp_subversion, QString::number(tap_device->data.remote_version.lmp_subversion));
367 item->setText(column_number_manufacturer, val_to_str_ext_const(tap_device->data.remote_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x"));
370 for (int i = 0; i < dialog->ui->tableTreeWidget->columnCount(); i++) {
371 dialog->ui->tableTreeWidget->resizeColumnToContents(i);
374 dialog->ui->hintLabel->setText(tr("%1 items; Right click for more option; Double click for device details").arg(dialog->ui->tableTreeWidget->topLevelItemCount()));
376 return TAP_PACKET_REDRAW;
379 void BluetoothDevicesDialog::interfaceCurrentIndexChanged(int)
381 cap_file_.retapPackets();
384 void BluetoothDevicesDialog::showInformationStepsChanged(int)
386 cap_file_.retapPackets();
389 void BluetoothDevicesDialog::on_tableTreeWidget_itemActivated(QTreeWidgetItem *item, int)
391 if (file_closed_)
392 return;
394 bluetooth_item_data_t *item_data = VariantPointer<bluetooth_item_data_t>::asPtr(item->data(0, Qt::UserRole));
396 emit goToPacket(item_data->frame_number);
400 void BluetoothDevicesDialog::on_actionCopy_All_triggered()
402 QClipboard *clipboard = QApplication::clipboard();
403 QString copy;
404 QTreeWidgetItemIterator i_item(ui->tableTreeWidget);
405 QTreeWidgetItem *item;
407 item = ui->tableTreeWidget->headerItem();
409 copy += QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
410 .arg(item->text(column_number_bd_addr), -20)
411 .arg(item->text(column_number_bd_addr_oui), -20)
412 .arg(item->text(column_number_name), -30)
413 .arg(item->text(column_number_lmp_version), -20)
414 .arg(item->text(column_number_lmp_subversion), -20)
415 .arg(item->text(column_number_manufacturer), -30)
416 .arg(item->text(column_number_hci_version), -20)
417 .arg(item->text(column_number_hci_revision), -20)
418 .arg(item->text(column_number_is_local_adapter), -20);
420 while (*i_item) {
421 item = static_cast<QTreeWidgetItem*>(*i_item);
422 copy += QStringLiteral("%1 %2 %3 %4 %5 %6 %7 %8 %9\n")
423 .arg(item->text(column_number_bd_addr), -20)
424 .arg(item->text(column_number_bd_addr_oui), -20)
425 .arg(item->text(column_number_name), -30)
426 .arg(item->text(column_number_lmp_version), -20)
427 .arg(item->text(column_number_lmp_subversion), -20)
428 .arg(item->text(column_number_manufacturer), -30)
429 .arg(item->text(column_number_hci_version), -20)
430 .arg(item->text(column_number_hci_revision), -20)
431 .arg(item->text(column_number_is_local_adapter), -20);
432 ++i_item;
435 clipboard->setText(copy);
438 void BluetoothDevicesDialog::on_actionSave_as_image_triggered()
440 QPixmap image;
442 QString fileName = WiresharkFileDialog::getSaveFileName(this,
443 tr("Save Table Image"),
444 "bluetooth_devices_table.png",
445 tr("PNG Image (*.png)"));
447 if (fileName.isEmpty()) return;
449 image = ui->tableTreeWidget->grab();
450 image.save(fileName, "PNG");
453 void BluetoothDevicesDialog::on_buttonBox_clicked(QAbstractButton *)
455 /* if (button == foo_button_) */