summaryrefslogtreecommitdiff
path: root/ui/gtk/main_80211_toolbar.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2012-06-20 17:02:07 +0000
committerAnders Broman <anders.broman@ericsson.com>2012-06-20 17:02:07 +0000
commita2f2c490747cdf36ad9dfb6cc73237a8ed569a21 (patch)
tree8e5f3c84d0bf3beb499c04c1889d979ce2eedcca /ui/gtk/main_80211_toolbar.c
parent9ee113d384fdfb3fefea56e4d9a2fc511b7a729d (diff)
downloadwireshark-a2f2c490747cdf36ad9dfb6cc73237a8ed569a21.tar.gz
Add the toolbar of bug https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6973
sligtly modified to compile on Windows. See if it breaks any other platform. svn path=/trunk/; revision=43411
Diffstat (limited to 'ui/gtk/main_80211_toolbar.c')
-rw-r--r--ui/gtk/main_80211_toolbar.c426
1 files changed, 426 insertions, 0 deletions
diff --git a/ui/gtk/main_80211_toolbar.c b/ui/gtk/main_80211_toolbar.c
new file mode 100644
index 0000000000..ac48654356
--- /dev/null
+++ b/ui/gtk/main_80211_toolbar.c
@@ -0,0 +1,426 @@
+/* main_80211_toolbar.c
+ * The 802.11 toolbar by Pontus Fuchs <pontus.fuchs@gmail.com>
+ *
+ * $Id$
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file implements the "80211" toolbar for Wireshark.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gtk/gtk.h>
+
+#include "epan/prefs.h"
+
+#include "gtkglobals.h"
+#include "stock_icons.h"
+
+#include "main.h"
+#include "main_toolbar.h"
+
+#include "ui/recent.h"
+#include "ui/gtk/old-gtk-compat.h"
+
+#include <ws80211_utils.h>
+#include "capture_sync.h"
+
+static GtkWidget *tb80211_iface_list_box, *tb80211_freq_list_box, *tb80211_chan_type_box, *tb80211_info_label;
+
+static GArray *tb80211_interfaces;
+static struct ws80211_interface *tb80211_current_iface;
+static gint32 tb80211_current_freq = -1;
+static gint32 tb80211_current_type = -1;
+
+static gboolean tb80211_dont_set_chan;
+static gboolean tb80211_dont_set_iface;
+
+static void tb80211_set_info(char *errstr)
+{
+ gtk_label_set_markup(GTK_LABEL(tb80211_info_label), errstr);
+}
+
+static
+void add_channel_type(char *type, int oldtype, int index )
+{
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box), type);
+
+ if (oldtype != -1 && oldtype == ws80211_str_to_chan_type(type)) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_chan_type_box), index);
+ tb80211_current_type = oldtype;
+ }
+}
+
+static
+void tb80211_update_chan_type(void)
+{
+ static unsigned int tb80211_type_cnt;
+ unsigned int i;
+ int oldtype = -1;
+ for (i = 0; i < tb80211_type_cnt; i++) {
+ gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box), 0);
+ }
+
+ if (!tb80211_current_iface) {
+ return;
+ }
+
+ oldtype = tb80211_current_type;
+ tb80211_current_type = -1;
+
+ i = 0;
+ add_channel_type(CHAN_NO_HT, oldtype, i++);
+
+ if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT20)) {
+ add_channel_type(CHAN_HT20, oldtype, i++);
+ }
+ if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT40MINUS)) {
+ add_channel_type(CHAN_HT40MINUS, oldtype, i++);
+ }
+ if (tb80211_current_iface->channel_types & (1 << WS80211_CHAN_HT40PLUS)) {
+ add_channel_type(CHAN_HT40PLUS, oldtype, i++);
+ }
+ tb80211_type_cnt = i;
+}
+
+static
+void tb80211_update_freq(void)
+{
+ static unsigned int tb80211_freq_cnt;
+ unsigned int i;
+ gchar *str;
+ gint32 oldfreq = 0;
+
+ for (i = 0; i < tb80211_freq_cnt; i++) {
+ gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), 0);
+ }
+
+ oldfreq = tb80211_current_freq;
+ tb80211_current_freq = -1;
+
+ if (!tb80211_current_iface)
+ return;
+
+ tb80211_freq_cnt = tb80211_current_iface->frequencies->len;
+ for (i = 0; i < tb80211_freq_cnt; i++) {
+ int freq;
+ freq = g_array_index(tb80211_current_iface->frequencies, int, i);
+ str = g_strdup_printf("%d MHz (%d)", freq, ws80211_frequency_to_channel(freq));
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_freq_list_box), str);
+ g_free(str);
+
+ if (freq == oldfreq) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), i);
+ tb80211_current_freq = oldfreq;
+ }
+ }
+}
+
+static
+void tb80211_update_freq_and_type(void)
+{
+ tb80211_dont_set_chan = TRUE;
+ tb80211_update_freq();
+ tb80211_update_chan_type();
+ tb80211_dont_set_chan = FALSE;
+}
+
+/* Get currently selected channel type type enum */
+static
+int get_selected_channel_type(void)
+{
+ int ret;
+ gchar *s = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tb80211_chan_type_box));
+
+ ret = ws80211_str_to_chan_type(s);
+
+ g_free(s);
+ return ret;
+}
+
+/* Invoke dumpcap to set channel */
+static int
+tb80211_do_set_channel(char *iface, int freq, int type)
+{
+ gchar *freq_s, *type_s;
+ gchar *data, *primary_msg, *secondary_msg;
+ int ret;
+
+ freq_s = g_strdup_printf("%d", freq);
+ type_s = ws80211_chan_type_to_str(type);
+
+ ret = sync_interface_set_80211_chan(iface, freq_s, type_s,
+ &data, &primary_msg, &secondary_msg);
+
+ /* Parse the error msg */
+ if (ret && primary_msg) {
+ return atoi(primary_msg);
+ }
+
+ g_free(data);
+ g_free(primary_msg);
+ g_free(secondary_msg);
+ g_free(freq_s);
+ return ret;
+}
+
+/* Called on freq and type combo box change. */
+static void
+tb80211_set_channel(void)
+{
+ gchar *info = NULL;
+ int err, selected_chan, new_type, new_freq;
+
+ GtkComboBox *freq_combo = GTK_COMBO_BOX(tb80211_freq_list_box);
+
+ GtkComboBox *type_combo = GTK_COMBO_BOX(tb80211_chan_type_box);
+
+ selected_chan = gtk_combo_box_get_active(freq_combo);
+ if (selected_chan < 0)
+ return;
+
+ new_freq = g_array_index(tb80211_current_iface->frequencies, int, selected_chan);
+ new_type = get_selected_channel_type();
+
+ err = tb80211_do_set_channel(tb80211_current_iface->ifname, new_freq, new_type);
+ if (err) {
+ info = g_strdup_printf("<b>Failed to set channel: %s</b>", g_strerror(abs(err)));
+ /* Try to set back to last working chan */
+ err = tb80211_do_set_channel(tb80211_current_iface->ifname, tb80211_current_freq, tb80211_current_type);
+ if (err) {
+ gtk_combo_box_set_active(freq_combo, -1);
+ gtk_combo_box_set_active(type_combo, -1);
+ tb80211_current_freq = -1;
+ tb80211_current_type = -1;
+ }
+ else {
+ tb80211_update_freq_and_type();
+ }
+ }
+ else {
+ info = g_strdup_printf("%s Switched to %d MHz (%d)", tb80211_current_iface->ifname, new_freq, ws80211_frequency_to_channel(new_freq));
+ tb80211_current_freq = new_freq;
+ tb80211_current_type = new_type;
+ }
+ tb80211_set_info(info);
+ g_free(info);
+}
+
+static void
+tb80211_set_chan_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+ if (!tb80211_current_iface || tb80211_dont_set_chan)
+ return;
+
+ tb80211_set_channel();
+}
+
+static void
+tb80211_iface_changed_cb(GtkWidget *widget, gpointer data _U_)
+{
+ unsigned int i;
+ int ret;
+ struct ws80211_interface *iface;
+ struct ws80211_iface_info iface_info;
+ gchar *active;
+ GtkComboBoxText *combo = GTK_COMBO_BOX_TEXT(widget);
+
+ if (tb80211_dont_set_iface)
+ return;
+
+ active = gtk_combo_box_text_get_active_text(combo);
+
+ if (!active || tb80211_dont_set_chan)
+ goto out_free;
+
+ for (i = 0; i < tb80211_interfaces->len; i++) {
+ iface = g_array_index(tb80211_interfaces, struct ws80211_interface *, i);
+ if (strcmp(active, iface->ifname) == 0) {
+ tb80211_current_iface = iface;
+ break;
+ }
+ }
+
+ tb80211_current_freq = -1;
+ tb80211_current_type = -1;
+ if (tb80211_current_iface) {
+ ret = ws80211_get_iface_info(tb80211_current_iface->ifname, &iface_info);
+ if (!ret) {
+ tb80211_current_freq = iface_info.current_freq;
+ tb80211_current_type = iface_info.current_chan_type;
+ }
+ }
+ tb80211_update_freq_and_type();
+
+out_free:
+ g_free(active);
+}
+
+static void
+tb80211_update_interfaces(void)
+{
+ struct ws80211_interface *iface;
+ unsigned int i;
+ gboolean same = FALSE;
+ gchar *selected_iface = NULL, *info;
+
+ if (tb80211_interfaces) {
+ selected_iface = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box));
+
+ for (i = 0; i < tb80211_interfaces->len; i++)
+ gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box), 0);
+
+ ws80211_free_interfaces(tb80211_interfaces);
+ tb80211_interfaces = NULL;
+ tb80211_current_iface = NULL;
+ }
+ tb80211_interfaces = ws80211_find_interfaces();
+
+ if (!tb80211_interfaces) {
+ goto out_free;
+ }
+
+ tb80211_dont_set_iface = TRUE;
+ for (i = 0; i < tb80211_interfaces->len; i++) {
+ iface = g_array_index(tb80211_interfaces, struct ws80211_interface *, i);
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(tb80211_iface_list_box), iface->ifname);
+
+ if (selected_iface && strcmp(selected_iface, iface->ifname) == 0) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_iface_list_box), i);
+ tb80211_current_iface = iface;
+ same = TRUE;
+ }
+ }
+ tb80211_dont_set_iface = FALSE;
+
+ /* Reset selectors if interface disappeared */
+ if (!same) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_iface_list_box), -1);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_freq_list_box), -1);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(tb80211_chan_type_box), -1);
+ }
+
+ info = g_strdup_printf("%d monitor interfaces found", tb80211_interfaces->len);
+ tb80211_set_info(info);
+ g_free(info);
+out_free:
+ g_free(selected_iface);
+}
+
+static void
+tb80211_update_iface_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+ tb80211_update_interfaces();
+}
+
+static void
+tb80211_add_label(gchar *text, GtkWidget *tb)
+{
+ GtkWidget *label;
+ GtkToolItem *label_ti;
+
+ label_ti = gtk_tool_item_new();
+ gtk_widget_show(GTK_WIDGET (label_ti));
+ label = gtk_label_new(text);
+ gtk_widget_show(GTK_WIDGET (label));
+ gtk_container_add(GTK_CONTAINER(label_ti), label);
+ gtk_toolbar_insert(GTK_TOOLBAR(tb), label_ti, -1);
+}
+
+GtkWidget *
+ws80211_toolbar_new(void)
+{
+ GtkWidget *tb80211_tb;
+ GtkToolItem *ti;
+ int ret;
+
+ /* filter toolbar */
+ tb80211_tb = gtk_toolbar_new();
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(tb80211_tb),
+ GTK_ORIENTATION_HORIZONTAL);
+
+ gtk_widget_show(tb80211_tb);
+
+ tb80211_add_label(" Interface: ", tb80211_tb);
+
+ ti = gtk_tool_item_new();
+ gtk_widget_show(GTK_WIDGET (ti));
+ tb80211_iface_list_box = gtk_combo_box_text_new();
+ g_signal_connect(tb80211_iface_list_box, "changed", G_CALLBACK(tb80211_iface_changed_cb), NULL);
+ gtk_container_add(GTK_CONTAINER(ti), tb80211_iface_list_box);
+ gtk_widget_show(GTK_WIDGET (tb80211_iface_list_box));
+ gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
+
+ ti = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
+ gtk_widget_set_tooltip_text(GTK_WIDGET(ti), "Refresh interfaces");
+ g_signal_connect(ti, "clicked", G_CALLBACK(tb80211_update_iface_cb), NULL);
+ gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
+ gtk_widget_show(GTK_WIDGET(ti));
+
+ tb80211_add_label(" Frequency: ", tb80211_tb);
+
+ ti = gtk_tool_item_new();
+ gtk_widget_show(GTK_WIDGET (ti));
+ tb80211_freq_list_box = gtk_combo_box_text_new();
+ g_signal_connect(tb80211_freq_list_box, "changed", G_CALLBACK(tb80211_set_chan_cb), NULL);
+ gtk_container_add(GTK_CONTAINER(ti), tb80211_freq_list_box);
+ gtk_widget_show(GTK_WIDGET (tb80211_freq_list_box));
+ gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
+
+ ti = gtk_tool_item_new();
+ gtk_widget_show(GTK_WIDGET (ti));
+ tb80211_chan_type_box = gtk_combo_box_text_new();
+ g_signal_connect(tb80211_chan_type_box, "changed", G_CALLBACK(tb80211_set_chan_cb), NULL);
+ gtk_container_add(GTK_CONTAINER(ti), tb80211_chan_type_box);
+ gtk_widget_show(GTK_WIDGET (tb80211_chan_type_box));
+ gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
+
+ ti = gtk_separator_tool_item_new();
+ gtk_widget_show(GTK_WIDGET (ti));
+ gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
+
+ ti = gtk_tool_item_new();
+ gtk_widget_show(GTK_WIDGET (ti));
+ tb80211_info_label = gtk_label_new("");
+ gtk_container_add(GTK_CONTAINER(ti), tb80211_info_label);
+ gtk_widget_show(GTK_WIDGET (tb80211_info_label));
+ gtk_toolbar_insert(GTK_TOOLBAR(tb80211_tb), ti, -1);
+
+ /* make current preferences effective */
+ toolbar_redraw_all();
+
+ ret = ws80211_init();
+ if (ret == -ENOTSUP)
+ tb80211_set_info("<b>Wireless support not enabled</b>");
+ else if(ret)
+ tb80211_set_info("<b>Failed to initialize ws80211</b>");
+ else {
+ tb80211_update_interfaces();
+ }
+
+ return tb80211_tb;
+}