summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hcid/dbus-adapter.c2
-rw-r--r--hcid/dbus.c4
-rw-r--r--hcid/dbus.h15
-rw-r--r--hcid/hcid.h23
-rw-r--r--hcid/kword.c1
-rw-r--r--hcid/main.c59
-rw-r--r--hcid/parser.y7
-rw-r--r--hcid/storage.c64
8 files changed, 157 insertions, 18 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c
index ee09ab8f..7c3bcfe9 100644
--- a/hcid/dbus-adapter.c
+++ b/hcid/dbus-adapter.c
@@ -395,6 +395,8 @@ static DBusHandlerResult handle_dev_set_discoverable_to_req(DBusConnection *conn
dbus_data->discoverable_timeout = timeout;
+ write_discoverable_timeout(dbus_data->address, timeout);
+
return send_reply_and_unref(conn, reply);
}
diff --git a/hcid/dbus.c b/hcid/dbus.c
index cd864215..3f99c272 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -339,7 +339,7 @@ static gboolean register_dbus_path(const char *path, uint16_t path_id, uint16_t
data->path_id = path_id;
data->dev_id = dev_id;
data->mode = SCAN_DISABLED;
- data->discoverable_timeout = DFT_DISCOVERABLE_TIMEOUT;
+ data->discoverable_timeout = get_discoverable_timeout(dev_id);
if (fallback) {
if (!dbus_connection_register_fallback(connection, path, pvtable, data)) {
@@ -1695,6 +1695,8 @@ void hcid_dbus_setscan_enable_complete(bdaddr_t *local)
goto failed;
}
+ write_device_mode(local, scan_mode);
+
message = dbus_message_new_signal(path, ADAPTER_INTERFACE,
"ModeChanged");
if (message == NULL) {
diff --git a/hcid/dbus.h b/hcid/dbus.h
index 7a347648..da6eeba7 100644
--- a/hcid/dbus.h
+++ b/hcid/dbus.h
@@ -201,20 +201,5 @@ int disc_device_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name
int disc_device_req_name(struct hci_dbus_data *dbus_data);
int discoverable_timeout_handler(void *data);
-/*
- * Scanning modes, used by DEV_SET_MODE
- * off: remote devices are not allowed to find or connect to this device
- * connectable: remote devices are allowed to connect, but they are not
- * allowed to find it.
- * discoverable: remote devices are allowed to connect and find this device
- * unknown: reserved to not allowed/future modes
- */
-#define MODE_OFF "off"
-#define MODE_CONNECTABLE "connectable"
-#define MODE_DISCOVERABLE "discoverable"
-#define MODE_UNKNOWN "unknown"
-
-#define DFT_DISCOVERABLE_TIMEOUT 180*1000 /* 3 seconds */
-#define DISCOVERABLE_TIMEOUT_OFF 0
#endif /* __H_BLUEZ_DBUS_H__ */
diff --git a/hcid/hcid.h b/hcid/hcid.h
index 066f9358..d10bdc0d 100644
--- a/hcid/hcid.h
+++ b/hcid/hcid.h
@@ -34,12 +34,28 @@
#define HCID_CONFIG_FILE CONFIGDIR "/hcid.conf"
+#define HCID_DEFAULT_DISCOVERABLE_TIMEOUT (180*1000) /* 3 minutes */
+
+/*
+ * Scanning modes, used by DEV_SET_MODE
+ * off: remote devices are not allowed to find or connect to this device
+ * connectable: remote devices are allowed to connect, but they are not
+ * allowed to find it.
+ * discoverable: remote devices are allowed to connect and find this device
+ * unknown: reserved to not allowed/future modes
+ */
+#define MODE_OFF "off"
+#define MODE_CONNECTABLE "connectable"
+#define MODE_DISCOVERABLE "discoverable"
+#define MODE_UNKNOWN "unknown"
+
enum {
HCID_SET_NAME,
HCID_SET_CLASS,
HCID_SET_VOICE,
HCID_SET_INQMODE,
HCID_SET_PAGETO,
+ HCID_SET_DISCOVTO,
HCID_SET_PTYPE,
HCID_SET_LM,
HCID_SET_LP,
@@ -58,6 +74,7 @@ struct device_opts {
uint16_t scan;
uint16_t auth;
uint16_t encrypt;
+ int discovto;
};
extern struct device_opts default_device;
@@ -116,6 +133,8 @@ int read_config(char *file);
struct device_opts *alloc_device_opts(char *ref);
+int get_discoverable_timeout(int dev_id);
+
void init_security_data(void);
void start_security_manager(int hdev);
void stop_security_manager(int hdev);
@@ -174,6 +193,10 @@ int set_device_alias(uint16_t dev_id, const bdaddr_t *bdaddr, const char *alias)
int get_encryption_key_size(uint16_t dev_id, const bdaddr_t *baddr);
+int write_discoverable_timeout(const char *address, int timeout);
+int read_discoverable_timeout(const char *address, int *timeout);
+int write_device_mode(bdaddr_t *bdaddr, const char *mode);
+int read_device_mode(bdaddr_t *bdaddr, char *mode, int length);
int write_local_name(bdaddr_t *bdaddr, char *name);
int read_local_name(bdaddr_t *bdaddr, char *name);
int write_local_class(bdaddr_t *bdaddr, uint8_t *class);
diff --git a/hcid/kword.c b/hcid/kword.c
index 32fd5571..62a946fe 100644
--- a/hcid/kword.c
+++ b/hcid/kword.c
@@ -58,6 +58,7 @@ struct kword cfg_keyword[] = {
{ "voice", K_VOICE },
{ "inqmode", K_INQMODE },
{ "pageto", K_PAGETO },
+ { "discovto", K_DISCOVTO },
{ "auth", K_AUTH },
{ "encrypt", K_ENCRYPT },
{ "passkey", K_PASSKEY },
diff --git a/hcid/main.c b/hcid/main.c
index 6a6b382c..4a3f0bc8 100644
--- a/hcid/main.c
+++ b/hcid/main.c
@@ -67,6 +67,7 @@ static inline void init_device_defaults(struct device_opts *device_opts)
memset(device_opts, 0, sizeof(*device_opts));
device_opts->scan = SCAN_PAGE;
device_opts->name = strdup("BlueZ");
+ device_opts->discovto = HCID_DEFAULT_DISCOVERABLE_TIMEOUT;
}
struct device_opts *alloc_device_opts(char *ref)
@@ -148,11 +149,54 @@ static struct device_opts *get_device_opts(int sock, int hdev)
return device_opts;
}
+int get_discoverable_timeout(int hdev)
+{
+ int sock, timeout;
+ char address[18];
+ struct device_opts *device_opts = NULL;
+ struct hci_dev_info di;
+
+ if (hdev < 0)
+ return HCID_DEFAULT_DISCOVERABLE_TIMEOUT;
+
+ sock = hci_open_dev(hdev);
+ if (sock < 0)
+ goto no_address;
+
+ di.dev_id = hdev;
+ if (!ioctl(sock, HCIGETDEVINFO, (void *) &di))
+ ba2str(&di.bdaddr, address);
+ else {
+ close(sock);
+ goto no_address;
+ }
+
+ close(sock);
+
+ if (!read_discoverable_timeout(address, &timeout))
+ return timeout;
+
+ device_opts = find_device_opts(address);
+
+no_address:
+ if (!device_opts) {
+ char ref[8];
+ snprintf(ref, sizeof(ref) - 1, "hci%d", hdev);
+ device_opts = find_device_opts(ref);
+ }
+
+ if (!device_opts)
+ device_opts = &default_device;
+
+ return device_opts->discovto;
+}
+
static void configure_device(int hdev)
{
struct device_opts *device_opts;
struct hci_dev_req dr;
struct hci_dev_info di;
+ char mode[14];
int s;
/* Do configuration in the separate process */
@@ -185,10 +229,19 @@ static void configure_device(int hdev)
device_opts = get_device_opts(s, hdev);
/* Set scan mode */
+ if (!read_device_mode(&di.bdaddr, mode, sizeof(mode))) {
+ if (!strcmp(mode, MODE_OFF))
+ device_opts->scan = SCAN_DISABLED;
+ else if (!strcmp(mode, MODE_CONNECTABLE))
+ device_opts->scan = SCAN_PAGE;
+ else if (!strcmp(mode, MODE_DISCOVERABLE))
+ device_opts->scan = SCAN_PAGE | SCAN_INQUIRY;
+ }
+
dr.dev_opt = device_opts->scan;
if (ioctl(s, HCISETSCAN, (unsigned long) &dr) < 0) {
error("Can't set scan mode on hci%d: %s (%d)",
- hdev, strerror(errno), errno);
+ hdev, strerror(errno), errno);
}
/* Set authentication */
@@ -305,6 +358,10 @@ static void configure_device(int hdev)
WRITE_PAGE_TIMEOUT_CP_SIZE, &cp);
}
+ /* Set default discoverable timeout if not set */
+ if (!(device_opts->flags & (1 << HCID_SET_DISCOVTO)))
+ device_opts->discovto = HCID_DEFAULT_DISCOVERABLE_TIMEOUT;
+
exit(0);
}
diff --git a/hcid/parser.y b/hcid/parser.y
index 60bbe224..9d33e448 100644
--- a/hcid/parser.y
+++ b/hcid/parser.y
@@ -59,7 +59,7 @@ int yyerror(char *s);
%token K_OPTIONS K_DEVICE
%token K_AUTOINIT K_SECURITY K_PAIRING
-%token K_PTYPE K_NAME K_CLASS K_VOICE K_INQMODE K_PAGETO K_LM K_LP K_AUTH K_ENCRYPT K_ISCAN K_PSCAN
+%token K_PTYPE K_NAME K_CLASS K_VOICE K_INQMODE K_PAGETO K_LM K_LP K_AUTH K_ENCRYPT K_ISCAN K_PSCAN K_DISCOVTO
%token K_PASSKEY
%token K_YES K_NO
@@ -199,6 +199,11 @@ device_opt:
parser_device->pageto = $2;
}
+ | K_DISCOVTO NUM {
+ parser_device->flags |= (1 << HCID_SET_DISCOVTO);
+ parser_device->discovto = $2;
+ }
+
| K_AUTH bool {
parser_device->auth = $2;
}
diff --git a/hcid/storage.c b/hcid/storage.c
index e3781278..f6475134 100644
--- a/hcid/storage.c
+++ b/hcid/storage.c
@@ -43,6 +43,70 @@
#include "textfile.h"
#include "hcid.h"
+int write_discoverable_timeout(const char *address, int timeout)
+{
+ char filename[PATH_MAX + 1], str[32];
+
+ snprintf(str, sizeof(str), "%d", timeout);
+
+ snprintf(filename, PATH_MAX, "%s/%s/config", STORAGEDIR, address);
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ return textfile_put(filename, "discovto", str);
+}
+
+int read_discoverable_timeout(const char *address, int *timeout)
+{
+ char filename[PATH_MAX + 1], *str;
+
+ snprintf(filename, PATH_MAX, "%s/%s/config", STORAGEDIR, address);
+
+ str = textfile_get(filename, "discovto");
+ if (!str)
+ return -ENOENT;
+
+ if (sscanf(str, "%d", timeout) != 1) {
+ free(str);
+ return -ENOENT;
+ }
+
+ free(str);
+
+ return 0;
+}
+
+int write_device_mode(bdaddr_t *bdaddr, const char *mode)
+{
+ char filename[PATH_MAX + 1], addr[18];
+
+ ba2str(bdaddr, addr);
+ snprintf(filename, PATH_MAX, "%s/%s/config", STORAGEDIR, addr);
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ return textfile_put(filename, "mode", mode);
+}
+
+int read_device_mode(bdaddr_t *bdaddr, char *mode, int length)
+{
+ char filename[PATH_MAX + 1], addr[18], *str;
+
+ ba2str(bdaddr, addr);
+ snprintf(filename, PATH_MAX, "%s/%s/config", STORAGEDIR, addr);
+
+ str = textfile_get(filename, "mode");
+ if (!str)
+ return -ENOENT;
+
+ strncpy(mode, str, length);
+ mode[length-1] = '\0';
+
+ free(str);
+
+ return 0;
+}
+
int write_local_name(bdaddr_t *bdaddr, char *name)
{
char filename[PATH_MAX + 1], addr[18], str[249];