diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-11-27 16:46:45 -0300 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-11-27 16:46:45 -0300 | 
| commit | 3ee81cab2ed66b7f3d4fbd6ba6676d5d9448d6dc (patch) | |
| tree | 459dc5218f3b944a638a16361a422e5ba3d7857d | |
| parent | 395c910980394868a3c2d14e90e4f55988c7663d (diff) | |
Introduce PairableTimeout Property and fix use of g_timeout_add.
PairableTimeout work similarly to DiscoverableTimeout where the user
application can set the amount of time to stay in Pairable. It also
fixes the use of g_timeout_add to g_timeout_add_seconds for both
PairableTimeout and DiscoverableTimeout.
| -rw-r--r-- | src/adapter.c | 229 | ||||
| -rw-r--r-- | src/adapter.h | 1 | ||||
| -rw-r--r-- | src/hcid.h | 1 | ||||
| -rw-r--r-- | src/main.c | 11 | ||||
| -rw-r--r-- | src/main.conf | 5 | ||||
| -rw-r--r-- | src/storage.c | 33 | ||||
| -rw-r--r-- | src/storage.h | 2 | 
7 files changed, 208 insertions, 74 deletions
diff --git a/src/adapter.c b/src/adapter.c index 8d76d4b2..002aa376 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -94,7 +94,9 @@ struct btd_adapter {  	char *path;			/* adapter object path */  	bdaddr_t bdaddr;		/* adapter Bluetooth Address */  	guint discov_timeout_id;	/* discoverable timeout id */ -	uint32_t discov_timeout;	/* discoverable time(msec) */ +	uint32_t discov_timeout;	/* discoverable time(sec) */ +	guint pairable_timeout_id;	/* pairable timeout id */ +	uint32_t pairable_timeout;	/* pairable time(sec) */  	uint8_t scan_mode;		/* scan mode: SCAN_DISABLED, SCAN_PAGE, SCAN_INQUIRY */  	uint8_t mode;			/* off, connectable, discoverable, limited */  	uint8_t global_mode;		/* last valid global mode */ @@ -117,6 +119,9 @@ struct btd_adapter {  	gboolean pairable;		/* pairable state */  }; +static void adapter_set_pairable_timeout(struct btd_adapter *adapter, +					guint interval); +  static inline DBusMessage *invalid_args(DBusMessage *msg)  {  	return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments", @@ -526,6 +531,71 @@ static uint8_t get_mode(const bdaddr_t *bdaddr, const char *mode)  		return MODE_UNKNOWN;  } +static gboolean discov_timeout_handler(void *data) +{ +	struct btd_adapter *adapter = data; +	struct hci_request rq; +	int dd; +	uint8_t scan_enable = adapter->scan_mode; +	uint8_t status = 0; +	gboolean retval = TRUE; +	uint16_t dev_id = adapter->dev_id; + +	scan_enable &= ~SCAN_INQUIRY; + +	dd = hci_open_dev(dev_id); +	if (dd < 0) { +		error("HCI device open failed: hci%d", dev_id); +		return TRUE; +	} + +	memset(&rq, 0, sizeof(rq)); +	rq.ogf    = OGF_HOST_CTL; +	rq.ocf    = OCF_WRITE_SCAN_ENABLE; +	rq.cparam = &scan_enable; +	rq.clen   = sizeof(scan_enable); +	rq.rparam = &status; +	rq.rlen   = sizeof(status); +	rq.event  = EVT_CMD_COMPLETE; + +	if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) { +		error("Sending write scan enable command to hci%d failed: %s (%d)", +				dev_id, strerror(errno), errno); +		goto failed; +	} +	if (status) { +		error("Setting scan enable failed with status 0x%02x", status); +		goto failed; +	} + +	set_limited_discoverable(dd, adapter->dev.class, FALSE); + +	adapter_remove_discov_timeout(adapter); +	retval = FALSE; + +failed: +	if (dd >= 0) +		hci_close_dev(dd); + +	return retval; +} + +static void adapter_set_discov_timeout(struct btd_adapter *adapter, +					guint interval) +{ +	if (adapter->discov_timeout_id) { +		g_source_remove(adapter->discov_timeout_id); +		adapter->discov_timeout_id = 0; +	} + +	if (interval == 0) +		return; + +	adapter->discov_timeout_id = g_timeout_add_seconds(interval, +							discov_timeout_handler, +							adapter); +} +  static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg,  				uint8_t new_mode, void *data)  { @@ -630,7 +700,7 @@ static DBusMessage *set_mode(DBusConnection *conn, DBusMessage *msg,  			if (!adapter->mode_sessions && adapter->discov_timeout)  				adapter_set_discov_timeout(adapter, -						adapter->discov_timeout * 1000); +						adapter->discov_timeout);  		}  	}  done: @@ -692,13 +762,40 @@ static DBusMessage *set_pairable(DBusConnection *conn, DBusMessage *msg,  				ADAPTER_INTERFACE, "Pairable",  				DBUS_TYPE_BOOLEAN, &pairable); +	if (pairable && adapter->pairable_timeout) +		adapter_set_pairable_timeout(adapter, +						adapter->pairable_timeout); +  	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); +	return msg ? dbus_message_new_method_return(msg) : NULL; +} + +static gboolean pairable_timeout_handler(void *data) +{ +	set_pairable(NULL, NULL, FALSE, data); + +	return FALSE; +} + +static void adapter_set_pairable_timeout(struct btd_adapter *adapter, +					guint interval) +{ +	if (adapter->pairable_timeout_id) { +		g_source_remove(adapter->pairable_timeout_id); +		adapter->pairable_timeout_id = 0; +	} + +	if (interval == 0) +		return; + +	adapter->pairable_timeout_id = g_timeout_add_seconds(interval, +							pairable_timeout_handler, +							adapter);  }  static struct session_req *find_session(GSList *list, DBusMessage *msg) @@ -887,13 +984,8 @@ static DBusMessage *set_discoverable_timeout(DBusConnection *conn,  	if (adapter->discov_timeout == timeout && timeout == 0)  		return dbus_message_new_method_return(msg); -	if (adapter->discov_timeout_id) { -		g_source_remove(adapter->discov_timeout_id); -		adapter->discov_timeout_id = 0; -	} - -	if ((timeout != 0) && (adapter->scan_mode & SCAN_INQUIRY)) -		adapter_set_discov_timeout(adapter, timeout * 1000); +	if (adapter->scan_mode & SCAN_INQUIRY) +		adapter_set_discov_timeout(adapter, timeout);  	adapter->discov_timeout = timeout; @@ -908,6 +1000,33 @@ static DBusMessage *set_discoverable_timeout(DBusConnection *conn,  	return dbus_message_new_method_return(msg);  } +static DBusMessage *set_pairable_timeout(DBusConnection *conn, +						DBusMessage *msg, +						uint32_t timeout, +						void *data) +{ +	struct btd_adapter *adapter = data; +	const char *path; + +	if (adapter->pairable_timeout == timeout && timeout == 0) +		return dbus_message_new_method_return(msg); + +	if (adapter->pairable) +		adapter_set_pairable_timeout(adapter, timeout); + +	adapter->pairable_timeout = timeout; + +	write_pairable_timeout(&adapter->bdaddr, timeout); + +	path = dbus_message_get_path(msg); + +	emit_property_changed(conn, path, +				ADAPTER_INTERFACE, "PairableTimeout", +				DBUS_TYPE_UINT32, &timeout); + +	return dbus_message_new_method_return(msg); +} +  static void update_ext_inquiry_response(int dd, struct hci_dev *dev)  {  	uint8_t fec = 0, data[240]; @@ -1694,6 +1813,11 @@ static DBusMessage *get_properties(DBusConnection *conn,  	dict_append_entry(&dict, "DiscoverableTimeout",  				DBUS_TYPE_UINT32, &adapter->discov_timeout); +	/* PairableTimeout */ +	dict_append_entry(&dict, "PairableTimeout", +				DBUS_TYPE_UINT32, &adapter->pairable_timeout); + +  	if (adapter->state & PERIODIC_INQUIRY || adapter->state & STD_INQUIRY)  		value = TRUE;  	else @@ -1802,6 +1926,15 @@ static DBusMessage *set_property(DBusConnection *conn,  		dbus_message_iter_get_basic(&sub, &pairable);  		return set_pairable(conn, msg, pairable, data); +	} else if (g_str_equal("PairableTimeout", property)) { +		uint32_t timeout; + +		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT32) +			return invalid_args(msg); + +		dbus_message_iter_get_basic(&sub, &timeout); + +		return set_pairable_timeout(conn, msg, timeout, data);  	}  	return invalid_args(msg); @@ -2435,6 +2568,16 @@ static int get_discoverable_timeout(const char *src)  	return main_opts.discovto;  } +static int get_pairable_timeout(const char *src) +{ +	int timeout; + +	if (read_pairable_timeout(src, &timeout) == 0) +		return timeout; + +	return main_opts.pairto; +} +  static void adapter_up(struct btd_adapter *adapter, int dd)  {  	struct hci_conn_list_req *cl = NULL; @@ -2449,6 +2592,7 @@ static void adapter_up(struct btd_adapter *adapter, int dd)  	adapter->up = 1;  	adapter->discov_timeout = get_discoverable_timeout(srcaddr); +	adapter->pairable_timeout = get_pairable_timeout(srcaddr);  	adapter->state = DISCOVER_TYPE_NONE;  	/* Set pairable mode */ @@ -2923,67 +3067,6 @@ void adapter_get_address(struct btd_adapter *adapter, bdaddr_t *bdaddr)  	bacpy(bdaddr, &adapter->bdaddr);  } -static gboolean discov_timeout_handler(void *data) -{ -	struct btd_adapter *adapter = data; -	struct hci_request rq; -	int dd; -	uint8_t scan_enable = adapter->scan_mode; -	uint8_t status = 0; -	gboolean retval = TRUE; -	uint16_t dev_id = adapter->dev_id; - -	scan_enable &= ~SCAN_INQUIRY; - -	dd = hci_open_dev(dev_id); -	if (dd < 0) { -		error("HCI device open failed: hci%d", dev_id); -		return TRUE; -	} - -	memset(&rq, 0, sizeof(rq)); -	rq.ogf    = OGF_HOST_CTL; -	rq.ocf    = OCF_WRITE_SCAN_ENABLE; -	rq.cparam = &scan_enable; -	rq.clen   = sizeof(scan_enable); -	rq.rparam = &status; -	rq.rlen   = sizeof(status); -	rq.event  = EVT_CMD_COMPLETE; - -	if (hci_send_req(dd, &rq, HCI_REQ_TIMEOUT) < 0) { -		error("Sending write scan enable command to hci%d failed: %s (%d)", -				dev_id, strerror(errno), errno); -		goto failed; -	} -	if (status) { -		error("Setting scan enable failed with status 0x%02x", status); -		goto failed; -	} - -	set_limited_discoverable(dd, adapter->dev.class, FALSE); - -	adapter_remove_discov_timeout(adapter); -	retval = FALSE; - -failed: -	if (dd >= 0) -		hci_close_dev(dd); - -	return retval; -} - -void adapter_set_discov_timeout(struct btd_adapter *adapter, guint interval) -{ -	if (!adapter) -		return; - -	if (adapter->discov_timeout_id) { -		error("Timeout already added for adapter %s", adapter->path); -		return; -	} - -	adapter->discov_timeout_id = g_timeout_add(interval, discov_timeout_handler, adapter); -}  void adapter_remove_discov_timeout(struct btd_adapter *adapter)  { @@ -3219,14 +3302,14 @@ void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode)  		}  		if (adapter->discov_timeout != 0)  			adapter_set_discov_timeout(adapter, -						adapter->discov_timeout * 1000); +						adapter->discov_timeout);  		break;  	case SCAN_INQUIRY:  		/* Address the scenario where a low-level application like  		 * hciconfig changed the scan mode */  		if (adapter->discov_timeout != 0)  			adapter_set_discov_timeout(adapter, -						adapter->discov_timeout * 1000); +						adapter->discov_timeout);  		/* ignore, this event should not be sent */  	default: diff --git a/src/adapter.h b/src/adapter.h index eb206ac6..b6a974f3 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -135,7 +135,6 @@ uint16_t adapter_get_dev_id(struct btd_adapter *adapter);  const gchar *adapter_get_path(struct btd_adapter *adapter);  void adapter_get_address(struct btd_adapter *adapter, bdaddr_t *bdaddr);  void adapter_remove(struct btd_adapter *adapter); -void adapter_set_discov_timeout(struct btd_adapter *adapter, guint interval);  void adapter_remove_discov_timeout(struct btd_adapter *adapter);  void adapter_set_scan_mode(struct btd_adapter *adapter, uint8_t scan_mode);  uint8_t adapter_get_scan_mode(struct btd_adapter *adapter); @@ -55,6 +55,7 @@ struct main_opts {  	uint32_t	class;  	uint16_t	pageto;  	uint32_t	discovto; +	uint32_t	pairto;  	uint16_t	link_mode;  	uint16_t	link_policy; @@ -127,6 +127,17 @@ static void parse_config(GKeyFile *config)  	}  	val = g_key_file_get_integer(config, "General", +					"PairableTimeout", +					&err); +	if (err) { +		debug("%s", err->message); +		g_clear_error(&err); +	} else { +		debug("pairto=%d", val); +		main_opts.pairto = val; +	} + +	val = g_key_file_get_integer(config, "General",  					"PageTimeout",  					&err);  	if (err) { diff --git a/src/main.conf b/src/main.conf index 16d04579..20bac707 100644 --- a/src/main.conf +++ b/src/main.conf @@ -17,6 +17,11 @@ Class = 0x000100  # 0 = disable timer, i.e. stay discoverable forever  DiscoverableTimeout = 0 +# How long to stay in pairable mode before going back to non-discoverable +# The value is in seconds. Default is 0. +# 0 = disable timer, i.e. stay pairable forever +PairableTimeout = 0 +  # Use some other page timeout than the controller default one  # (16384 = 10 seconds)  PageTimeout = 8192 diff --git a/src/storage.c b/src/storage.c index 212f7ce2..a97a9992 100644 --- a/src/storage.c +++ b/src/storage.c @@ -120,6 +120,39 @@ int read_discoverable_timeout(const char *src, int *timeout)  	return 0;  } +int write_pairable_timeout(bdaddr_t *bdaddr, int timeout) +{ +	char filename[PATH_MAX + 1], str[32]; + +	snprintf(str, sizeof(str), "%d", timeout); + +	create_filename(filename, PATH_MAX, bdaddr, "config"); + +	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + +	return textfile_put(filename, "pairto", str); +} + +int read_pairable_timeout(const char *src, int *timeout) +{ +	char filename[PATH_MAX + 1], *str; + +	create_name(filename, PATH_MAX, STORAGEDIR, src, "config"); + +	str = textfile_get(filename, "pairto"); +	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]; diff --git a/src/storage.h b/src/storage.h index b6bedbed..ce3a22e5 100644 --- a/src/storage.h +++ b/src/storage.h @@ -25,6 +25,8 @@ int read_device_alias(const char *src, const char *dst, char *alias, size_t size  int write_device_alias(const char *src, const char *dst, const char *alias);  int write_discoverable_timeout(bdaddr_t *bdaddr, int timeout);  int read_discoverable_timeout(const char *src, int *timeout); +int write_pairable_timeout(bdaddr_t *bdaddr, int timeout); +int read_pairable_timeout(const char *src, int *timeout);  int write_device_mode(bdaddr_t *bdaddr, const char *mode);  int read_device_mode(const char *src, char *mode, int length);  int read_on_mode(const char *src, char *mode, int length);  | 
