546 lines
14 KiB
Diff
546 lines
14 KiB
Diff
From b228f205853a122327a9ce93a75fb88848c02312 Mon Sep 17 00:00:00 2001
|
|
From: Bastien Nocera <hadess@hadess.net>
|
|
Date: Tue, 10 May 2011 18:02:14 +0100
|
|
Subject: [PATCH] adaptername: Move adapter naming into a plugin
|
|
|
|
Moving the adapter naming allows us to use the /etc/machine-info [1]
|
|
pretty hostname, as implemented by hostnamed [2] in systemd.
|
|
|
|
If /etc/machine-info is not present, the adapter name stored
|
|
on disk in /var/lib/bluetooth will be used. If no adapter name
|
|
has been set yet, the default from the main.conf will be used.
|
|
|
|
We don't currently number the name of hci0 if a pretty name is
|
|
available, but we should instead number it if it happens not
|
|
to be the default adapter. As we cannot be told when the default
|
|
adapter changes, we'll behave this way for now.
|
|
|
|
[1]: http://0pointer.de/public/systemd-man/machine-info.html
|
|
[2]: http://www.freedesktop.org/wiki/Software/systemd/hostnamed
|
|
---
|
|
Makefile.am | 3 +
|
|
configure.ac | 4 +
|
|
plugins/adaptername.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++
|
|
src/adapter.c | 107 +++----------------
|
|
src/adapter.h | 2 +-
|
|
src/manager.c | 5 +
|
|
src/manager.h | 1 +
|
|
7 files changed, 319 insertions(+), 92 deletions(-)
|
|
create mode 100644 plugins/adaptername.c
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index 175f8c9..2f3051c 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -218,6 +218,9 @@ EXTRA_DIST += plugins/hal.c plugins/formfactor.c
|
|
builtin_modules += storage
|
|
builtin_sources += plugins/storage.c
|
|
|
|
+builtin_modules += adaptername
|
|
+builtin_sources += plugins/adaptername.c
|
|
+
|
|
if MAEMO6PLUGIN
|
|
builtin_modules += maemo6
|
|
builtin_sources += plugins/maemo6.c
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 111ff01..987b7e1 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -35,6 +35,10 @@ AC_FUNC_PPOLL
|
|
AC_CHECK_LIB(dl, dlopen, dummy=yes,
|
|
AC_MSG_ERROR(dynamic linking loader is required))
|
|
|
|
+AC_CHECK_HEADER([sys/inotify.h],
|
|
+ [AC_DEFINE([HAVE_SYS_INOTIFY_H], 1,
|
|
+ [Define to 1 if you have <sys/inotify.h>.])],
|
|
+ [AC_MSG_ERROR(inotify headers are required and missing)])
|
|
AC_PATH_DBUS
|
|
AC_PATH_GLIB
|
|
AC_PATH_ALSA
|
|
diff --git a/plugins/adaptername.c b/plugins/adaptername.c
|
|
new file mode 100644
|
|
index 0000000..53c67e9
|
|
--- /dev/null
|
|
+++ b/plugins/adaptername.c
|
|
@@ -0,0 +1,289 @@
|
|
+/*
|
|
+ *
|
|
+ * BlueZ - Bluetooth protocol stack for Linux
|
|
+ *
|
|
+ * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.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 <stdlib.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <glib.h>
|
|
+#include <bluetooth/bluetooth.h>
|
|
+
|
|
+#include "plugin.h"
|
|
+#include "hcid.h" /* For main_opts */
|
|
+#include "adapter.h"
|
|
+#include "manager.h"
|
|
+#include "device.h" /* Needed for storage.h */
|
|
+#include "storage.h"
|
|
+#include "log.h"
|
|
+
|
|
+#include <sys/inotify.h>
|
|
+#define EVENT_SIZE (sizeof (struct inotify_event))
|
|
+#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
+
|
|
+#define MACHINE_INFO_DIR "/etc/"
|
|
+#define MACHINE_INFO_FILE "machine-info"
|
|
+
|
|
+static GIOChannel *inotify = NULL;
|
|
+static int watch_fd = -1;
|
|
+
|
|
+/* This file is part of systemd's hostnamed functionality:
|
|
+ * http://0pointer.de/public/systemd-man/machine-info.html
|
|
+ * http://www.freedesktop.org/wiki/Software/systemd/hostnamed
|
|
+ */
|
|
+static char *read_pretty_host_name (void)
|
|
+{
|
|
+ char *contents, *ret;
|
|
+ char **lines;
|
|
+ guint i;
|
|
+
|
|
+ ret = NULL;
|
|
+
|
|
+ if (g_file_get_contents(MACHINE_INFO_DIR MACHINE_INFO_FILE,
|
|
+ &contents, NULL, NULL) == FALSE) {
|
|
+ return NULL;
|
|
+ }
|
|
+ lines = g_strsplit_set(contents, "\r\n", 0);
|
|
+ g_free(contents);
|
|
+
|
|
+ if (lines == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ for (i = 0; lines[i] != NULL; i++) {
|
|
+ if (g_str_has_prefix(lines[i], "PRETTY_HOSTNAME=")) {
|
|
+ ret = g_strdup(lines[i] + strlen("PRETTY_HOSTNAME="));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ g_strfreev(lines);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Device name expansion
|
|
+ * %d - device id
|
|
+ * %h - hostname
|
|
+ */
|
|
+static char *expand_name(char *dst, int size, char *str, int dev_id)
|
|
+{
|
|
+ register int sp, np, olen;
|
|
+ char *opt, buf[10];
|
|
+
|
|
+ if (!str || !dst)
|
|
+ return NULL;
|
|
+
|
|
+ sp = np = 0;
|
|
+ while (np < size - 1 && str[sp]) {
|
|
+ switch (str[sp]) {
|
|
+ case '%':
|
|
+ opt = NULL;
|
|
+
|
|
+ switch (str[sp+1]) {
|
|
+ case 'd':
|
|
+ sprintf(buf, "%d", dev_id);
|
|
+ opt = buf;
|
|
+ break;
|
|
+
|
|
+ case 'h':
|
|
+ opt = main_opts.host_name;
|
|
+ break;
|
|
+
|
|
+ case '%':
|
|
+ dst[np++] = str[sp++];
|
|
+ /* fall through */
|
|
+ default:
|
|
+ sp++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (opt) {
|
|
+ /* substitute */
|
|
+ olen = strlen(opt);
|
|
+ if (np + olen < size - 1)
|
|
+ memcpy(dst + np, opt, olen);
|
|
+ np += olen;
|
|
+ }
|
|
+ sp += 2;
|
|
+ continue;
|
|
+
|
|
+ case '\\':
|
|
+ sp++;
|
|
+ /* fall through */
|
|
+ default:
|
|
+ dst[np++] = str[sp++];
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ dst[np] = '\0';
|
|
+ return dst;
|
|
+}
|
|
+
|
|
+static int adaptername_probe(struct btd_adapter *adapter)
|
|
+{
|
|
+ int current_id;
|
|
+ char name[MAX_NAME_LENGTH + 1];
|
|
+ char *pretty_hostname;
|
|
+ bdaddr_t bdaddr;
|
|
+
|
|
+ current_id = adapter_get_dev_id(adapter);
|
|
+
|
|
+ pretty_hostname = read_pretty_host_name();
|
|
+ if (pretty_hostname != NULL) {
|
|
+ int default_adapter;
|
|
+
|
|
+ default_adapter = manager_get_default_adapter();
|
|
+
|
|
+ /* If it's the first device, let's assume it will
|
|
+ * be the default one, as we're not told when
|
|
+ * the default adapter changes */
|
|
+ if (default_adapter < 0)
|
|
+ default_adapter = current_id;
|
|
+
|
|
+ if (default_adapter != current_id) {
|
|
+ char *str;
|
|
+
|
|
+ /* +1 because we don't want an adapter called "Foobar's laptop #0" */
|
|
+ str = g_strdup_printf ("%s #%d", pretty_hostname, current_id + 1);
|
|
+ DBG("Setting name '%s' for device 'hci%d'", str, current_id);
|
|
+
|
|
+ adapter_update_local_name(adapter, str);
|
|
+ g_free(str);
|
|
+ } else {
|
|
+ DBG("Setting name '%s' for device 'hci%d'", pretty_hostname, current_id);
|
|
+ adapter_update_local_name(adapter, pretty_hostname);
|
|
+ }
|
|
+ g_free(pretty_hostname);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ adapter_get_address(adapter, &bdaddr);
|
|
+
|
|
+ if (read_local_name(&bdaddr, name) < 0) {
|
|
+ expand_name(name, MAX_NAME_LENGTH, main_opts.name,
|
|
+ current_id);
|
|
+ }
|
|
+ DBG("Setting name '%s' for device 'hci%d'", name, current_id);
|
|
+ adapter_update_local_name(adapter, name);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static gboolean handle_inotify_cb(GIOChannel *channel,
|
|
+ GIOCondition condition, gpointer data)
|
|
+{
|
|
+ char buf[EVENT_BUF_LEN];
|
|
+ GIOStatus err;
|
|
+ gsize len, i;
|
|
+ gboolean changed;
|
|
+
|
|
+ changed = FALSE;
|
|
+
|
|
+ err = g_io_channel_read_chars(channel, buf, EVENT_BUF_LEN, &len, NULL);
|
|
+ if (err != G_IO_STATUS_NORMAL) {
|
|
+ error("Error reading inotify event: %d\n", err);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ i = 0;
|
|
+ while (i < len) {
|
|
+ struct inotify_event *pevent = (struct inotify_event *) & buf[i];
|
|
+
|
|
+ /* check that it's ours */
|
|
+ if (pevent->len &&
|
|
+ pevent->name != NULL &&
|
|
+ strcmp(pevent->name, MACHINE_INFO_FILE) == 0) {
|
|
+ changed = TRUE;
|
|
+ }
|
|
+ i += EVENT_SIZE + pevent->len;
|
|
+ }
|
|
+
|
|
+ if (changed != FALSE) {
|
|
+ DBG(MACHINE_INFO_DIR MACHINE_INFO_FILE
|
|
+ " changed, changing names for adapters");
|
|
+ manager_foreach_adapter ((adapter_cb) adaptername_probe, NULL);
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static void adaptername_remove(struct btd_adapter *adapter)
|
|
+{
|
|
+ if (watch_fd >= 0)
|
|
+ close (watch_fd);
|
|
+ if (inotify != NULL)
|
|
+ g_io_channel_shutdown(inotify, FALSE, NULL);
|
|
+}
|
|
+
|
|
+static struct btd_adapter_driver adaptername_driver = {
|
|
+ .name = "adaptername",
|
|
+ .probe = adaptername_probe,
|
|
+ .remove = adaptername_remove,
|
|
+};
|
|
+
|
|
+static int adaptername_init(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = btd_register_adapter_driver(&adaptername_driver);
|
|
+
|
|
+ if (ret == 0) {
|
|
+ int inot_fd;
|
|
+
|
|
+ inot_fd = inotify_init();
|
|
+ if (inot_fd < 0) {
|
|
+ error("Failed to setup inotify");
|
|
+ return 0;
|
|
+ }
|
|
+ watch_fd = inotify_add_watch(inot_fd,
|
|
+ MACHINE_INFO_DIR,
|
|
+ IN_CLOSE_WRITE | IN_DELETE | IN_CREATE);
|
|
+ if (watch_fd < 0) {
|
|
+ error("Failed to setup watch for '%s'",
|
|
+ MACHINE_INFO_DIR);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ inotify = g_io_channel_unix_new(inot_fd);
|
|
+ g_io_channel_set_close_on_unref(inotify, TRUE);
|
|
+ g_io_channel_set_encoding (inotify, NULL, NULL);
|
|
+ g_io_channel_set_flags (inotify, G_IO_FLAG_NONBLOCK, NULL);
|
|
+ g_io_add_watch(inotify, G_IO_IN, handle_inotify_cb, NULL);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void adaptername_exit(void)
|
|
+{
|
|
+ btd_unregister_adapter_driver(&adaptername_driver);
|
|
+}
|
|
+
|
|
+BLUETOOTH_PLUGIN_DEFINE(adaptername, VERSION,
|
|
+ BLUETOOTH_PLUGIN_PRIORITY_LOW, adaptername_init, adaptername_exit)
|
|
diff --git a/src/adapter.c b/src/adapter.c
|
|
index c30febc..5598d17 100644
|
|
--- a/src/adapter.c
|
|
+++ b/src/adapter.c
|
|
@@ -182,64 +182,6 @@ static void dev_info_free(struct remote_dev_info *dev)
|
|
g_free(dev);
|
|
}
|
|
|
|
-/*
|
|
- * Device name expansion
|
|
- * %d - device id
|
|
- */
|
|
-static char *expand_name(char *dst, int size, char *str, int dev_id)
|
|
-{
|
|
- register int sp, np, olen;
|
|
- char *opt, buf[10];
|
|
-
|
|
- if (!str || !dst)
|
|
- return NULL;
|
|
-
|
|
- sp = np = 0;
|
|
- while (np < size - 1 && str[sp]) {
|
|
- switch (str[sp]) {
|
|
- case '%':
|
|
- opt = NULL;
|
|
-
|
|
- switch (str[sp+1]) {
|
|
- case 'd':
|
|
- sprintf(buf, "%d", dev_id);
|
|
- opt = buf;
|
|
- break;
|
|
-
|
|
- case 'h':
|
|
- opt = main_opts.host_name;
|
|
- break;
|
|
-
|
|
- case '%':
|
|
- dst[np++] = str[sp++];
|
|
- /* fall through */
|
|
- default:
|
|
- sp++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (opt) {
|
|
- /* substitute */
|
|
- olen = strlen(opt);
|
|
- if (np + olen < size - 1)
|
|
- memcpy(dst + np, opt, olen);
|
|
- np += olen;
|
|
- }
|
|
- sp += 2;
|
|
- continue;
|
|
-
|
|
- case '\\':
|
|
- sp++;
|
|
- /* fall through */
|
|
- default:
|
|
- dst[np++] = str[sp++];
|
|
- break;
|
|
- }
|
|
- }
|
|
- dst[np] = '\0';
|
|
- return dst;
|
|
-}
|
|
-
|
|
int btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major,
|
|
uint8_t minor)
|
|
{
|
|
@@ -912,10 +854,10 @@ void btd_adapter_class_changed(struct btd_adapter *adapter, uint32_t new_class)
|
|
DBUS_TYPE_UINT32, &new_class);
|
|
}
|
|
|
|
-void adapter_update_local_name(struct btd_adapter *adapter, const char *name)
|
|
+int adapter_update_local_name(struct btd_adapter *adapter, const char *name)
|
|
{
|
|
if (strncmp(name, adapter->name, MAX_NAME_LENGTH) == 0)
|
|
- return;
|
|
+ return 0;
|
|
|
|
strncpy(adapter->name, name, MAX_NAME_LENGTH);
|
|
|
|
@@ -934,38 +876,29 @@ void adapter_update_local_name(struct btd_adapter *adapter, const char *name)
|
|
DBUS_TYPE_STRING, &name_ptr);
|
|
}
|
|
|
|
+ if (adapter->up) {
|
|
+ int err = adapter_ops->set_name(adapter->dev_id, name);
|
|
+ if (err < 0)
|
|
+ return -err;
|
|
+
|
|
+ adapter->name_stored = TRUE;
|
|
+ }
|
|
+
|
|
adapter->name_stored = FALSE;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,
|
|
const char *name, void *data)
|
|
{
|
|
struct btd_adapter *adapter = data;
|
|
- char *name_ptr = adapter->name;
|
|
-
|
|
- if (!g_utf8_validate(name, -1, NULL)) {
|
|
- error("Name change failed: supplied name isn't valid UTF-8");
|
|
- return btd_error_invalid_args(msg);
|
|
- }
|
|
-
|
|
- if (strncmp(name, adapter->name, MAX_NAME_LENGTH) == 0)
|
|
- goto done;
|
|
-
|
|
- strncpy(adapter->name, name, MAX_NAME_LENGTH);
|
|
- write_local_name(&adapter->bdaddr, name);
|
|
- emit_property_changed(connection, adapter->path,
|
|
- ADAPTER_INTERFACE, "Name",
|
|
- DBUS_TYPE_STRING, &name_ptr);
|
|
-
|
|
- if (adapter->up) {
|
|
- int err = adapter_ops->set_name(adapter->dev_id, name);
|
|
- if (err < 0)
|
|
- return btd_error_failed(msg, strerror(-err));
|
|
+ int err;
|
|
|
|
- adapter->name_stored = TRUE;
|
|
- }
|
|
+ err = adapter_update_local_name (adapter, name);
|
|
+ if (err < 0)
|
|
+ return btd_error_failed(msg, strerror(err));
|
|
|
|
-done:
|
|
return dbus_message_new_method_return(msg);
|
|
}
|
|
|
|
@@ -2577,14 +2510,6 @@ gboolean adapter_init(struct btd_adapter *adapter)
|
|
return FALSE;
|
|
}
|
|
|
|
- if (read_local_name(&adapter->bdaddr, adapter->name) < 0)
|
|
- expand_name(adapter->name, MAX_NAME_LENGTH, main_opts.name,
|
|
- adapter->dev_id);
|
|
-
|
|
- if (main_opts.attrib_server)
|
|
- attrib_gap_set(GATT_CHARAC_DEVICE_NAME,
|
|
- (const uint8_t *) adapter->name, strlen(adapter->name));
|
|
-
|
|
sdp_init_services_list(&adapter->bdaddr);
|
|
load_drivers(adapter);
|
|
clear_blocked(adapter);
|
|
diff --git a/src/adapter.h b/src/adapter.h
|
|
index 3526849..13971bf 100644
|
|
--- a/src/adapter.h
|
|
+++ b/src/adapter.h
|
|
@@ -115,7 +115,7 @@ int adapter_remove_found_device(struct btd_adapter *adapter, bdaddr_t *bdaddr);
|
|
void adapter_emit_device_found(struct btd_adapter *adapter,
|
|
struct remote_dev_info *dev);
|
|
void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
|
|
-void adapter_update_local_name(struct btd_adapter *adapter, const char *name);
|
|
+int adapter_update_local_name(struct btd_adapter *adapter, const char *name);
|
|
void adapter_service_insert(struct btd_adapter *adapter, void *rec);
|
|
void adapter_service_remove(struct btd_adapter *adapter, void *rec);
|
|
void btd_adapter_class_changed(struct btd_adapter *adapter,
|
|
diff --git a/src/manager.c b/src/manager.c
|
|
index e805e0c..dedec8b 100644
|
|
--- a/src/manager.c
|
|
+++ b/src/manager.c
|
|
@@ -288,6 +288,11 @@ static void manager_remove_adapter(struct btd_adapter *adapter)
|
|
btd_start_exit_timer();
|
|
}
|
|
|
|
+int manager_get_default_adapter (void)
|
|
+{
|
|
+ return default_adapter_id;
|
|
+}
|
|
+
|
|
void manager_cleanup(DBusConnection *conn, const char *path)
|
|
{
|
|
g_slist_foreach(adapters, (GFunc) manager_remove_adapter, NULL);
|
|
diff --git a/src/manager.h b/src/manager.h
|
|
index 05c38b3..90d3690 100644
|
|
--- a/src/manager.h
|
|
+++ b/src/manager.h
|
|
@@ -41,3 +41,4 @@ struct btd_adapter *btd_manager_register_adapter(int id);
|
|
int btd_manager_unregister_adapter(int id);
|
|
void manager_add_adapter(const char *path);
|
|
void btd_manager_set_did(uint16_t vendor, uint16_t product, uint16_t version);
|
|
+int manager_get_default_adapter (void);
|
|
--
|
|
1.7.5.1
|
|
|