#include <stdlib.h>
#include <stdbool.h>
#include <sys/ioctl.h>
+#include <sys/file.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/uuid.h>
#define REMOVE_TEMP_TIMEOUT (3 * 60)
#define PENDING_FOUND_MAX 5
+#define SETTINGS_PATH STORAGEDIR "/%s/settings"
+
static GSList *adapter_drivers = NULL;
enum session_req_type {
return MODE_UNKNOWN;
}
+static void store_adapter_info(struct btd_adapter *adapter)
+{
+ GKeyFile *key_file;
+ char filename[PATH_MAX + 1];
+ char address[18];
+ char *str;
+ gsize length = 0;
+
+ key_file = g_key_file_new();
+
+ g_key_file_set_string(key_file, "General", "Name", adapter->name);
+
+ g_key_file_set_boolean(key_file, "General", "Powered",
+ adapter->mode > MODE_OFF);
+
+ g_key_file_set_boolean(key_file, "General", "Pairable",
+ adapter->pairable);
+
+ if (adapter->pairable_timeout != main_opts.pairto)
+ g_key_file_set_integer(key_file, "General", "PairableTimeout",
+ adapter->pairable_timeout);
+
+ g_key_file_set_boolean(key_file, "General", "Discoverable",
+ adapter->discoverable);
+
+ if (adapter->discov_timeout != main_opts.discovto)
+ g_key_file_set_integer(key_file, "General",
+ "DiscoverableTimeout",
+ adapter->discov_timeout);
+
+ ba2str(&adapter->bdaddr, address);
+ snprintf(filename, PATH_MAX, SETTINGS_PATH, address);
+ filename[PATH_MAX] = '\0';
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ str = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(filename, str, length, NULL);
+ g_free(str);
+
+ g_key_file_free(key_file);
+}
+
static struct session_req *session_ref(struct session_req *req)
{
req->refcount++;
static int set_mode(struct btd_adapter *adapter, uint8_t new_mode)
{
int err;
- const char *modestr;
if (adapter->pending_mode != NULL)
return -EALREADY;
return err;
done:
- modestr = mode2str(new_mode);
- write_device_mode(&adapter->bdaddr, modestr);
+ store_adapter_info(adapter);
- DBG("%s", modestr);
+ DBG("%s", mode2str(new_mode));
return 0;
}
{
adapter->pairable = pairable;
- write_device_pairable(&adapter->bdaddr, pairable);
+ store_adapter_info(adapter);
g_dbus_emit_property_changed(btd_get_dbus_connection(), adapter->path,
ADAPTER_INTERFACE, "Pairable");
adapter->discov_timeout = timeout;
- write_discoverable_timeout(&adapter->bdaddr, timeout);
+ store_adapter_info(adapter);
g_dbus_emit_property_changed(conn, adapter->path, ADAPTER_INTERFACE,
"DiscoverableTimeout");
adapter->pairable_timeout = timeout;
- write_pairable_timeout(&adapter->bdaddr, timeout);
+ store_adapter_info(adapter);
g_dbus_emit_property_changed(conn, adapter->path, ADAPTER_INTERFACE,
"PairableTimeout");
adapter->name = g_strdup(maxname);
}
- write_local_name(&adapter->bdaddr, maxname);
+ store_adapter_info(adapter);
return 0;
}
{
DBusConnection *conn = btd_get_dbus_connection();
struct session_req *pending;
- const char *modestr;
int err;
- modestr = mode2str(adapter->mode);
- write_device_mode(&adapter->bdaddr, modestr);
+ store_adapter_info(adapter);
- DBG("%s", modestr);
+ DBG("%s", mode2str(adapter->mode));
if (adapter->mode == MODE_OFF) {
g_slist_free_full(adapter->mode_sessions, session_free);
g_free(path);
}
-static void load_config(struct btd_adapter *adapter)
+static void convert_config(struct btd_adapter *adapter, const char *filename,
+ GKeyFile *key_file)
{
- char name[MAX_NAME_LENGTH + 1];
char address[18];
- char mode[14];
+ char str[MAX_NAME_LENGTH + 1];
+ char config_path[PATH_MAX + 1];
+ char *converted;
+ gboolean flag;
int timeout;
+ uint8_t mode;
+ char *data;
+ gsize length = 0;
ba2str(&adapter->bdaddr, address);
+ snprintf(config_path, PATH_MAX, STORAGEDIR "/%s/config", address);
+ config_path[PATH_MAX] = '\0';
+
+ converted = textfile_get(config_path, "converted");
+ if (converted) {
+ if (strcmp(converted, "yes") == 0) {
+ DBG("Legacy config file already converted");
+ return;
+ }
+
+ g_free(converted);
+ }
+
+ if (read_local_name(&adapter->bdaddr, str) == 0)
+ g_key_file_set_string(key_file, "General", "Name", str);
+
+ if (read_device_pairable(&adapter->bdaddr, &flag) == 0)
+ g_key_file_set_boolean(key_file, "General", "Pairable", flag);
+
+ if (read_pairable_timeout(address, &timeout) == 0)
+ g_key_file_set_integer(key_file, "General",
+ "PairableTimeout", timeout);
+
+ if (read_discoverable_timeout(address, &timeout) == 0)
+ g_key_file_set_integer(key_file, "General",
+ "DiscoverableTimeout", timeout);
+
+ if (read_device_mode(address, str, sizeof(str)) == 0) {
+ mode = get_mode(str);
+ g_key_file_set_boolean(key_file, "General", "Powered",
+ mode > MODE_OFF);
+ }
+
+ if (read_on_mode(address, str, sizeof(str)) == 0) {
+ mode = get_mode(str);
+ g_key_file_set_boolean(key_file, "General", "Discoverable",
+ mode == MODE_DISCOVERABLE);
+ }
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+ g_file_set_contents(filename, data, length, NULL);
+ g_free(data);
+
+ textfile_put(config_path, "converted", "yes");
+}
+
+static void load_config(struct btd_adapter *adapter)
+{
+ GKeyFile *key_file;
+ char filename[PATH_MAX + 1];
+ char address[18];
+ gboolean powered;
+ GError *gerr = NULL;
+
+ ba2str(&adapter->bdaddr, address);
+
+ key_file = g_key_file_new();
+
+ snprintf(filename, PATH_MAX, SETTINGS_PATH, address);
+ filename[PATH_MAX] = '\0';
+
+ if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
+ convert_config(adapter, filename, key_file);
/* Get name */
- if (read_local_name(&adapter->bdaddr, name) < 0)
- adapter->name = NULL;
- else
- adapter->name = g_strdup(name);
+ adapter->name = g_key_file_get_string(key_file, "General",
+ "Name", NULL);
/* Set class */
adapter->dev_class = main_opts.class;
/* Get pairable mode */
- if (read_device_pairable(&adapter->bdaddr, &adapter->pairable) < 0)
+ adapter->pairable = g_key_file_get_boolean(key_file, "General",
+ "Pairable", &gerr);
+ if (gerr) {
adapter->pairable = TRUE;
+ g_error_free(gerr);
+ gerr = NULL;
+ }
/* Get pairable timeout */
- if (read_pairable_timeout(address, &timeout) < 0)
+ adapter->pairable_timeout = g_key_file_get_integer(key_file, "General",
+ "PairableTimeout", &gerr);
+ if (gerr) {
adapter->pairable_timeout = main_opts.pairto;
- else
- adapter->pairable_timeout = timeout;
+ g_error_free(gerr);
+ gerr = NULL;
+ }
+
+ /* Get discoverable mode */
+ adapter->discoverable = g_key_file_get_boolean(key_file, "General",
+ "Discoverable", &gerr);
+ if (gerr) {
+ adapter->discoverable = (main_opts.mode == MODE_DISCOVERABLE);
+ g_error_free(gerr);
+ gerr = NULL;
+ }
/* Get discoverable timeout */
- if (read_discoverable_timeout(address, &timeout) < 0)
+ adapter->discov_timeout = g_key_file_get_integer(key_file, "General",
+ "DiscoverableTimeout", &gerr);
+ if (gerr) {
adapter->discov_timeout = main_opts.discovto;
- else
- adapter->discov_timeout = timeout;
+ g_error_free(gerr);
+ gerr = NULL;
+ }
- /* Get mode */
- if (main_opts.remember_powered == FALSE)
- adapter->mode = main_opts.mode;
- else if (read_device_mode(address, mode, sizeof(mode)) == 0)
- adapter->mode = get_mode(mode);
- else
+ /* Get powered mode */
+ powered = g_key_file_get_boolean(key_file, "General", "Powered",
+ &gerr);
+ if (gerr) {
adapter->mode = main_opts.mode;
-
- /* Get on mode */
- if (read_on_mode(address, mode, sizeof(mode)) == 0)
- adapter->discoverable = (strcasecmp("discoverable", mode) == 0);
- else
- adapter->discoverable = (adapter->mode == MODE_DISCOVERABLE);
+ g_error_free(gerr);
+ gerr = NULL;
+ } else if (powered) {
+ adapter->mode = adapter->discoverable ? MODE_DISCOVERABLE :
+ MODE_CONNECTABLE;
+ } else
+ adapter->mode = MODE_OFF;
mgmt_set_connectable(adapter->dev_id, TRUE);
mgmt_set_discoverable(adapter->dev_id, adapter->discoverable,