diff options
-rw-r--r-- | hcid/dbus-adapter.c | 2 | ||||
-rw-r--r-- | hcid/dbus.c | 4 | ||||
-rw-r--r-- | hcid/dbus.h | 15 | ||||
-rw-r--r-- | hcid/hcid.h | 23 | ||||
-rw-r--r-- | hcid/kword.c | 1 | ||||
-rw-r--r-- | hcid/main.c | 59 | ||||
-rw-r--r-- | hcid/parser.y | 7 | ||||
-rw-r--r-- | hcid/storage.c | 64 |
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]; |