mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-12-02 08:34:26 +08:00
6960cb73b2
If pretty hostname is not set fallback to static hostname (if it is set). If static or pretty hostname is not set appropriate properties are empty strings not NULLs. This behaviour is recomended by hostnamed.
324 lines
7.2 KiB
C
324 lines
7.2 KiB
C
/*
|
|
*
|
|
* 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 <errno.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <gdbus/gdbus.h>
|
|
|
|
#include "dbus-common.h"
|
|
#include "plugin.h"
|
|
#include "adapter.h"
|
|
#include "log.h"
|
|
|
|
/* http://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm */
|
|
|
|
#define MAJOR_CLASS_MISCELLANEOUS 0x00
|
|
#define MAJOR_CLASS_COMPUTER 0x01
|
|
|
|
#define MINOR_CLASS_UNCATEGORIZED 0x00
|
|
#define MINOR_CLASS_DESKTOP 0x01
|
|
#define MINOR_CLASS_SERVER 0x02
|
|
#define MINOR_CLASS_LAPTOP 0x03
|
|
#define MINOR_CLASS_HANDHELD 0x04
|
|
#define MINOR_CLASS_PALM_SIZED 0x05
|
|
#define MINOR_CLASS_WEARABLE 0x06
|
|
#define MINOR_CLASS_TABLET 0x07
|
|
|
|
static uint8_t major_class = MAJOR_CLASS_MISCELLANEOUS;
|
|
static uint8_t minor_class = MINOR_CLASS_UNCATEGORIZED;
|
|
|
|
static char *pretty_hostname = NULL;
|
|
static char *static_hostname = NULL;
|
|
|
|
/*
|
|
* Fallback to static hostname only if empty pretty hostname was already
|
|
* received.
|
|
*/
|
|
static const char *get_hostname(void)
|
|
{
|
|
if (pretty_hostname) {
|
|
if (g_str_equal(pretty_hostname, "") == FALSE)
|
|
return pretty_hostname;
|
|
|
|
if (static_hostname &&
|
|
g_str_equal(static_hostname, "") == FALSE)
|
|
return static_hostname;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void update_name(struct btd_adapter *adapter, gpointer user_data)
|
|
{
|
|
const char *hostname = get_hostname();
|
|
|
|
if (hostname == NULL)
|
|
return;
|
|
|
|
if (btd_adapter_is_default(adapter)) {
|
|
DBG("name: %s", hostname);
|
|
|
|
adapter_set_name(adapter, hostname);
|
|
} else {
|
|
uint16_t index = btd_adapter_get_index(adapter);
|
|
char *str;
|
|
|
|
/* Avoid "some device #0" names, start at #1 */
|
|
str = g_strdup_printf("%s #%u", hostname, index + 1);
|
|
|
|
DBG("name: %s", str);
|
|
|
|
adapter_set_name(adapter, str);
|
|
|
|
g_free(str);
|
|
}
|
|
}
|
|
|
|
static void update_class(struct btd_adapter *adapter, gpointer user_data)
|
|
{
|
|
if (major_class == MAJOR_CLASS_MISCELLANEOUS)
|
|
return;
|
|
|
|
DBG("major: 0x%02x minor: 0x%02x", major_class, minor_class);
|
|
|
|
btd_adapter_set_class(adapter, major_class, minor_class);
|
|
}
|
|
|
|
static const struct {
|
|
const char *chassis;
|
|
uint8_t major_class;
|
|
uint8_t minor_class;
|
|
} chassis_table[] = {
|
|
{ "desktop", MAJOR_CLASS_COMPUTER, MINOR_CLASS_DESKTOP },
|
|
{ "server", MAJOR_CLASS_COMPUTER, MINOR_CLASS_SERVER },
|
|
{ "laptop", MAJOR_CLASS_COMPUTER, MINOR_CLASS_LAPTOP },
|
|
{ "handset", MAJOR_CLASS_COMPUTER, MINOR_CLASS_HANDHELD },
|
|
{ "tablet", MAJOR_CLASS_COMPUTER, MINOR_CLASS_TABLET },
|
|
{ }
|
|
};
|
|
|
|
static void property_changed(GDBusProxy *proxy, const char *name,
|
|
DBusMessageIter *iter, void *user_data)
|
|
{
|
|
if (g_str_equal(name, "PrettyHostname") == TRUE) {
|
|
if (iter == NULL) {
|
|
g_dbus_proxy_refresh_property(proxy, name);
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
|
|
const char *str;
|
|
|
|
dbus_message_iter_get_basic(iter, &str);
|
|
|
|
DBG("pretty hostname: %s", str);
|
|
|
|
g_free(pretty_hostname);
|
|
pretty_hostname = g_strdup(str);
|
|
|
|
adapter_foreach(update_name, NULL);
|
|
}
|
|
} else if (g_str_equal(name, "StaticHostname") == TRUE) {
|
|
if (iter == NULL) {
|
|
g_dbus_proxy_refresh_property(proxy, name);
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
|
|
const char *str;
|
|
|
|
dbus_message_iter_get_basic(iter, &str);
|
|
|
|
DBG("static hostname: %s", str);
|
|
|
|
g_free(static_hostname);
|
|
static_hostname = g_strdup(str);
|
|
|
|
adapter_foreach(update_name, NULL);
|
|
}
|
|
} else if (g_str_equal(name, "Chassis") == TRUE) {
|
|
if (iter == NULL) {
|
|
g_dbus_proxy_refresh_property(proxy, name);
|
|
return;
|
|
}
|
|
|
|
if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
|
|
const char *str;
|
|
int i;
|
|
|
|
dbus_message_iter_get_basic(iter, &str);
|
|
|
|
DBG("chassis: %s", str);
|
|
|
|
for (i = 0; chassis_table[i].chassis; i++) {
|
|
if (strcmp(chassis_table[i].chassis, str))
|
|
continue;
|
|
|
|
major_class = chassis_table[i].major_class;
|
|
minor_class = chassis_table[i].minor_class;
|
|
|
|
adapter_foreach(update_class, NULL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int hostname_probe(struct btd_adapter *adapter)
|
|
{
|
|
DBG("");
|
|
|
|
update_name(adapter, NULL);
|
|
update_class(adapter, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void hostname_remove(struct btd_adapter *adapter)
|
|
{
|
|
DBG("");
|
|
}
|
|
|
|
static struct btd_adapter_driver hostname_driver = {
|
|
.name = "hostname",
|
|
.probe = hostname_probe,
|
|
.remove = hostname_remove,
|
|
};
|
|
|
|
static void read_dmi_fallback(void)
|
|
{
|
|
char *contents;
|
|
int i, type;
|
|
const char *str;
|
|
|
|
if (g_file_get_contents("/sys/class/dmi/id/chassis_type",
|
|
&contents, NULL, NULL) == FALSE)
|
|
return;
|
|
|
|
type = atoi(contents);
|
|
if (type < 0 || type > 0x1D)
|
|
return;
|
|
|
|
g_free(contents);
|
|
|
|
/* from systemd hostname chassis list */
|
|
switch (type) {
|
|
case 0x3:
|
|
case 0x4:
|
|
case 0x6:
|
|
case 0x7:
|
|
str = "desktop";
|
|
break;
|
|
case 0x8:
|
|
case 0x9:
|
|
case 0xA:
|
|
case 0xE:
|
|
str = "laptop";
|
|
break;
|
|
case 0xB:
|
|
str = "handset";
|
|
break;
|
|
case 0x11:
|
|
case 0x1C:
|
|
str = "server";
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
DBG("chassis: %s", str);
|
|
|
|
for (i = 0; chassis_table[i].chassis; i++) {
|
|
if (!strcmp(chassis_table[i].chassis, str)) {
|
|
major_class = chassis_table[i].major_class;
|
|
minor_class = chassis_table[i].minor_class;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DBG("major: 0x%02x minor: 0x%02x", major_class, minor_class);
|
|
}
|
|
|
|
static GDBusClient *hostname_client = NULL;
|
|
static GDBusProxy *hostname_proxy = NULL;
|
|
|
|
static int hostname_init(void)
|
|
{
|
|
DBusConnection *conn = btd_get_dbus_connection();
|
|
int err;
|
|
|
|
read_dmi_fallback();
|
|
|
|
hostname_client = g_dbus_client_new(conn, "org.freedesktop.hostname1",
|
|
"/org/freedesktop/hostname1");
|
|
if (!hostname_client)
|
|
return -EIO;
|
|
|
|
hostname_proxy = g_dbus_proxy_new(hostname_client,
|
|
"/org/freedesktop/hostname1",
|
|
"org.freedesktop.hostname1");
|
|
if (!hostname_proxy) {
|
|
g_dbus_client_unref(hostname_client);
|
|
hostname_client = NULL;
|
|
return -EIO;
|
|
}
|
|
|
|
g_dbus_proxy_set_property_watch(hostname_proxy, property_changed, NULL);
|
|
|
|
err = btd_register_adapter_driver(&hostname_driver);
|
|
if (err < 0) {
|
|
g_dbus_proxy_unref(hostname_proxy);
|
|
hostname_proxy = NULL;
|
|
g_dbus_client_unref(hostname_client);
|
|
hostname_client = NULL;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static void hostname_exit(void)
|
|
{
|
|
btd_unregister_adapter_driver(&hostname_driver);
|
|
|
|
if (hostname_proxy) {
|
|
g_dbus_proxy_unref(hostname_proxy);
|
|
hostname_proxy = NULL;
|
|
}
|
|
|
|
if (hostname_client) {
|
|
g_dbus_client_unref(hostname_client);
|
|
hostname_client = NULL;
|
|
}
|
|
|
|
g_free(pretty_hostname);
|
|
g_free(static_hostname);
|
|
}
|
|
|
|
BLUETOOTH_PLUGIN_DEFINE(hostname, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
|
|
hostname_init, hostname_exit)
|