1 /* bluetooth_device_dialog.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  */
9 
10 #include "bluetooth_device_dialog.h"
11 #include <ui_bluetooth_device_dialog.h>
12 
13 #include <ui/qt/utils/color_utils.h>
14 
15 #include "epan/epan.h"
16 #include "epan/addr_resolv.h"
17 #include "epan/to_str.h"
18 #include "epan/epan_dissect.h"
19 #include "epan/prefs.h"
20 #include "epan/dissectors/packet-bthci_cmd.h"
21 #include "epan/dissectors/packet-bthci_evt.h"
22 
23 #include "ui/simple_dialog.h"
24 
25 #include <ui/qt/utils/variant_pointer.h>
26 #include "ui/qt/widgets/wireshark_file_dialog.h"
27 
28 #include <QClipboard>
29 #include <QContextMenuEvent>
30 #include <QPushButton>
31 #include <QTreeWidget>
32 
33 static const int column_number_value = 0;
34 static const int column_number_changes = 1;
35 
36 static const int row_number_bd_addr = 0;
37 static const int row_number_bd_addr_oui = 1;
38 static const int row_number_name = 2;
39 static const int row_number_class_of_device = 3;
40 static const int row_number_lmp_version = 4;
41 static const int row_number_lmp_subversion = 5;
42 static const int row_number_manufacturer = 6;
43 static const int row_number_hci_version = 7;
44 static const int row_number_hci_revision = 8;
45 static const int row_number_scan = 9;
46 static const int row_number_authentication = 10;
47 static const int row_number_encryption = 11;
48 static const int row_number_acl_mtu = 12;
49 static const int row_number_acl_packets = 13;
50 static const int row_number_sco_mtu = 14;
51 static const int row_number_sco_packets = 15;
52 static const int row_number_le_acl_mtu = 16;
53 static const int row_number_le_acl_packets = 17;
54 static const int row_number_le_iso_mtu = 18;
55 static const int row_number_le_iso_packets = 19;
56 static const int row_number_inquiry_mode = 20;
57 static const int row_number_page_timeout = 21;
58 static const int row_number_simple_pairing_mode = 22;
59 static const int row_number_voice_setting = 23;
60 
61 static tap_packet_status
bluetooth_device_tap_packet(void * tapinfo_ptr,packet_info * pinfo,epan_dissect_t * edt,const void * data)62 bluetooth_device_tap_packet(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *edt, const void* data)
63 {
64     bluetooth_device_tapinfo_t *tapinfo = (bluetooth_device_tapinfo_t *) tapinfo_ptr;
65 
66     if (tapinfo->tap_packet)
67         tapinfo->tap_packet(tapinfo, pinfo, edt, data);
68 
69     return TAP_PACKET_REDRAW;
70 }
71 
72 static void
bluetooth_device_tap_reset(void * tapinfo_ptr)73 bluetooth_device_tap_reset(void *tapinfo_ptr)
74 {
75     bluetooth_device_tapinfo_t *tapinfo = (bluetooth_device_tapinfo_t *) tapinfo_ptr;
76 
77     if (tapinfo->tap_reset)
78         tapinfo->tap_reset(tapinfo);
79 }
80 
81 
82 static void
bluetooth_devices_tap(void * data)83 bluetooth_devices_tap(void *data)
84 {
85     GString *error_string;
86 
87     error_string = register_tap_listener("bluetooth.device", data, NULL,
88             0,
89             bluetooth_device_tap_reset,
90             bluetooth_device_tap_packet,
91             NULL,
92             NULL
93             );
94 
95     if (error_string != NULL) {
96         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
97                 "%s", error_string->str);
98         g_string_free(error_string, TRUE);
99     }
100 }
101 
102 
BluetoothDeviceDialog(QWidget & parent,CaptureFile & cf,QString bdAddr,QString name,guint32 interface_id,guint32 adapter_id,gboolean is_local)103 BluetoothDeviceDialog::BluetoothDeviceDialog(QWidget &parent, CaptureFile &cf, QString bdAddr, QString name, guint32 interface_id, guint32 adapter_id, gboolean is_local) :
104     WiresharkDialog(parent, cf),
105     ui(new Ui::BluetoothDeviceDialog)
106 {
107     QString titleBdAddr;
108     QString titleName;
109 
110     ui->setupUi(this);
111     resize(parent.width() * 4 / 10, parent.height() * 2 / 2);
112 
113     setTitle(bdAddr, name);
114 
115     connect(ui->tableWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(tableContextMenu(const QPoint &)));
116 
117     ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
118 
119     ui->tableWidget->setStyleSheet("QTableView::item:hover{background-color:lightyellow; color:black;}");
120 
121     context_menu_.addActions(QList<QAction *>() << ui->actionMark_Unmark_Cell);
122     context_menu_.addActions(QList<QAction *>() << ui->actionMark_Unmark_Row);
123     context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Cell);
124     context_menu_.addActions(QList<QAction *>() << ui->actionCopy_Rows);
125     context_menu_.addActions(QList<QAction *>() << ui->actionCopy_All);
126     context_menu_.addActions(QList<QAction *>() << ui->actionSave_as_image);
127 
128     changes_ = 0;
129 
130     tapinfo_.tap_packet   = tapPacket;
131     tapinfo_.tap_reset    = tapReset;
132     tapinfo_.ui           = this;
133     tapinfo_.is_local     = is_local;
134     tapinfo_.bdAddr       = bdAddr;
135     tapinfo_.interface_id = interface_id;
136     tapinfo_.adapter_id   = adapter_id;
137     tapinfo_.changes      = &changes_;
138 
139     ui->hintLabel->setText(ui->hintLabel->text().arg(changes_));
140 
141     for (int i_row = 0; i_row < ui->tableWidget->rowCount(); i_row += 1) {
142         for (int i_column = 0; i_column < ui->tableWidget->columnCount(); i_column += 1) {
143             QTableWidgetItem *item = new QTableWidgetItem();
144             ui->tableWidget->setItem(i_row, i_column, item);
145         }
146     }
147 
148     bluetooth_devices_tap(&tapinfo_);
149 
150     cap_file_.retapPackets();
151 }
152 
153 
~BluetoothDeviceDialog()154 BluetoothDeviceDialog::~BluetoothDeviceDialog()
155 {
156     delete ui;
157 
158     remove_tap_listener(&tapinfo_);
159 }
160 
setTitle(QString bdAddr,QString name)161 void BluetoothDeviceDialog::setTitle(QString bdAddr, QString name)
162 {
163     QString titleBdAddr;
164     QString titleName;
165 
166     if (bdAddr.isEmpty())
167         titleBdAddr = QString(tr("Unknown"));
168     else
169         titleBdAddr = bdAddr;
170 
171     if (name.isEmpty())
172         titleName = "";
173     else
174         titleName = " ("+name+")";
175 
176     setWindowTitle(tr("Bluetooth Device - %1%2").arg(titleBdAddr).arg(titleName));
177 }
178 
captureFileClosing()179 void BluetoothDeviceDialog::captureFileClosing()
180 {
181     remove_tap_listener(&tapinfo_);
182 
183     WiresharkDialog::captureFileClosing();
184 }
185 
186 
changeEvent(QEvent * event)187 void BluetoothDeviceDialog::changeEvent(QEvent *event)
188 {
189     if (0 != event)
190     {
191         switch (event->type())
192         {
193         case QEvent::LanguageChange:
194             ui->retranslateUi(this);
195             break;
196         default:
197             break;
198         }
199     }
200     QDialog::changeEvent(event);
201 }
202 
203 
keyPressEvent(QKeyEvent * event)204 void BluetoothDeviceDialog::keyPressEvent(QKeyEvent *event)
205 {
206 /* NOTE: Do nothing*, but in real it "takes focus" from button_box so allow user
207  * to use Enter button to jump to frame from tree widget */
208 /* * - reimplement shortcuts from contex menu */
209 
210    if (event->modifiers() & Qt::ControlModifier && event->key()== Qt::Key_M)
211         on_actionMark_Unmark_Row_triggered();
212 }
213 
on_actionMark_Unmark_Cell_triggered()214 void BluetoothDeviceDialog::on_actionMark_Unmark_Cell_triggered()
215 {
216     QTableWidgetItem *current_item = ui->tableWidget->currentItem();
217     if (!current_item)
218         return;
219 
220     QBrush fg;
221     QBrush bg;
222 
223     if (current_item->background() == QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg))) {
224         fg = QBrush();
225         bg = QBrush();
226     } else {
227         fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg));
228         bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg));
229     }
230 
231     current_item->setForeground(fg);
232     current_item->setBackground(bg);
233 }
234 
235 
on_actionMark_Unmark_Row_triggered()236 void BluetoothDeviceDialog::on_actionMark_Unmark_Row_triggered()
237 {
238     QBrush fg;
239     QBrush bg;
240     bool   is_marked = TRUE;
241 
242     QTableWidgetItem *current_item = ui->tableWidget->currentItem();
243     if (!current_item)
244         return;
245 
246     for (int i = 0; i < ui->tableWidget->columnCount(); i += 1) {
247         QTableWidgetItem *item = ui->tableWidget->item(current_item->row(), i);
248         if (item->background() != QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg)))
249             is_marked = FALSE;
250     }
251 
252     if (is_marked) {
253         fg = QBrush();
254         bg = QBrush();
255     } else {
256         fg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_fg));
257         bg = QBrush(ColorUtils::fromColorT(&prefs.gui_marked_bg));
258     }
259 
260     for (int i = 0; i < ui->tableWidget->columnCount(); i += 1) {
261         QTableWidgetItem *item = ui->tableWidget->item(current_item->row(), i);
262         item->setForeground(fg);
263         item->setBackground(bg);
264     }
265 }
266 
267 
tableContextMenu(const QPoint & pos)268 void BluetoothDeviceDialog::tableContextMenu(const QPoint &pos)
269 {
270     context_menu_.exec(ui->tableWidget->viewport()->mapToGlobal(pos));
271 }
272 
on_actionCopy_Cell_triggered()273 void BluetoothDeviceDialog::on_actionCopy_Cell_triggered()
274 {
275     QTableWidgetItem *current_item = ui->tableWidget->currentItem();
276     if (!current_item)
277         return;
278 
279     QClipboard *clipboard = QApplication::clipboard();
280     QString     copy;
281 
282     copy = QString(current_item->text());
283 
284     clipboard->setText(copy);
285 }
286 
on_actionCopy_Rows_triggered()287 void BluetoothDeviceDialog::on_actionCopy_Rows_triggered()
288 {
289     QClipboard                         *clipboard = QApplication::clipboard();
290     QString                             copy;
291     QList<QTableWidgetItem *>           items;
292     QList<QTableWidgetItem *>::iterator i_item;
293 
294     items =  ui->tableWidget->selectedItems();
295 
296     for (i_item = items.begin(); i_item != items.end(); ++i_item) {
297         copy += QString("%1  %2  %3\n")
298                 .arg(ui->tableWidget->verticalHeaderItem((*i_item)->row())->text(), -40)
299                 .arg(ui->tableWidget->item((*i_item)->row(), column_number_value)->text(), -50)
300                 .arg(ui->tableWidget->item((*i_item)->row(), column_number_changes)->text(), -10);
301     }
302 
303     clipboard->setText(copy);
304 }
305 
on_actionCopy_All_triggered()306 void BluetoothDeviceDialog::on_actionCopy_All_triggered()
307 {
308     QClipboard             *clipboard = QApplication::clipboard();
309     QString                 copy;
310 
311     copy += QString("%1  %2  %3\n")
312             .arg("Headers", -40)
313             .arg(ui->tableWidget->horizontalHeaderItem(column_number_value)->text(), -50)
314             .arg(ui->tableWidget->horizontalHeaderItem(column_number_changes)->text(), -10);
315 
316     for (int i_row = 0; i_row < ui->tableWidget->rowCount(); i_row += 1) {
317         for (int i_column = 0; i_column < ui->tableWidget->columnCount(); i_column += 1) {
318 
319         copy += QString("%1  %2  %3\n")
320                 .arg(ui->tableWidget->verticalHeaderItem(i_row)->text(), -40)
321                 .arg(ui->tableWidget->item(i_row, column_number_value)->text(), -50)
322                 .arg(ui->tableWidget->item(i_row, column_number_changes)->text(), -10);
323         }
324     }
325 
326     clipboard->setText(copy);
327 }
328 
329 
330 
tapReset(void * tapinfo_ptr)331 void BluetoothDeviceDialog::tapReset(void *tapinfo_ptr)
332 {
333     bluetooth_device_tapinfo_t *tapinfo = (bluetooth_device_tapinfo_t *) tapinfo_ptr;
334     BluetoothDeviceDialog  *dialog = static_cast<BluetoothDeviceDialog *>(tapinfo->ui);
335 
336     for (int i_row = 0; i_row < dialog->ui->tableWidget->rowCount(); i_row += 1) {
337         for (int i_column = 0; i_column < dialog->ui->tableWidget->columnCount(); i_column += 1) {
338             QTableWidgetItem *item = new QTableWidgetItem();
339             dialog->ui->tableWidget->setItem(i_row, i_column, item);
340         }
341     }
342     *tapinfo->changes = 0;
343 }
344 
updateChanges(QTableWidget * tableWidget,QString value,const int row,guint * changes,packet_info * pinfo)345 void BluetoothDeviceDialog::updateChanges(QTableWidget *tableWidget, QString value, const int row, guint *changes, packet_info *pinfo)
346 {
347     QTableWidgetItem *item = tableWidget->item(row, column_number_value);
348     bluetooth_item_data_t *item_data = VariantPointer<bluetooth_item_data_t>::asPtr(item->data(Qt::UserRole));
349 
350     if (item->text() == value)
351         return;
352 
353     if (item_data->changes == -1) {
354         item_data->changes = 0;
355     } else {
356         *changes += 1;
357         item_data->changes += 1;
358         item_data->frame_number = pinfo->fd->num;
359         tableWidget->item(row, column_number_changes)->setText(QString::number(item_data->changes));
360     }
361 }
362 
saveItemData(QTableWidgetItem * item,bluetooth_device_tap_t * tap_device,packet_info * pinfo)363 void BluetoothDeviceDialog::saveItemData(QTableWidgetItem *item,
364         bluetooth_device_tap_t *tap_device, packet_info *pinfo)
365 {
366     if (item->data(Qt::UserRole).isValid())
367         return;
368 
369     bluetooth_item_data_t *item_data = wmem_new(wmem_file_scope(), bluetooth_item_data_t);
370     item_data->interface_id = tap_device->interface_id;
371     item_data->adapter_id = tap_device->adapter_id;
372     item_data->changes = -1;
373     item_data->frame_number = pinfo->fd->num;
374     item->setData(Qt::UserRole, VariantPointer<bluetooth_item_data_t>::asQVariant(item_data));
375 
376 }
377 
tapPacket(void * tapinfo_ptr,packet_info * pinfo,epan_dissect_t *,const void * data)378 tap_packet_status BluetoothDeviceDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data)
379 {
380     bluetooth_device_tapinfo_t   *tapinfo    = static_cast<bluetooth_device_tapinfo_t *>(tapinfo_ptr);
381     BluetoothDeviceDialog        *dialog     = static_cast<BluetoothDeviceDialog *>(tapinfo->ui);
382     bluetooth_device_tap_t       *tap_device = static_cast<bluetooth_device_tap_t *>(const_cast<void *>(data));
383     QString                       bd_addr;
384     QString                       bd_addr_oui;
385     QString                       name;
386     const gchar                  *manuf;
387     QTableWidget                 *tableWidget;
388     QTableWidgetItem             *item;
389     QString                       field;
390 
391     tableWidget = dialog->ui->tableWidget;
392 
393     if (!((!tap_device->is_local && tap_device->has_bd_addr) || (tap_device->is_local && tapinfo->is_local && tap_device->interface_id == tapinfo->interface_id && tap_device->adapter_id == tapinfo->adapter_id))) {
394         return TAP_PACKET_REDRAW;
395     }
396 
397     if (tap_device->has_bd_addr) {
398         for (int i = 0; i < 6; ++i) {
399             bd_addr += QString("%1:").arg(tap_device->bd_addr[i], 2, 16, QChar('0'));
400         }
401         bd_addr.chop(1); // remove extra character ":" from the end of the string
402         if (!tap_device->is_local && bd_addr != tapinfo->bdAddr)
403             return TAP_PACKET_REDRAW;
404 
405         manuf = get_ether_name(tap_device->bd_addr);
406         if (manuf) {
407             int pos;
408 
409             bd_addr_oui = QString(manuf);
410             pos = bd_addr_oui.indexOf('_');
411             if (pos < 0) {
412                 manuf = NULL;
413             } else {
414                 bd_addr_oui.remove(pos, bd_addr_oui.size());
415             }
416         }
417 
418         if (!manuf)
419             bd_addr_oui = "";
420 
421         item = tableWidget->item(row_number_bd_addr, column_number_value);
422         saveItemData(item, tap_device, pinfo);
423         updateChanges(tableWidget, bd_addr, row_number_bd_addr, tapinfo->changes, pinfo);
424         item->setText(bd_addr);
425 
426         item = tableWidget->item(row_number_bd_addr_oui, column_number_value);
427         saveItemData(item, tap_device, pinfo);
428         updateChanges(tableWidget, bd_addr_oui, row_number_bd_addr_oui, tapinfo->changes, pinfo);
429         item->setText(bd_addr_oui);
430 
431         dialog->setTitle(bd_addr, tableWidget->item(row_number_name, column_number_value)->text());
432     }
433 
434     switch (tap_device->type) {
435     case BLUETOOTH_DEVICE_LOCAL_ADAPTER:
436     case BLUETOOTH_DEVICE_BD_ADDR:
437         break;
438     case BLUETOOTH_DEVICE_NAME:
439         item = tableWidget->item(row_number_name, column_number_value);
440         saveItemData(item, tap_device, pinfo);
441         updateChanges(tableWidget, QString(tap_device->data.name), row_number_name, tapinfo->changes, pinfo);
442 
443         item->setText(tap_device->data.name);
444 
445         dialog->setTitle(tableWidget->item(row_number_bd_addr, column_number_value)->text(), tap_device->data.name);
446 
447         break;
448     case BLUETOOTH_DEVICE_RESET:
449         for (int i_row = 0; i_row < dialog->ui->tableWidget->rowCount(); i_row += 1) {
450             bluetooth_item_data_t       *item_data;
451 
452             item = dialog->ui->tableWidget->item(i_row, column_number_value);
453             saveItemData(item, tap_device, pinfo);
454 
455             item_data = VariantPointer<bluetooth_item_data_t>::asPtr(item->data(Qt::UserRole));
456 
457             if (item_data->changes > -1) {
458                 item_data->changes += 1;
459                 item_data->frame_number = pinfo->fd->num;
460                 dialog->ui->tableWidget->item(i_row, column_number_changes)->setText(QString::number(item_data->changes));
461             } else {
462                 item_data->changes = 0;
463             }
464             dialog->ui->tableWidget->item(i_row, column_number_value)->setText("");
465         }
466         *tapinfo->changes += 1;
467 
468         break;
469     case BLUETOOTH_DEVICE_SCAN:
470         field = QString(val_to_str_const(tap_device->data.scan, bthci_cmd_scan_enable_values, "Unknown 0x%02x"));
471         item = tableWidget->item(row_number_scan, column_number_value);
472         saveItemData(item, tap_device, pinfo);
473         updateChanges(tableWidget, field, row_number_scan, tapinfo->changes, pinfo);
474         item->setText(field);
475         break;
476     case BLUETOOTH_DEVICE_LOCAL_VERSION:
477         field = QString(val_to_str_const(tap_device->data.local_version.hci_version, bthci_evt_hci_version, "Unknown 0x%02x"));
478         item = tableWidget->item(row_number_hci_version, column_number_value);
479         saveItemData(item, tap_device, pinfo);
480         updateChanges(tableWidget, field, row_number_hci_version, tapinfo->changes, pinfo);
481         item->setText(field);
482 
483         field = QString::number(tap_device->data.local_version.hci_revision);
484         item = tableWidget->item(row_number_hci_revision, column_number_value);
485         saveItemData(item, tap_device, pinfo);
486         updateChanges(tableWidget, field, row_number_hci_revision, tapinfo->changes, pinfo);
487         item->setText(field);
488 
489         field = QString(val_to_str_const(tap_device->data.local_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x"));
490         item = tableWidget->item(row_number_lmp_version, column_number_value);
491         saveItemData(item, tap_device, pinfo);
492         updateChanges(tableWidget, field, row_number_lmp_version, tapinfo->changes, pinfo);
493         item->setText(field);
494 
495         field = QString(val_to_str_const(tap_device->data.local_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x"));
496         item = tableWidget->item(row_number_lmp_version, column_number_value);
497         saveItemData(item, tap_device, pinfo);
498         updateChanges(tableWidget, field, row_number_lmp_version, tapinfo->changes, pinfo);
499         item->setText(field);
500 
501         field = QString::number(tap_device->data.local_version.lmp_subversion);
502         item = tableWidget->item(row_number_lmp_subversion, column_number_value);
503         saveItemData(item, tap_device, pinfo);
504         updateChanges(tableWidget, field, row_number_lmp_subversion, tapinfo->changes, pinfo);
505         item->setText(field);
506 
507         field = QString(val_to_str_ext_const(tap_device->data.local_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x"));
508         item = tableWidget->item(row_number_manufacturer, column_number_value);
509         saveItemData(item, tap_device, pinfo);
510         updateChanges(tableWidget, field, row_number_manufacturer, tapinfo->changes, pinfo);
511         item->setText(field);
512 
513         break;
514     case BLUETOOTH_DEVICE_REMOTE_VERSION:
515         field = QString(val_to_str_const(tap_device->data.remote_version.lmp_version, bthci_evt_lmp_version, "Unknown 0x%02x"));
516         item = tableWidget->item(row_number_lmp_version, column_number_value);
517         saveItemData(item, tap_device, pinfo);
518         updateChanges(tableWidget, field, row_number_lmp_version, tapinfo->changes, pinfo);
519         item->setText(field);
520 
521         field = QString::number(tap_device->data.remote_version.lmp_subversion);
522         item = tableWidget->item(row_number_lmp_subversion, column_number_value);
523         saveItemData(item, tap_device, pinfo);
524         updateChanges(tableWidget, field, row_number_lmp_subversion, tapinfo->changes, pinfo);
525         item->setText(field);
526 
527         field = QString(val_to_str_ext_const(tap_device->data.remote_version.manufacturer, &bluetooth_company_id_vals_ext, "Unknown 0x%04x"));
528         item = tableWidget->item(row_number_manufacturer, column_number_value);
529         saveItemData(item, tap_device, pinfo);
530         updateChanges(tableWidget, field, row_number_manufacturer, tapinfo->changes, pinfo);
531         item->setText(field);
532 
533         break;
534     case BLUETOOTH_DEVICE_VOICE_SETTING:
535         field = QString("%1").arg(tap_device->data.voice_setting, 4, 16, QChar('0'));
536         item = tableWidget->item(row_number_voice_setting, column_number_value);
537         saveItemData(item, tap_device, pinfo);
538         updateChanges(tableWidget, field, row_number_voice_setting, tapinfo->changes, pinfo);
539         item->setText(field);
540 
541         break;
542     case BLUETOOTH_DEVICE_CLASS_OF_DEVICE:
543         field = QString("%1").arg(tap_device->data.class_of_device, 6, 16, QChar('0'));
544         item = tableWidget->item(row_number_class_of_device, column_number_value);
545         saveItemData(item, tap_device, pinfo);
546         updateChanges(tableWidget, field, row_number_class_of_device, tapinfo->changes, pinfo);
547         item->setText(field);
548 
549         break;
550     case BLUETOOTH_DEVICE_AUTHENTICATION:
551         field = QString(val_to_str_const(tap_device->data.authentication, bthci_cmd_authentication_enable_values, "Unknown 0x%02x"));
552         item = tableWidget->item(row_number_authentication, column_number_value);
553         saveItemData(item, tap_device, pinfo);
554         updateChanges(tableWidget, field, row_number_authentication, tapinfo->changes, pinfo);
555         item->setText(field);
556 
557         break;
558     case BLUETOOTH_DEVICE_ENCRYPTION:
559         field = QString(val_to_str_const(tap_device->data.encryption, bthci_cmd_encrypt_mode_vals, "Unknown 0x%02x"));
560         item = tableWidget->item(row_number_encryption, column_number_value);
561         saveItemData(item, tap_device, pinfo);
562         updateChanges(tableWidget, field, row_number_encryption, tapinfo->changes, pinfo);
563         item->setText(field);
564 
565         break;
566     case BLUETOOTH_DEVICE_SIMPLE_PAIRING_MODE:
567         field = QString(tap_device->data.encryption ? tr("enabled") : tr("disabled"));
568         item = tableWidget->item(row_number_simple_pairing_mode, column_number_value);
569         saveItemData(item, tap_device, pinfo);
570         updateChanges(tableWidget, field, row_number_simple_pairing_mode, tapinfo->changes, pinfo);
571         item->setText(field);
572 
573         break;
574     case BLUETOOTH_DEVICE_PAGE_TIMEOUT:
575         field = QString(tr("%1 ms (%2 slots)")).arg(tap_device->data.page_timeout * 0.625).arg(tap_device->data.page_timeout);
576         item = tableWidget->item(row_number_page_timeout, column_number_value);
577         saveItemData(item, tap_device, pinfo);
578         updateChanges(tableWidget, field, row_number_page_timeout, tapinfo->changes, pinfo);
579         item->setText(field);
580 
581         break;
582     case BLUETOOTH_DEVICE_INQUIRY_MODE:
583         field = QString(val_to_str_const(tap_device->data.inquiry_mode, bthci_cmd_inq_modes, "Unknown 0x%02x"));
584         item = tableWidget->item(row_number_inquiry_mode, column_number_value);
585         saveItemData(item, tap_device, pinfo);
586         updateChanges(tableWidget, field, row_number_inquiry_mode, tapinfo->changes, pinfo);
587         item->setText(field);
588 
589         break;
590     case BLUETOOTH_DEVICE_MTUS:
591         field = QString::number(tap_device->data.mtus.acl_mtu);
592         item = tableWidget->item(row_number_acl_mtu, column_number_value);
593         saveItemData(item, tap_device, pinfo);
594         updateChanges(tableWidget, field, row_number_acl_mtu, tapinfo->changes, pinfo);
595         item->setText(field);
596 
597         field = QString::number(tap_device->data.mtus.acl_packets);
598         item = tableWidget->item(row_number_acl_packets, column_number_value);
599         saveItemData(item, tap_device, pinfo);
600         updateChanges(tableWidget, field, row_number_acl_packets, tapinfo->changes, pinfo);
601         item->setText(field);
602 
603         field = QString::number(tap_device->data.mtus.sco_mtu);
604         item = tableWidget->item(row_number_sco_mtu, column_number_value);
605         saveItemData(item, tap_device, pinfo);
606         updateChanges(tableWidget, field, row_number_sco_mtu, tapinfo->changes, pinfo);
607         item->setText(field);
608 
609         field = QString::number(tap_device->data.mtus.sco_packets);
610         item = tableWidget->item(row_number_sco_packets, column_number_value);
611         saveItemData(item, tap_device, pinfo);
612         updateChanges(tableWidget, field, row_number_sco_packets, tapinfo->changes, pinfo);
613         item->setText(field);
614 
615         break;
616     case BLUETOOTH_DEVICE_LE_MTU:
617         field = QString::number(tap_device->data.le_mtus.acl_mtu);
618         item = tableWidget->item(row_number_le_acl_mtu, column_number_value);
619         saveItemData(item, tap_device, pinfo);
620         updateChanges(tableWidget, field, row_number_le_acl_mtu, tapinfo->changes, pinfo);
621         item->setText(field);
622 
623         field = QString::number(tap_device->data.le_mtus.acl_packets);
624         item = tableWidget->item(row_number_le_acl_packets, column_number_value);
625         saveItemData(item, tap_device, pinfo);
626         updateChanges(tableWidget, field, row_number_le_acl_packets, tapinfo->changes, pinfo);
627         item->setText(field);
628 
629         field = QString::number(tap_device->data.le_mtus.iso_mtu);
630         item = tableWidget->item(row_number_le_iso_mtu, column_number_value);
631         saveItemData(item, tap_device, pinfo);
632         updateChanges(tableWidget, field, row_number_le_iso_mtu, tapinfo->changes, pinfo);
633         item->setText(field);
634 
635         field = QString::number(tap_device->data.le_mtus.iso_packets);
636         item = tableWidget->item(row_number_le_iso_packets, column_number_value);
637         saveItemData(item, tap_device, pinfo);
638         updateChanges(tableWidget, field, row_number_le_iso_packets, tapinfo->changes, pinfo);
639         item->setText(field);
640 
641         break;
642     }
643 
644     dialog->ui->hintLabel->setText(QString(tr("%1 changes")).arg(*tapinfo->changes));
645 
646     return TAP_PACKET_REDRAW;
647 }
648 
interfaceCurrentIndexChanged(int)649 void BluetoothDeviceDialog::interfaceCurrentIndexChanged(int)
650 {
651     cap_file_.retapPackets();
652 }
653 
showInformationStepsChanged(int)654 void BluetoothDeviceDialog::showInformationStepsChanged(int)
655 {
656     cap_file_.retapPackets();
657 }
658 
659 
on_tableWidget_itemActivated(QTableWidgetItem * item)660 void BluetoothDeviceDialog::on_tableWidget_itemActivated(QTableWidgetItem *item)
661 {
662     if (!cap_file_.isValid())
663         return;
664 
665     if (!item->data(Qt::UserRole).isValid())
666         return;
667 
668     bluetooth_item_data_t *item_data = VariantPointer<bluetooth_item_data_t>::asPtr(item->data(Qt::UserRole));
669 
670     emit goToPacket(item_data->frame_number);
671 
672 }
673 
on_actionSave_as_image_triggered()674 void BluetoothDeviceDialog::on_actionSave_as_image_triggered()
675 {
676     QPixmap image;
677 
678     QString fileName = WiresharkFileDialog::getSaveFileName(this,
679             tr("Save Table Image"),
680             "bluetooth_device_table.png",
681             tr("PNG Image (*.png)"));
682 
683     if (fileName.isEmpty()) return;
684 
685     image = ui->tableWidget->grab();
686     image.save(fileName, "PNG");
687 }
688 
on_buttonBox_clicked(QAbstractButton *)689 void BluetoothDeviceDialog::on_buttonBox_clicked(QAbstractButton *)
690 {
691 
692 }
693