diff options
| -rw-r--r-- | doc/adapter-api.txt | 9 | ||||
| -rw-r--r-- | src/adapter.c | 68 | ||||
| -rw-r--r-- | src/adapter.h | 2 | ||||
| -rw-r--r-- | src/dbus-hci.c | 8 | ||||
| -rw-r--r-- | src/storage.c | 30 | ||||
| -rw-r--r-- | src/storage.h | 2 | 
6 files changed, 117 insertions, 2 deletions
| diff --git a/doc/adapter-api.txt b/doc/adapter-api.txt index a13273f8..d0adf189 100644 --- a/doc/adapter-api.txt +++ b/doc/adapter-api.txt @@ -266,6 +266,15 @@ Properties	string Address [readonly]  			this property will be updated via a PropertyChanged  			signal. +		boolean Pairable [readwrite] + +			Switch an adapter to pairable or non-pairable. This is +			a global setting and should only be used by the +			settings application. + +			Note that this property only affects incoming pairing +			requests. +  		uint32 DiscoverableTimeout [readwrite]  			The discoverable timeout in seconds. A value of zero diff --git a/src/adapter.c b/src/adapter.c index 1f20cb40..8d76d4b2 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -114,6 +114,7 @@ struct btd_adapter {  	guint scheduler_id;		/* Scheduler handle */  	struct hci_dev dev;		/* hci info */ +	gboolean pairable;		/* pairable state */  };  static inline DBusMessage *invalid_args(DBusMessage *msg) @@ -627,7 +628,7 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg,  				adapter->discov_timeout_id = 0;  			} -			if (!adapter->mode_sessions && !adapter->discov_timeout) +			if (!adapter->mode_sessions && adapter->discov_timeout)  				adapter_set_discov_timeout(adapter,  						adapter->discov_timeout * 1000);  		} @@ -666,12 +667,40 @@ static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg,  	strmode = discoverable ? "discoverable" : "connectable";  	mode = get_mode(&adapter->bdaddr, strmode); +	if (mode == MODE_DISCOVERABLE && adapter->pairable) +		mode = MODE_LIMITED; +  	if (mode == adapter->mode)  		return dbus_message_new_method_return(msg);  	return set_mode(conn, msg, mode, data);  } +static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg, +				gboolean pairable, void *data) +{ +	struct btd_adapter *adapter = data; + +	if (pairable == adapter->pairable) +		goto done; + +	adapter->pairable = pairable; + +	write_device_pairable(&adapter->bdaddr, pairable); + +	emit_property_changed(connection, adapter->path, +				ADAPTER_INTERFACE, "Pairable", +				DBUS_TYPE_BOOLEAN, &pairable); + +	if (adapter->scan_mode & SCAN_INQUIRY) { +		uint8_t mode = pairable ? MODE_LIMITED : MODE_DISCOVERABLE; +		return set_mode(conn, msg, mode, data); +	} + +done: +	return dbus_message_new_method_return(msg); +} +  static struct session_req *find_session(GSList *list, DBusMessage *msg)  {  	GSList *l; @@ -1657,6 +1686,10 @@ static DBusMessage *get_properties(DBusConnection *conn,  	value = adapter->scan_mode & SCAN_INQUIRY ? TRUE : FALSE;  	dict_append_entry(&dict, "Discoverable", DBUS_TYPE_BOOLEAN, &value); +	/* Pairable */ +	dict_append_entry(&dict, "Pairable", DBUS_TYPE_BOOLEAN, +				&adapter->pairable); +  	/* DiscoverableTimeout */  	dict_append_entry(&dict, "DiscoverableTimeout",  				DBUS_TYPE_UINT32, &adapter->discov_timeout); @@ -1760,6 +1793,15 @@ static DBusMessage *set_property(DBusConnection *conn,  		dbus_message_iter_get_basic(&sub, &timeout);  		return set_discoverable_timeout(conn, msg, timeout, data); +	} else if (g_str_equal("Pairable", property)) { +		gboolean pairable; + +		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN) +			return invalid_args(msg); + +		dbus_message_iter_get_basic(&sub, &pairable); + +		return set_pairable(conn, msg, pairable, data);  	}  	return invalid_args(msg); @@ -2409,6 +2451,10 @@ static void adapter_up(struct btd_adapter *adapter, int dd)  	adapter->discov_timeout = get_discoverable_timeout(srcaddr);  	adapter->state = DISCOVER_TYPE_NONE; +	/* Set pairable mode */ +	if (read_device_pairable(&adapter->bdaddr, &adapter->pairable) < 0) +		adapter->pairable = TRUE; +  	/* Set scan mode */  	if (read_device_mode(srcaddr, mode, sizeof(mode)) == 0) {  		if (!strcmp(mode, "off")) { @@ -2437,7 +2483,8 @@ static void adapter_up(struct btd_adapter *adapter, int dd)  		} else if (!strcmp(mode, "discoverable")) {  			/* Set discoverable only if timeout is 0 */  			if (adapter->discov_timeout == 0) { -				adapter->mode = MODE_DISCOVERABLE; +				adapter->mode = adapter->pairable ? +					MODE_LIMITED : MODE_DISCOVERABLE;  				adapter->scan_mode = SCAN_PAGE | SCAN_INQUIRY;  			} else {  				adapter->mode = MODE_CONNECTABLE; @@ -2497,6 +2544,10 @@ static void adapter_up(struct btd_adapter *adapter, int dd)  				ADAPTER_INTERFACE, "Discoverable",  				DBUS_TYPE_BOOLEAN, &discoverable); +	emit_property_changed(connection, adapter->path, +				ADAPTER_INTERFACE, "Pairable", +				DBUS_TYPE_BOOLEAN, &adapter->pairable); +  	load_drivers(adapter);  	load_devices(adapter);  } @@ -3496,3 +3547,16 @@ void btd_adapter_any_release_path(void)  	g_free(adapter_any_path);  	adapter_any_path = NULL;  } + +gboolean adapter_is_pairable(struct btd_adapter *adapter) +{ +	return adapter->pairable; +} + +gboolean adapter_pairing_initiator(struct btd_adapter *adapter, bdaddr_t *bda) +{ +	if (!adapter->bonding) +		return FALSE; + +	return (bacmp(&adapter->bonding->bdaddr, bda) == 0); +} diff --git a/src/adapter.h b/src/adapter.h index 7d666a5b..eb206ac6 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -184,3 +184,5 @@ const char *adapter_any_get_path(void);  const char *btd_adapter_any_request_path(void);  void btd_adapter_any_release_path(void); +gboolean adapter_is_pairable(struct btd_adapter *adapter); +gboolean adapter_pairing_initiator(struct btd_adapter *adapter, bdaddr_t *bda); diff --git a/src/dbus-hci.c b/src/dbus-hci.c index 5b0a1f96..6f9f1bc5 100644 --- a/src/dbus-hci.c +++ b/src/dbus-hci.c @@ -239,6 +239,10 @@ int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)  		return -1;  	} +	if (!adapter_pairing_initiator(adapter, sba) && +			!adapter_is_pairable(adapter)) +		return -EPERM; +  	ba2str(&ci->bdaddr, addr);  	device = adapter_find_device(adapter, addr); @@ -1466,6 +1470,10 @@ int hcid_dbus_get_io_cap(bdaddr_t *local, bdaddr_t *remote,  	if (get_auth_requirements(local, remote, auth) < 0)  		return -1; +	if (!adapter_pairing_initiator(adapter, remote) && +			!adapter_is_pairable(adapter)) +		return -EPERM; +  	ba2str(remote, addr);  	/* For CreatePairedDevice use dedicated bonding */ diff --git a/src/storage.c b/src/storage.c index ac1ec5bd..212f7ce2 100644 --- a/src/storage.c +++ b/src/storage.c @@ -1028,3 +1028,33 @@ int read_device_id(const gchar *srcaddr, const gchar *dstaddr,  	return 0;  } + +int write_device_pairable(bdaddr_t *bdaddr, gboolean mode) +{ +	char filename[PATH_MAX + 1]; + +	create_filename(filename, PATH_MAX, bdaddr, "config"); + +	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +	return textfile_put(filename, "pairable", mode ? "yes" : "no"); +} + +int read_device_pairable(bdaddr_t *bdaddr, gboolean *mode) +{ +	char filename[PATH_MAX + 1], *str; + +	create_filename(filename, PATH_MAX, bdaddr, "config"); + +	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +	str = textfile_get(filename, "pairable"); +	if (!str) +		return -ENOENT; + +	*mode = strcmp(str, "yes") == 0 ? TRUE : FALSE; + +	free(str); + +	return 0; +} diff --git a/src/storage.h b/src/storage.h index 29f08d80..b6bedbed 100644 --- a/src/storage.h +++ b/src/storage.h @@ -68,6 +68,8 @@ int store_device_id(const gchar *src, const gchar *dst,  int read_device_id(const gchar *src, const gchar *dst,  					uint16_t *source, uint16_t *vendor,  					uint16_t *product, uint16_t *version); +int write_device_pairable(bdaddr_t *local, gboolean mode); +int read_device_pairable(bdaddr_t *local, gboolean *mode);  #define PNP_UUID		"00001200-0000-1000-8000-00805f9b34fb" | 
