From: David Woodhouse <dwmw2@infradead.org>
To: BlueZ development <bluez-devel@lists.sourceforge.net>
Subject: [Bluez-devel] Serial service support for bluez-gnome
Date: Sun, 23 Sep 2007 00:38:49 +0100 [thread overview]
Message-ID: <1190504329.7150.277.camel@pmac.infradead.org> (raw)
This needs a little more work in the support for adding devices -- we
probably want another page in the dialog which shows the services
available on the selected device, and lets you choose which one to
connect to. I've hard-coded it to DUN for now.
It would be nicer if we could print the service ident string, and also
the friendly name of the device we're connecting to. But the former
isn't available, and for the latter I think I need to select a local
adapter to query even if I only want to take it from the cache? I
suppose I could hard-code it to hci0 but that seems a bit wrong.
diff --git a/properties/Makefile.am b/properties/Makefile.am
index 717fc16..f30b11e 100644
--- a/properties/Makefile.am
+++ b/properties/Makefile.am
@@ -4,7 +4,8 @@ bin_PROGRAMS = bluetooth-properties
bluetooth_properties_SOURCES = main.c \
dialog.h dialog.c general.h general.c \
adapter.h adapter.c service.h service.c \
- network.h network.c input.h input.c audio.h audio.c
+ network.h network.c input.h input.c \
+ audio.h audio.c serial.h serial.c
bluetooth_properties_LDADD = $(top_builddir)/common/libcommon.a \
@GCONF_LIBS@ @GTK_LIBS@ @DBUS_LIBS@
diff --git a/properties/service.c b/properties/service.c
index 4a828b3..d2a52de 100644
--- a/properties/service.c
+++ b/properties/service.c
@@ -37,6 +37,7 @@
#include "network.h"
#include "input.h"
#include "audio.h"
+#include "serial.h"
static DBusGConnection *connection = NULL;
static DBusGProxy *manager = NULL;
@@ -45,6 +46,7 @@ static GtkWidget *notebook;
static GtkWidget *page_network;
static GtkWidget *page_input;
static GtkWidget *page_audio;
+static GtkWidget *page_serial;
static GtkListStore *service_store;
@@ -71,6 +73,9 @@ static void show_service(const gchar *identifier)
if (g_ascii_strcasecmp(identifier, "audio") == 0)
widget = page_audio;
+ if (g_ascii_strcasecmp(identifier, "serial") == 0)
+ widget = page_serial;
+
page = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), widget);
if (page < 0) {
gtk_widget_hide(notebook);
@@ -284,6 +289,9 @@ GtkWidget *create_service(void)
page_audio = create_audio();
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_audio, NULL);
+ page_serial = create_serial();
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_serial, NULL);
+
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
g_signal_connect(G_OBJECT(selection), "changed",
@@ -352,6 +360,9 @@ static void service_started(DBusGProxy *object, gpointer user_data)
if (g_ascii_strcasecmp(service->identifier, "audio") == 0)
enable_audio(connection, busname);
+
+ if (g_ascii_strcasecmp(service->identifier, "serial") == 0)
+ enable_serial(connection, busname);
}
static void service_stopped(DBusGProxy *object, gpointer user_data)
@@ -369,6 +380,9 @@ static void service_stopped(DBusGProxy *object, gpointer user_data)
if (g_ascii_strcasecmp(service->identifier, "audio") == 0)
disable_audio();
+
+ if (g_ascii_strcasecmp(service->identifier, "serial") == 0)
+ disable_serial();
}
static void add_service(const char *path)
--- /dev/null 2007-09-21 01:30:37.492000000 +0100
+++ b/properties/serial.h 2007-09-23 00:13:56.000000000 +0100
@@ -0,0 +1,28 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2006-2007 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2007 David Woodhouse <dwmw2@infradead.org>
+ *
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+GtkWidget *create_serial(void);
+void enable_serial(DBusGConnection *conn, const char *busname);
+void disable_serial(void);
--- /dev/null 2007-09-21 01:30:37.492000000 +0100
+++ b/properties/serial.c 2007-09-23 00:13:30.000000000 +0100
@@ -0,0 +1,387 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2005-2007 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2006-2007 Bastien Nocera <hadess@hadess.net>
+ * Copyright (C) 2007 David Woodhouse <dwmw2@infradead.org>
+ *
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <dbus/dbus-glib.h>
+
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+
+#include "client.h"
+
+#include "general.h"
+#include "adapter.h"
+#include "dialog.h"
+#include "serial.h"
+
+static DBusGConnection *connection = NULL;
+static DBusGProxy *manager = NULL;
+static DBusGProxy *serialdevice = NULL;
+
+static GtkListStore *store = NULL;
+static GtkWidget *tree = NULL;
+static GtkWidget *button_remove;
+
+static void proxy_callback(DBusGProxy *proxy,
+ DBusGProxyCall *call, void *user_data)
+{
+ GError *error = NULL;
+ GtkWidget *notebook = user_data;
+ GtkWidget *button;
+ GtkWidget *label;
+ DBusGProxy *client;
+ const char *path, *busname;
+ const char *address = NULL, *device = NULL;
+ gchar *text;
+
+ g_object_set_data(G_OBJECT(notebook), "call", NULL);
+
+ dbus_g_proxy_end_call(proxy, call, &error,
+ G_TYPE_STRING, &path, G_TYPE_INVALID);
+
+ button = g_object_get_data(G_OBJECT(notebook), "cancel");
+ gtk_widget_hide(button);
+
+ button = g_object_get_data(G_OBJECT(notebook), "close");
+ gtk_widget_set_sensitive(button, TRUE);
+
+ label = g_object_get_data(G_OBJECT(notebook), "label");
+
+ if (error) {
+ text = g_strdup_printf("<b>%s: %s</b>",
+ _("Connection failed"), error->message);
+ gtk_label_set_markup(GTK_LABEL(label), text);
+ g_free(text);
+ return;
+ }
+
+ busname = dbus_g_proxy_get_bus_name(proxy);
+
+ client = dbus_g_proxy_new_for_name(connection, busname,
+ path, "org.bluez.serial.Port");
+
+ dbus_g_proxy_call(client, "GetAddress", NULL, G_TYPE_INVALID,
+ G_TYPE_STRING, &address, G_TYPE_INVALID);
+
+ dbus_g_proxy_call(client, "GetDevice", NULL, G_TYPE_INVALID,
+ G_TYPE_STRING, &device, G_TYPE_INVALID);
+
+ text = g_strdup_printf("<b>%s %s %s</b>",
+ address, _("connected as"), device);
+ gtk_label_set_markup(GTK_LABEL(label), text);
+ g_free(text);
+
+ // set_trusted(adapter, address);
+
+ g_object_unref(client);
+}
+
+static void connect_callback(const gchar *address, gpointer user_data)
+{
+ DBusGProxyCall *call;
+
+ call = dbus_g_proxy_begin_call(manager, "CreatePort",
+ proxy_callback, user_data, NULL,
+ G_TYPE_STRING, address,
+ G_TYPE_STRING, "dun", G_TYPE_INVALID);
+
+ g_object_set_data(G_OBJECT(user_data), "call", call);
+}
+
+static void cleanup_callback(gpointer user_data)
+{
+ DBusGProxyCall *call;
+
+ call = g_object_get_data(G_OBJECT(user_data), "call");
+ if (call != NULL)
+ dbus_g_proxy_cancel_call(manager, call);
+
+ g_object_set_data(G_OBJECT(user_data), "call", NULL);
+}
+
+static gboolean device_filter(GtkTreeModel *model,
+ GtkTreeIter *iter, gpointer user_data)
+{
+ gboolean active;
+ guint type;
+
+ gtk_tree_model_get(model, iter, COLUMN_ACTIVE, &active,
+ COLUMN_TYPE, &type, -1);
+
+ if (active == FALSE)
+ return FALSE;
+
+ if (type == BLUETOOTH_TYPE_PHONE || type == BLUETOOTH_TYPE_MODEM)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void create_callback(GtkWidget *button, gpointer user_data)
+{
+ show_device_dialog(connect_callback, cleanup_callback, device_filter);
+}
+
+static void remove_callback(GtkWidget *button, gpointer user_data)
+{
+ GtkTreeSelection *selection = user_data;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gchar *path;
+
+ if (show_remove_dialog() == FALSE)
+ return;
+
+ gtk_tree_selection_get_selected(selection, &model, &iter);
+
+ gtk_tree_model_get(model, &iter, 0, &path, -1);
+
+ dbus_g_proxy_call(manager, "RemovePort", NULL,
+ G_TYPE_STRING, path, G_TYPE_INVALID, G_TYPE_INVALID);
+
+ g_free(path);
+}
+
+static void select_callback(GtkTreeSelection *selection, gpointer user_data)
+{
+ gboolean selected;
+
+ selected = gtk_tree_selection_get_selected(selection, NULL, NULL);
+
+ gtk_widget_set_sensitive(button_remove, selected);
+}
+
+GtkWidget *create_serial(void)
+{
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *scrolled;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
+ GtkWidget *buttonbox;
+ GtkWidget *button;
+
+ vbox = gtk_vbox_new(FALSE, 6);
+
+ label = create_label(_("Serial devices"));
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+ scrolled = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled),
+ GTK_SHADOW_OUT);
+ gtk_container_add(GTK_CONTAINER(vbox), scrolled);
+
+ tree = gtk_tree_view_new();
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store));
+
+ gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree), 0,
+ "Name", gtk_cell_renderer_text_new(),
+ "text", 1, NULL);
+ gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(tree), 0,
+ "Name", gtk_cell_renderer_text_new(),
+ "text", 2, NULL);
+ column = gtk_tree_view_get_column(GTK_TREE_VIEW(tree), 0);
+ gtk_tree_view_column_set_expand(GTK_TREE_VIEW_COLUMN(column), TRUE);
+
+ gtk_container_add(GTK_CONTAINER(scrolled), tree);
+
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
+ g_signal_connect(G_OBJECT(selection), "changed",
+ G_CALLBACK(select_callback), NULL);
+
+ buttonbox = gtk_hbutton_box_new();
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(buttonbox),
+ GTK_BUTTONBOX_START);
+ gtk_box_set_spacing(GTK_BOX(buttonbox), 6);
+ gtk_box_set_homogeneous(GTK_BOX(buttonbox), FALSE);
+ gtk_box_pack_start(GTK_BOX(vbox), buttonbox, FALSE, FALSE, 0);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_ADD);
+ gtk_container_add(GTK_CONTAINER(buttonbox), button);
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(create_callback), NULL);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
+ gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
+ gtk_container_add(GTK_CONTAINER(buttonbox), button);
+
+ button_remove = button;
+
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(remove_callback), selection);
+
+ gtk_widget_show_all(vbox);
+
+ return vbox;
+}
+
+static void add_device(const char *busname, const char *path)
+{
+ DBusGProxy *proxy;
+ const char *address = NULL, *device = NULL;
+ GtkTreeIter iter;
+
+ proxy = dbus_g_proxy_new_for_name(connection, busname,
+ path, "org.bluez.serial.Port");
+
+ dbus_g_proxy_call(proxy, "GetAddress", NULL, G_TYPE_INVALID,
+ G_TYPE_STRING, &address, G_TYPE_INVALID);
+
+ dbus_g_proxy_call(proxy, "GetDevice", NULL, G_TYPE_INVALID,
+ G_TYPE_STRING, &device, G_TYPE_INVALID);
+
+ gtk_list_store_insert_with_values(store, &iter, -1,
+ 0, path, 1, address, 2, device,
+ -1);
+
+ g_object_unref(proxy);
+}
+
+static void device_created(DBusGProxy *object,
+ const char *path, gpointer user_data)
+{
+ const char *busname;
+
+ busname = dbus_g_proxy_get_bus_name(object);
+
+ add_device(busname, path);
+}
+
+static void device_removed(DBusGProxy *object,
+ const char *path, gpointer user_data)
+{
+ GtkTreeIter iter;
+ gboolean cont;
+
+ cont = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
+
+ while (cont == TRUE) {
+ gchar *temp;
+
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &temp, -1);
+
+ if (g_ascii_strcasecmp(path, temp) == 0) {
+ gtk_list_store_remove(store, &iter);
+ g_free(temp);
+ break;
+ }
+
+ g_free(temp);
+
+ cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter);
+ }
+}
+
+static void list_devices(DBusGProxy *object,
+ DBusGProxyCall *call, void *user_data)
+{
+ GError *error = NULL;
+ const gchar **array = NULL;
+ const char *busname;
+
+ dbus_g_proxy_end_call(object, call, &error,
+ G_TYPE_STRV, &array, G_TYPE_INVALID);
+
+ if (error == NULL) {
+ busname = dbus_g_proxy_get_bus_name(object);
+
+ while (*array) {
+ add_device(busname, *array);
+ array++;
+ }
+ } else
+ g_error_free(error);
+}
+
+void enable_serial(DBusGConnection *conn, const char *busname)
+{
+ store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_STRING);
+ if (store == NULL)
+ return;
+
+ if (tree != NULL)
+ gtk_tree_view_set_model(GTK_TREE_VIEW(tree),
+ GTK_TREE_MODEL(store));
+
+ manager = dbus_g_proxy_new_for_name(conn, busname,
+ "/org/bluez/serial", "org.bluez.serial.Manager");
+
+ if (manager == NULL)
+ return;
+
+ connection = dbus_g_connection_ref(conn);
+
+ dbus_g_proxy_add_signal(manager, "PortCreated",
+ G_TYPE_STRING, G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(manager, "PortCreated",
+ G_CALLBACK(device_created), NULL, NULL);
+
+ dbus_g_proxy_add_signal(manager, "PortRemoved",
+ G_TYPE_STRING, G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(manager, "PortRemoved",
+ G_CALLBACK(device_removed), NULL, NULL);
+
+ dbus_g_proxy_begin_call(manager, "ListPorts", list_devices,
+ NULL, NULL, G_TYPE_INVALID);
+}
+
+void disable_serial(void)
+{
+ if (tree != NULL)
+ gtk_tree_view_set_model(GTK_TREE_VIEW(tree), NULL);
+
+ if (store != NULL) {
+ g_object_unref(store);
+ store = NULL;
+ }
+
+ if (manager != NULL) {
+ g_object_unref(manager);
+ manager = NULL;
+ }
+
+ if (serialdevice != NULL) {
+ g_object_unref(serialdevice);
+ serialdevice = NULL;
+ }
+
+ if (connection != NULL) {
+ dbus_g_connection_unref(connection);
+ connection = NULL;
+ }
+}
--
dwmw2
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
next reply other threads:[~2007-09-22 23:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-22 23:38 David Woodhouse [this message]
2007-09-23 16:21 ` [Bluez-devel] Serial service support for bluez-gnome David Woodhouse
2007-09-23 21:27 ` David Woodhouse
2007-10-02 12:15 ` David Woodhouse
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1190504329.7150.277.camel@pmac.infradead.org \
--to=dwmw2@infradead.org \
--cc=bluez-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox