diff options
author | Alexander Orlenko <zxteam@gmail.com> | 2010-06-29 23:21:37 +1100 |
---|---|---|
committer | Alexander Orlenko <zxteam@gmail.com> | 2010-06-29 23:21:37 +1100 |
commit | ebbcda0b861f23e35d7eeab8e39d0ef3dc3c978f (patch) | |
tree | 8b3328628ec9732b6ed4c17f5cbea73cca9a2977 | |
parent | 19bb1d403cf17a0da285ee451f88330c60f28c78 (diff) | |
download | bluez-tools-ebbcda0b861f23e35d7eeab8e39d0ef3dc3c978f.tar.gz |
added agent gobject && started dev. of bt-adapter
-rwxr-xr-x | contrib/gen-dbus-gobject.pl | 19 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/bt-adapter.c | 170 | ||||
-rw-r--r-- | src/bt-agent.c | 0 | ||||
-rw-r--r-- | src/bt-audio.c | 0 | ||||
-rw-r--r-- | src/bt-device.c | 0 | ||||
-rw-r--r-- | src/bt-input.c | 0 | ||||
-rw-r--r-- | src/bt-monitor.c | 8 | ||||
-rw-r--r-- | src/bt-network.c | 0 | ||||
-rw-r--r-- | src/bt-serial.c | 0 | ||||
-rw-r--r-- | src/lib/adapter.c | 17 | ||||
-rw-r--r-- | src/lib/adapter.h | 2 | ||||
-rw-r--r-- | src/lib/agent.c | 118 | ||||
-rw-r--r-- | src/lib/agent.h | 94 | ||||
-rw-r--r-- | src/lib/dbus-common.c | 4 | ||||
-rw-r--r-- | src/lib/device.c | 17 | ||||
-rw-r--r-- | src/lib/device.h | 2 | ||||
-rw-r--r-- | src/lib/helpers.c | 148 | ||||
-rw-r--r-- | src/lib/helpers.h | 42 | ||||
-rw-r--r-- | src/lib/marshallers.list | 6 |
20 files changed, 628 insertions, 23 deletions
diff --git a/contrib/gen-dbus-gobject.pl b/contrib/gen-dbus-gobject.pl index d4db223..379f9c9 100755 --- a/contrib/gen-dbus-gobject.pl +++ b/contrib/gen-dbus-gobject.pl @@ -173,7 +173,8 @@ sub get_g_type { $g_type = 'gboolean ' if $bluez_type eq 'boolean'; $g_type = 'gint32 ' if $bluez_type eq 'int32'; $g_type = 'guint32 ' if $bluez_type eq 'uint32'; - $g_type = 'GPtrArray *' if $bluez_type eq 'array{object}' || $bluez_type eq 'array{string}'; + $g_type = 'GPtrArray *' if $bluez_type eq 'array{object}'; + $g_type = 'gchar **' if $bluez_type eq 'array{string}'; die "unknown bluez type (1): $bluez_type\n" unless defined $g_type; @@ -645,7 +646,7 @@ EOT $properties_changed_handler .= "\t\tg_free(self->priv->$property_var);\n". "\t\tself->priv->$property_var = (gchar *)g_value_dup_boxed(value);\n"; - } elsif ($p{'type'} eq 'array{object}' || $p{'type'} eq 'array{string}') { + } elsif ($p{'type'} eq 'array{object}') { $properties_registration .= "\tpspec = g_param_spec_boxed(\"$property\", NULL, NULL, G_TYPE_PTR_ARRAY, ".($p{'mode'} eq 'readonly' ? 'G_PARAM_READABLE' : 'G_PARAM_READWRITE').");\n"; $properties_init .= "\tif (g_hash_table_lookup(properties, \"$property\")) {\n". @@ -658,6 +659,20 @@ EOT $properties_changed_handler .= "\t\tg_ptr_array_unref(self->priv->$property_var);\n". "\t\tself->priv->$property_var = g_value_dup_boxed(value);\n"; + } elsif ($p{'type'} eq 'array{string}') { + $properties_registration .= "\tpspec = g_param_spec_boxed(\"$property\", NULL, NULL, G_TYPE_STRV, ".($p{'mode'} eq 'readonly' ? 'G_PARAM_READABLE' : 'G_PARAM_READWRITE').");\n"; + $properties_init .= + "\tif (g_hash_table_lookup(properties, \"$property\")) {\n". + "\t\tself->priv->$property_var = (gchar **)g_value_dup_boxed(g_hash_table_lookup(properties, \"$property\"));\n". + "\t} else {\n". + "\t\tself->priv->$property_var = g_new0(char *, 1);\n". + "\t\tself->priv->${property_var}[0] = NULL;\n". + "\t}\n"; + $get_properties .= "\t\tg_value_set_boxed(value, $property_get_method(self));\n"; + $properties_free .= "\tg_strfreev(self->priv->$property_var);\n"; + $properties_changed_handler .= + "\t\tg_strfreev(self->priv->$property_var);\n". + "\t\tself->priv->$property_var = (gchar **)g_value_dup_boxed(value);\n"; } elsif ($p{'type'} eq 'uint32') { $properties_registration .= "\tpspec = g_param_spec_uint(\"$property\", NULL, NULL, 0, 65535, 0, ".($p{'mode'} eq 'readonly' ? 'G_PARAM_READABLE' : 'G_PARAM_READWRITE').");\n"; $properties_init .= diff --git a/src/Makefile.am b/src/Makefile.am index a5391bb..9b70b80 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,6 +15,7 @@ lib_sources = lib/marshallers.c lib/marshallers.h \ lib/dbus-common.c lib/dbus-common.h \ lib/helpers.c lib/helpers.h \ lib/adapter.c lib/adapter.h \ + lib/agent.c lib/agent.h \ lib/audio.c lib/audio.h \ lib/device.c lib/device.h \ lib/input.c lib/input.h \ @@ -22,8 +23,9 @@ lib_sources = lib/marshallers.c lib/marshallers.h \ lib/network.c lib/network.h \ lib/serial.c lib/serial.h -bin_PROGRAMS = bt-monitor +bin_PROGRAMS = bt-monitor bt-adapter bt_monitor_SOURCES = $(lib_sources) bt-monitor.c +bt_adapter_SOURCES = ${lib_sources} bt-adapter.c CLEANFILES = Makefile.in lib/marshallers.c lib/marshallers.h diff --git a/src/bt-adapter.c b/src/bt-adapter.c new file mode 100644 index 0000000..187fe3f --- /dev/null +++ b/src/bt-adapter.c @@ -0,0 +1,170 @@ +/*
+ *
+ * bluez-tools - a set of tools to manage bluetooth devices for linux
+ *
+ * Copyright (C) 2010 Alexander Orlenko <zxteam@gmail.com>
+ *
+ *
+ * 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 <stdlib.h>
+#include <glib.h>
+
+#include "lib/dbus-common.h"
+#include "lib/helpers.h"
+#include "lib/adapter.h"
+#include "lib/device.h"
+#include "lib/manager.h"
+#include "lib/agent.h"
+
+static gboolean stop_discovery(gpointer data) {
+ g_main_loop_quit(data);
+ return FALSE;
+}
+
+static void adapter_device_found(Adapter *adapter, const gchar *address, const GHashTable *values, gpointer data)
+{
+ g_print("device found: %s\n", address);
+}
+
+static void adapter_device_disappeared(Adapter *adapter, const gchar *address, gpointer data)
+{
+ g_print("device disappeared: %s\n", address);
+}
+
+static gboolean list_arg = FALSE;
+static gchar *adapter_arg = NULL;
+static gboolean info_arg = FALSE;
+static gboolean discover_arg = FALSE;
+static gboolean set_arg = FALSE;
+
+static GOptionEntry entries[] = {
+ { "list", 'l', 0, G_OPTION_ARG_NONE, &list_arg, "List all available adapters", NULL},
+ { "adapter", 'a', 0, G_OPTION_ARG_STRING, &adapter_arg, "Adapter name or MAC", "adapter#id"},
+ { "info", 'i', 0, G_OPTION_ARG_NONE, &info_arg, "Show adapter info", NULL},
+ { "discover", 'd', 0, G_OPTION_ARG_NONE, &discover_arg, "Discover remote devices", NULL},
+ { "set", 0, 0, G_OPTION_ARG_NONE, &set_arg, "Set property", NULL},
+ { NULL}
+};
+
+int main(int argc, char *argv[])
+{
+ GError *error = NULL;
+ GOptionContext *context;
+
+ g_type_init();
+
+ context = g_option_context_new("[--set Name Value] - a bluetooth adapter manager");
+ g_option_context_add_main_entries(context, entries, NULL);
+ g_option_context_set_summary(context, "summary");
+ g_option_context_set_description(context, "desc");
+ if (!g_option_context_parse(context, &argc, &argv, &error)) {
+ g_print("%s: %s\n", g_get_prgname(), error->message);
+ g_print("Try `%s --help` for more information.\n", g_get_prgname());
+ exit(EXIT_FAILURE);
+ }
+
+ if (!list_arg && !info_arg && !discover_arg && !set_arg) {
+ g_print("%s", g_option_context_get_help(context, FALSE, NULL));
+ exit(EXIT_FAILURE);
+ }
+
+ g_option_context_free(context);
+
+ if (!dbus_connect(&error)) {
+ g_printerr("Couldn't connect to dbus: %s", error->message);
+ exit(EXIT_FAILURE);
+ }
+
+ Manager *manager = g_object_new(MANAGER_TYPE, NULL);
+
+ if (list_arg) {
+ const GPtrArray *adapters_list = manager_get_adapters(manager);
+ g_return_val_if_fail(adapters_list != NULL, EXIT_FAILURE);
+
+ g_print("Available adapters:\n");
+
+ if (adapters_list->len == 0) {
+ g_print("no adapters found\n");
+ }
+
+ for (int i = 0; i < adapters_list->len; i++) {
+ Adapter *adapter = g_object_new(ADAPTER_TYPE, "DBusObjectPath", g_ptr_array_index(adapters_list, i), NULL);
+ g_print("%s (%s)\n", adapter_get_name(adapter), adapter_get_address(adapter));
+ g_object_unref(adapter);
+ }
+ } else if (info_arg) {
+ Adapter *adapter = find_adapter(adapter_arg, &error);
+ exit_if_error(error);
+
+ g_print("[%s]\n", g_basename(adapter_get_dbus_object_path(adapter)));
+ g_print(" Name: %s [rw]\n", adapter_get_name(adapter));
+ g_print(" Address: %s\n", adapter_get_address(adapter));
+ g_print(" Class: 0x%x\n", adapter_get_class(adapter));
+ g_print(" Discoverable: %d [rw]\n", adapter_get_discoverable(adapter));
+ g_print(" DiscoverableTimeout: %d [rw]\n", adapter_get_discoverable_timeout(adapter));
+ g_print(" Discovering: %d\n", adapter_get_discovering(adapter));
+ g_print(" Pairable: %d [rw]\n", adapter_get_pairable(adapter));
+ g_print(" PairableTimeout: %d [rw]\n", adapter_get_pairable_timeout(adapter));
+ g_print(" Powered: %d [rw]\n", adapter_get_powered(adapter));
+ g_print(" Service(s): [");
+ const gchar **uuids = adapter_get_uuids(adapter);
+ for (int j = 0; uuids[j] != NULL; j++) {
+ if (j > 0) g_print(", ");
+ g_print("%s", uuid2service(uuids[j]));
+ }
+ g_print("]\n");
+ g_object_unref(adapter);
+ } else if (discover_arg) {
+ Adapter *adapter = find_adapter(adapter_arg, &error);
+ exit_if_error(error);
+
+ g_signal_connect(adapter, "DeviceFound", G_CALLBACK(adapter_device_found), NULL);
+ g_signal_connect(adapter, "DeviceDisappeared", G_CALLBACK(adapter_device_disappeared), NULL);
+
+ adapter_start_discovery(adapter, error);
+ exit_if_error(error);
+
+ g_print("Searching...\n");
+
+ GSource *timeout_src = g_timeout_source_new_seconds(60);
+ g_source_attach(timeout_src, NULL);
+ GMainLoop *mainloop = g_main_loop_new(NULL, FALSE);
+ g_source_set_callback(timeout_src, stop_discovery, mainloop, NULL);
+ g_main_loop_run(mainloop);
+ g_main_loop_unref(mainloop);
+ g_source_unref(timeout_src);
+
+ adapter_stop_discovery(adapter, &error);
+ exit_if_error(error);
+
+ g_print("Done\n");
+ } else if (set_arg) {
+ Adapter *adapter = find_adapter(adapter_arg, &error);
+ exit_if_error(error);
+
+ }
+
+ g_object_unref(manager);
+
+ exit(EXIT_SUCCESS);
+}
+
diff --git a/src/bt-agent.c b/src/bt-agent.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bt-agent.c diff --git a/src/bt-audio.c b/src/bt-audio.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bt-audio.c diff --git a/src/bt-device.c b/src/bt-device.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bt-device.c diff --git a/src/bt-input.c b/src/bt-input.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bt-input.c diff --git a/src/bt-monitor.c b/src/bt-monitor.c index 253d7e1..b1ebae2 100644 --- a/src/bt-monitor.c +++ b/src/bt-monitor.c @@ -33,6 +33,7 @@ #include "lib/adapter.h" #include "lib/device.h" #include "lib/manager.h" +#include "lib/agent.h" static gchar *capture_adapter_name = NULL; static GPtrArray *captured_adapters = NULL; @@ -92,7 +93,7 @@ static void adapter_device_disappeared(Adapter *adapter, const gchar *address, g g_print("[ADAPTER] device disappeared: %s\n", address); } -static void adapter_device_found(Adapter *adapter, const gchar *address, gpointer data) +static void adapter_device_found(Adapter *adapter, const gchar *address, const GHashTable *values, gpointer data) { g_print("[ADAPTER] device found: %s\n", address); } @@ -242,7 +243,7 @@ int main(int argc, char *argv[]) Manager *manager = g_object_new(MANAGER_TYPE, NULL); if (capture_adapter_name != NULL) { - Adapter *adapter = find_adapter_by_name(capture_adapter_name, &error); + Adapter *adapter = find_adapter(capture_adapter_name, &error); exit_if_error(error); capture_adapter(adapter); } else { @@ -264,6 +265,9 @@ int main(int argc, char *argv[]) g_signal_connect(manager, "DefaultAdapterChanged", G_CALLBACK(manager_default_adapter_changed), NULL); g_signal_connect(manager, "PropertyChanged", G_CALLBACK(manager_property_changed), NULL); + Agent *agent = g_object_new(AGENT_TYPE, NULL); + g_print("agent registered...\n"); + GMainLoop *mainloop; mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); diff --git a/src/bt-network.c b/src/bt-network.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bt-network.c diff --git a/src/bt-serial.c b/src/bt-serial.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bt-serial.c diff --git a/src/lib/adapter.c b/src/lib/adapter.c index e26f28f..b456d6c 100644 --- a/src/lib/adapter.c +++ b/src/lib/adapter.c @@ -47,7 +47,7 @@ struct _AdapterPrivate { gboolean pairable; guint32 pairable_timeout; gboolean powered; - GPtrArray *uuids; + gchar **uuids; }; G_DEFINE_TYPE(Adapter, adapter, G_TYPE_OBJECT); @@ -105,7 +105,7 @@ static void adapter_dispose(GObject *gobject) g_free(self->priv->address); g_ptr_array_unref(self->priv->devices); g_free(self->priv->name); - g_ptr_array_unref(self->priv->uuids); + g_strfreev(self->priv->uuids); /* Chain up to the parent class */ G_OBJECT_CLASS(adapter_parent_class)->dispose(gobject); @@ -170,7 +170,7 @@ static void adapter_class_init(AdapterClass *klass) g_object_class_install_property(gobject_class, PROP_POWERED, pspec); /* array{string} UUIDs [readonly] */ - pspec = g_param_spec_boxed("UUIDs", NULL, NULL, G_TYPE_PTR_ARRAY, G_PARAM_READABLE); + pspec = g_param_spec_boxed("UUIDs", NULL, NULL, G_TYPE_STRV, G_PARAM_READABLE); g_object_class_install_property(gobject_class, PROP_UUIDS, pspec); /* Signals registation */ @@ -321,9 +321,10 @@ static void adapter_post_init(Adapter *self) /* array{string} UUIDs [readonly] */ if (g_hash_table_lookup(properties, "UUIDs")) { - self->priv->uuids = g_value_dup_boxed(g_hash_table_lookup(properties, "UUIDs")); + self->priv->uuids = (gchar **)g_value_dup_boxed(g_hash_table_lookup(properties, "UUIDs")); } else { - self->priv->uuids = g_ptr_array_new(); + self->priv->uuids = g_new0(char *, 1); + self->priv->uuids[0] = NULL; } g_hash_table_unref(properties); @@ -751,7 +752,7 @@ void adapter_set_powered(Adapter *self, const gboolean value) g_assert(error == NULL); } -const GPtrArray *adapter_get_uuids(Adapter *self) +const gchar **adapter_get_uuids(Adapter *self) { g_assert(ADAPTER_IS(self)); @@ -815,8 +816,8 @@ static void property_changed_handler(DBusGProxy *dbus_g_proxy, const gchar *name } else if (g_strcmp0(name, "Powered") == 0) { self->priv->powered = g_value_get_boolean(value); } else if (g_strcmp0(name, "UUIDs") == 0) { - g_ptr_array_unref(self->priv->uuids); - self->priv->uuids = g_value_dup_boxed(value); + g_strfreev(self->priv->uuids); + self->priv->uuids = (gchar **)g_value_dup_boxed(value); } g_signal_emit(self, signals[PROPERTY_CHANGED], 0, name, value); diff --git a/src/lib/adapter.h b/src/lib/adapter.h index 84b4f1c..9758218 100644 --- a/src/lib/adapter.h +++ b/src/lib/adapter.h @@ -88,7 +88,7 @@ const guint32 adapter_get_pairable_timeout(Adapter *self); void adapter_set_pairable_timeout(Adapter *self, const guint32 value); const gboolean adapter_get_powered(Adapter *self); void adapter_set_powered(Adapter *self, const gboolean value); -const GPtrArray *adapter_get_uuids(Adapter *self); +const gchar **adapter_get_uuids(Adapter *self); #endif /* __ADAPTER_H */ diff --git a/src/lib/agent.c b/src/lib/agent.c new file mode 100644 index 0000000..e14703e --- /dev/null +++ b/src/lib/agent.c @@ -0,0 +1,118 @@ +/* + * + * bluez-tools - a set of tools to manage bluetooth devices for linux + * + * Copyright (C) 2010 Alexander Orlenko <zxteam@gmail.com> + * + * + * 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-common.h" +#include "agent.h" + +#define BLUEZ_DBUS_AGENT_INTERFACE "org.bluez.Agent" + +#define AGENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), AGENT_TYPE, AgentPrivate)) + +struct _AgentPrivate { + DBusGProxy *proxy; +}; + +G_DEFINE_TYPE(Agent, agent, G_TYPE_OBJECT); + +static void agent_dispose(GObject *gobject) +{ + Agent *self = AGENT(gobject); + + dbus_g_connection_unregister_g_object(conn, gobject); + + /* Chain up to the parent class */ + G_OBJECT_CLASS(agent_parent_class)->dispose(gobject); +} + +static void agent_class_init(AgentClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = agent_dispose; + + g_type_class_add_private(klass, sizeof(AgentPrivate)); +} + +static void agent_init(Agent *self) +{ + self->priv = AGENT_GET_PRIVATE(self); + + g_assert(conn != NULL); + + dbus_g_connection_register_g_object(conn, "/Agent", G_OBJECT(self)); +} + +/* Methods */ + +gboolean agent_release(Agent *self, GError **error) +{ + g_print("agent_release\n"); + return TRUE; +} + +gboolean agent_request_pin_code(Agent *self, const gchar *device, gchar **ret, GError **error) +{ + g_print("agent_request_pin_code\n"); + return TRUE; +} + +gboolean agent_request_passkey(Agent *self, const gchar *device, guint *ret, GError **error) +{ + g_print("agent_request_passkey\n"); + return TRUE; +} + +gboolean agent_display_passkey(Agent *self, const gchar *device, guint passkey, guint8 entered, GError **error) +{ + g_print("agent_display_passkey\n"); + return TRUE; +} + +gboolean agent_request_confirmation(Agent *self, const gchar *device, guint passkey, GError **error) +{ + g_print("agent_request_confirmation\n"); + return TRUE; +} + +gboolean agent_authorize(Agent *self, const gchar *device, const gchar *uuid, GError **error) +{ + g_print("agent_authorize\n"); + return TRUE; +} + +gboolean agent_confirm_mode_change(Agent *self, const gchar *mode, GError **error) +{ + g_print("agent_confirm_mode_change\n"); + return TRUE; +} + +gboolean agent_cancel(Agent *self, GError **error) +{ + g_print("agent_cancel\n"); + return TRUE; +} + diff --git a/src/lib/agent.h b/src/lib/agent.h new file mode 100644 index 0000000..49b90dc --- /dev/null +++ b/src/lib/agent.h @@ -0,0 +1,94 @@ +/* + * + * bluez-tools - a set of tools to manage bluetooth devices for linux + * + * Copyright (C) 2010 Alexander Orlenko <zxteam@gmail.com> + * + * + * 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 + * + */ + +#ifndef __AGENT_H +#define __AGENT_H + +#include <glib-object.h> +#include <dbus/dbus-glib.h> + +#include "marshallers.h" + +/* + * Type macros + */ +#define AGENT_TYPE (agent_get_type()) +#define AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AGENT_TYPE, Agent)) +#define AGENT_IS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), AGENT_TYPE)) +#define AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), AGENT_TYPE, AgentClass)) +#define AGENT_IS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), AGENT_TYPE)) +#define AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), AGENT_TYPE, AgentClass)) + +typedef struct _Agent Agent; +typedef struct _AgentClass AgentClass; +typedef struct _AgentPrivate AgentPrivate; + +struct _Agent { + GObject parent_instance; + + /*< private >*/ + AgentPrivate *priv; +}; + +struct _AgentClass { + GObjectClass parent_class; +}; + +/* used by AGENT_TYPE */ +GType agent_get_type(void) G_GNUC_CONST; + +/* + * Method definitions + */ +gboolean agent_release(Agent *self, GError **error); +gboolean agent_request_pin_code(Agent *self, const gchar *device, gchar **ret, GError **error); +gboolean agent_request_passkey(Agent *self, const gchar *device, guint *ret, GError **error); +gboolean agent_display_passkey(Agent *self, const gchar *device, guint passkey, guint8 entered, GError **error); +gboolean agent_request_confirmation(Agent *self, const gchar *device, guint passkey, GError **error); +gboolean agent_authorize(Agent *self, const gchar *device, const gchar *uuid, GError **error); +gboolean agent_confirm_mode_change(Agent *self, const gchar *mode, GError **error); +gboolean agent_cancel(Agent *self, GError **error); + +/* Glue code */ +static const DBusGMethodInfo dbus_glib_agent_methods[] = { + { (GCallback) agent_release, g_cclosure_bluez_marshal_BOOLEAN__POINTER, 0}, + { (GCallback) agent_request_pin_code, g_cclosure_bluez_marshal_BOOLEAN__BOXED_POINTER_POINTER, 27}, + { (GCallback) agent_request_passkey, g_cclosure_bluez_marshal_BOOLEAN__BOXED_POINTER_POINTER, 85}, + { (GCallback) agent_display_passkey, g_cclosure_bluez_marshal_BOOLEAN__BOXED_UINT_UCHAR_POINTER, 143}, + { (GCallback) agent_request_confirmation, g_cclosure_bluez_marshal_BOOLEAN__BOXED_UINT_POINTER, 212}, + { (GCallback) agent_authorize, g_cclosure_bluez_marshal_BOOLEAN__BOXED_STRING_POINTER, 274}, + { (GCallback) agent_confirm_mode_change, g_cclosure_bluez_marshal_BOOLEAN__STRING_POINTER, 323}, + { (GCallback) agent_cancel, g_cclosure_bluez_marshal_BOOLEAN__POINTER, 369}, +}; + +static const DBusGObjectInfo dbus_glib_agent_object_info = { + 0, + dbus_glib_agent_methods, + 8, + "org.bluez.Agent\0Release\0S\0\0org.bluez.Agent\0RequestPinCode\0S\0device\0I\0o\0arg1\0O\0F\0N\0s\0\0org.bluez.Agent\0RequestPasskey\0S\0device\0I\0o\0arg1\0O\0F\0N\0u\0\0org.bluez.Agent\0DisplayPasskey\0S\0device\0I\0o\0passkey\0I\0u\0entered\0I\0y\0\0org.bluez.Agent\0RequestConfirmation\0S\0device\0I\0o\0passkey\0I\0u\0\0org.bluez.Agent\0Authorize\0S\0device\0I\0o\0uuid\0I\0s\0\0org.bluez.Agent\0ConfirmModeChange\0S\0mode\0I\0s\0\0org.bluez.Agent\0Cancel\0S\0\0\0", + "\0", + "\0" +}; + +#endif /* __AGENT_H */ + diff --git a/src/lib/dbus-common.c b/src/lib/dbus-common.c index d7ee6bb..054dc56 100644 --- a/src/lib/dbus-common.c +++ b/src/lib/dbus-common.c @@ -25,6 +25,7 @@ #include <config.h> #endif +#include "agent.h" #include "marshallers.h" #include "dbus-common.h" @@ -40,6 +41,9 @@ gboolean dbus_connect(GError **error) /* Marshallers registration */ dbus_g_object_register_marshaller(g_cclosure_bluez_marshal_VOID__STRING_BOXED, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID); + /* Agent installation */ + dbus_g_object_type_install_info(AGENT_TYPE, &dbus_glib_agent_object_info); + return TRUE; } diff --git a/src/lib/device.c b/src/lib/device.c index d97027b..ca6aca2 100644 --- a/src/lib/device.c +++ b/src/lib/device.c @@ -49,7 +49,7 @@ struct _DevicePrivate { GPtrArray *nodes; gboolean paired; gboolean trusted; - GPtrArray *uuids; + gchar **uuids; }; G_DEFINE_TYPE(Device, device, G_TYPE_OBJECT); @@ -109,7 +109,7 @@ static void device_dispose(GObject *gobject) g_free(self->priv->icon); g_free(self->priv->name); g_ptr_array_unref(self->priv->nodes); - g_ptr_array_unref(self->priv->uuids); + g_strfreev(self->priv->uuids); /* Chain up to the parent class */ G_OBJECT_CLASS(device_parent_class)->dispose(gobject); @@ -182,7 +182,7 @@ static void device_class_init(DeviceClass *klass) g_object_class_install_property(gobject_class, PROP_TRUSTED, pspec); /* array{string} UUIDs [readonly] */ - pspec = g_param_spec_boxed("UUIDs", NULL, NULL, G_TYPE_PTR_ARRAY, G_PARAM_READABLE); + pspec = g_param_spec_boxed("UUIDs", NULL, NULL, G_TYPE_STRV, G_PARAM_READABLE); g_object_class_install_property(gobject_class, PROP_UUIDS, pspec); /* Signals registation */ @@ -336,9 +336,10 @@ static void device_post_init(Device *self) /* array{string} UUIDs [readonly] */ if (g_hash_table_lookup(properties, "UUIDs")) { - self->priv->uuids = g_value_dup_boxed(g_hash_table_lookup(properties, "UUIDs")); + self->priv->uuids = (gchar **)g_value_dup_boxed(g_hash_table_lookup(properties, "UUIDs")); } else { - self->priv->uuids = g_ptr_array_new(); + self->priv->uuids = g_new0(char *, 1); + self->priv->uuids[0] = NULL; } g_hash_table_unref(properties); @@ -679,7 +680,7 @@ void device_set_trusted(Device *self, const gboolean value) g_assert(error == NULL); } -const GPtrArray *device_get_uuids(Device *self) +const gchar **device_get_uuids(Device *self) { g_assert(DEVICE_IS(self)); @@ -743,8 +744,8 @@ static void property_changed_handler(DBusGProxy *dbus_g_proxy, const gchar *name } else if (g_strcmp0(name, "Trusted") == 0) { self->priv->trusted = g_value_get_boolean(value); } else if (g_strcmp0(name, "UUIDs") == 0) { - g_ptr_array_unref(self->priv->uuids); - self->priv->uuids = g_value_dup_boxed(value); + g_strfreev(self->priv->uuids); + self->priv->uuids = (gchar **)g_value_dup_boxed(value); } g_signal_emit(self, signals[PROPERTY_CHANGED], 0, name, value); diff --git a/src/lib/device.h b/src/lib/device.h index 594f691..6e7370a 100644 --- a/src/lib/device.h +++ b/src/lib/device.h @@ -82,7 +82,7 @@ const GPtrArray *device_get_nodes(Device *self); const gboolean device_get_paired(Device *self); const gboolean device_get_trusted(Device *self); void device_set_trusted(Device *self, const gboolean value); -const GPtrArray *device_get_uuids(Device *self); +const gchar **device_get_uuids(Device *self); #endif /* __DEVICE_H */ diff --git a/src/lib/helpers.c b/src/lib/helpers.c new file mode 100644 index 0000000..04c1450 --- /dev/null +++ b/src/lib/helpers.c @@ -0,0 +1,148 @@ +/* + * + * bluez-tools - a set of tools to manage bluetooth devices for linux + * + * Copyright (C) 2010 Alexander Orlenko <zxteam@gmail.com> + * + * + * 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 <string.h> + +#include "helpers.h" +#include "adapter.h" +#include "manager.h" + +Adapter *find_adapter(const gchar *name, GError **error) +{ + gchar *adapter_path = NULL; + Adapter *adapter = NULL; + + Manager *manager = g_object_new(MANAGER_TYPE, NULL); + + // If name is null - return default adapter + if (name == NULL || strlen(name) == 0) { + adapter_path = manager_default_adapter(manager, error); + if (adapter_path) { + adapter = g_object_new(ADAPTER_TYPE, "DBusObjectPath", adapter_path, NULL); + } + } else { + // Try to find by id + adapter_path = manager_find_adapter(manager, name, error); + + // Found + if (adapter_path) { + adapter = g_object_new(ADAPTER_TYPE, "DBusObjectPath", adapter_path, NULL); + } else { + // Try to find by name + const GPtrArray *adapters_list = manager_get_adapters(manager); + g_assert(adapters_list != NULL); + for (int i = 0; i < adapters_list->len; i++) { + adapter = g_object_new(ADAPTER_TYPE, "DBusObjectPath", g_ptr_array_index(adapters_list, i), NULL); + + if (g_strcmp0(name, adapter_get_name(adapter)) == 0) { + if (error) { + g_error_free(*error); + *error = NULL; + } + break; + } + + g_object_unref(adapter); + adapter = NULL; + } + } + } + + g_object_unref(manager); + if (adapter_path) g_free(adapter_path); + + return adapter; +} + +const gchar *uuid2service(const gchar *uuid) +{ + static GHashTable *t = NULL; + if (t == NULL) + { + t = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(t, "00001000-0000-1000-8000-00805f9b34fb", "ServiceDiscoveryServer"); + g_hash_table_insert(t, "00001001-0000-1000-8000-00805f9b34fb", "BrowseGroupDescriptor"); + g_hash_table_insert(t, "00001002-0000-1000-8000-00805f9b34fb", "PublicBrowseGroup"); + g_hash_table_insert(t, "00001101-0000-1000-8000-00805f9b34fb", "SerialPort"); + g_hash_table_insert(t, "00001102-0000-1000-8000-00805f9b34fb", "LANAccessUsingPPP"); + g_hash_table_insert(t, "00001103-0000-1000-8000-00805f9b34fb", "DialupNetworking"); + g_hash_table_insert(t, "00001104-0000-1000-8000-00805f9b34fb", "IrMCSync"); + g_hash_table_insert(t, "00001105-0000-1000-8000-00805f9b34fb", "OBEXObjectPush"); + g_hash_table_insert(t, "00001106-0000-1000-8000-00805f9b34fb", "OBEXFileTransfer"); + g_hash_table_insert(t, "00001107-0000-1000-8000-00805f9b34fb", "IrMCSyncCommand"); + g_hash_table_insert(t, "00001108-0000-1000-8000-00805f9b34fb", "Headset"); + g_hash_table_insert(t, "00001109-0000-1000-8000-00805f9b34fb", "CordlessTelephony"); + g_hash_table_insert(t, "0000110a-0000-1000-8000-00805f9b34fb", "AudioSource"); + g_hash_table_insert(t, "0000110b-0000-1000-8000-00805f9b34fb", "AudioSink"); + g_hash_table_insert(t, "0000110c-0000-1000-8000-00805f9b34fb", "AVRemoteControlTarget"); + g_hash_table_insert(t, "0000110d-0000-1000-8000-00805f9b34fb", "AdvancedAudioDistribution"); + g_hash_table_insert(t, "0000110e-0000-1000-8000-00805f9b34fb", "AVRemoteControl"); + g_hash_table_insert(t, "0000110f-0000-1000-8000-00805f9b34fb", "VideoConferencing"); + g_hash_table_insert(t, "00001110-0000-1000-8000-00805f9b34fb", "Intercom"); + g_hash_table_insert(t, "00001111-0000-1000-8000-00805f9b34fb", "Fax"); + g_hash_table_insert(t, "00001112-0000-1000-8000-00805f9b34fb", "HeadsetAudioGateway"); + g_hash_table_insert(t, "00001113-0000-1000-8000-00805f9b34fb", "WAP"); + g_hash_table_insert(t, "00001114-0000-1000-8000-00805f9b34fb", "WAPClient"); + g_hash_table_insert(t, "00001115-0000-1000-8000-00805f9b34fb", "PANU"); + g_hash_table_insert(t, "00001116-0000-1000-8000-00805f9b34fb", "NAP"); + g_hash_table_insert(t, "00001117-0000-1000-8000-00805f9b34fb", "GN"); + g_hash_table_insert(t, "00001118-0000-1000-8000-00805f9b34fb", "DirectPrinting"); + g_hash_table_insert(t, "00001119-0000-1000-8000-00805f9b34fb", "ReferencePrinting"); + g_hash_table_insert(t, "0000111a-0000-1000-8000-00805f9b34fb", "Imaging"); + g_hash_table_insert(t, "0000111b-0000-1000-8000-00805f9b34fb", "ImagingResponder"); + g_hash_table_insert(t, "0000111c-0000-1000-8000-00805f9b34fb", "ImagingAutomaticArchive"); + g_hash_table_insert(t, "0000111d-0000-1000-8000-00805f9b34fb", "ImagingReferenceObjects"); + g_hash_table_insert(t, "0000111e-0000-1000-8000-00805f9b34fb", "Handsfree"); + g_hash_table_insert(t, "0000111f-0000-1000-8000-00805f9b34fb", "HandsfreeAudioGateway"); + g_hash_table_insert(t, "00001120-0000-1000-8000-00805f9b34fb", "DirectPrintingReferenceObjects"); + g_hash_table_insert(t, "00001121-0000-1000-8000-00805f9b34fb", "ReflectedUI"); + g_hash_table_insert(t, "00001122-0000-1000-8000-00805f9b34fb", "BasicPringing"); + g_hash_table_insert(t, "00001123-0000-1000-8000-00805f9b34fb", "PrintingStatus"); + g_hash_table_insert(t, "00001124-0000-1000-8000-00805f9b34fb", "HumanInterfaceDevice"); + g_hash_table_insert(t, "00001125-0000-1000-8000-00805f9b34fb", "HardcopyCableReplacement"); + g_hash_table_insert(t, "00001126-0000-1000-8000-00805f9b34fb", "HCRPrint"); + g_hash_table_insert(t, "00001127-0000-1000-8000-00805f9b34fb", "HCRScan"); + g_hash_table_insert(t, "00001128-0000-1000-8000-00805f9b34fb", "CommonISDNAccess"); + g_hash_table_insert(t, "00001129-0000-1000-8000-00805f9b34fb", "VideoConferencingGW"); + g_hash_table_insert(t, "0000112a-0000-1000-8000-00805f9b34fb", "UDIMT"); + g_hash_table_insert(t, "0000112b-0000-1000-8000-00805f9b34fb", "UDITA"); + g_hash_table_insert(t, "0000112c-0000-1000-8000-00805f9b34fb", "AudioVideo"); + g_hash_table_insert(t, "0000112d-0000-1000-8000-00805f9b34fb", "SIMAccess"); + g_hash_table_insert(t, "00001200-0000-1000-8000-00805f9b34fb", "PnPInformation"); + g_hash_table_insert(t, "00001201-0000-1000-8000-00805f9b34fb", "GenericNetworking"); + g_hash_table_insert(t, "00001202-0000-1000-8000-00805f9b34fb", "GenericFileTransfer"); + g_hash_table_insert(t, "00001203-0000-1000-8000-00805f9b34fb", "GenericAudio"); + g_hash_table_insert(t, "00001204-0000-1000-8000-00805f9b34fb", "GenericTelephony"); + } + + if (g_hash_table_lookup(t, uuid) != NULL) { + return g_hash_table_lookup(t, uuid); + } else { + return uuid; + } +} + diff --git a/src/lib/helpers.h b/src/lib/helpers.h new file mode 100644 index 0000000..c09911d --- /dev/null +++ b/src/lib/helpers.h @@ -0,0 +1,42 @@ +/* + * + * bluez-tools - a set of tools to manage bluetooth devices for linux + * + * Copyright (C) 2010 Alexander Orlenko <zxteam@gmail.com> + * + * + * 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 + * + */ + +#ifndef __HELPERS_H +#define __HELPERS_H + +#include <glib.h> +#include <dbus/dbus-glib.h> + +#include "adapter.h" + +Adapter *find_adapter(const gchar *name, GError **error); +const gchar *uuid2service(const gchar *uuid); + +#define exit_if_error(error) G_STMT_START{ \ +if (error) { \ + g_printerr("%s\n", error->message); \ + exit(EXIT_FAILURE); \ +}; }G_STMT_END + +#endif /* __HELPERS_H */ + diff --git a/src/lib/marshallers.list b/src/lib/marshallers.list index e72aa4b..4096a34 100644 --- a/src/lib/marshallers.list +++ b/src/lib/marshallers.list @@ -1 +1,7 @@ VOID:STRING,BOXED +BOOLEAN:BOXED,UINT,UCHAR,POINTER +BOOLEAN:BOXED,STRING,POINTER +BOOLEAN:POINTER +BOOLEAN:BOXED,POINTER,POINTER +BOOLEAN:BOXED,UINT,POINTER +BOOLEAN:STRING,POINTER |