diff options
| author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-20 13:22:00 +0000 | 
|---|---|---|
| committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-20 13:22:00 +0000 | 
| commit | 76435ed8bf033567c510e7ba9a18e39c1729534a (patch) | |
| tree | e8273307cb57822c6db9ad51ddbf4aab4c916569 | |
| parent | 75ad3946b10a5eab94962870263618d86b74fc80 (diff) | |
added GetRemoteName: integrated with the discover procedure queue
| -rw-r--r-- | hcid/dbus-adapter.c | 55 | ||||
| -rw-r--r-- | hcid/dbus-error.c | 7 | ||||
| -rw-r--r-- | hcid/dbus.c | 202 | ||||
| -rw-r--r-- | hcid/dbus.h | 7 | 
4 files changed, 158 insertions, 113 deletions
| diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index ebc532dc..36c47e0b 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -105,7 +105,7 @@ static int bonding_requests_append(struct slist **list, bdaddr_t *bdaddr, DBusMe  		return -1;  	dev->bdaddr = malloc(sizeof(*dev->bdaddr)); -	memcpy(dev->bdaddr, bdaddr, sizeof(*dev->bdaddr)); +	bacpy(dev->bdaddr, bdaddr);  	dev->msg = msg;  	dev->bonding_state = bonding_state; @@ -811,13 +811,14 @@ static DBusHandlerResult handle_dev_get_remote_name_req(DBusConnection *conn, DB  	struct hci_dbus_data *dbus_data = data;  	DBusMessage *reply = NULL;  	DBusError err; -	const char *str_bdaddr; -	char *name; +	const char *peer_addr; +	bdaddr_t peer_bdaddr; +	char *str;  	int ecode;  	dbus_error_init(&err);  	dbus_message_get_args(msg, &err, -				DBUS_TYPE_STRING, &str_bdaddr, +				DBUS_TYPE_STRING, &peer_addr,  				DBUS_TYPE_INVALID);  	if (dbus_error_is_set(&err)) { @@ -827,28 +828,48 @@ static DBusHandlerResult handle_dev_get_remote_name_req(DBusConnection *conn, DB  	}  	ecode = get_device_address(dbus_data->dev_id, addr, sizeof(addr)); -	if (ecode< 0) +	if (ecode < 0)  		return error_failed(conn, msg, -ecode); +	/* check if it is a unknown address */ +	snprintf(filename, PATH_MAX, "%s/%s/lastseen", STORAGEDIR, addr); + +	str = textfile_get(filename, peer_addr); + +	if (!str) +		return error_unknown_address(conn, msg); + +	free(str); + +	/* check if it is in the cache */  	snprintf(filename, PATH_MAX, "%s/%s/names", STORAGEDIR, addr); -	name = textfile_get(filename, str_bdaddr); +	str = textfile_get(filename, peer_addr); -	if (!name) -		return error_record_does_not_exist(conn, msg); +	if (str) { +		reply = dbus_message_new_method_return(msg); +		if (!reply) { +			free(str); +			return error_out_of_memory(conn, msg); +		} -	reply = dbus_message_new_method_return(msg); -	if (!reply) { -		free(name); -		return error_out_of_memory(conn, msg); +		/* send the cached name */ +		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str, +						DBUS_TYPE_INVALID); + +		free(str); +		return send_reply_and_unref(conn, reply);  	} -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &name, -					DBUS_TYPE_INVALID); +	/* put the request name in the queue to resolve name */ +	str2ba(peer_addr, &peer_bdaddr); +	remote_name_append(&dbus_data->discovered_devices, &peer_bdaddr, NAME_PENDING); -	free(name); +	/* check if there is a discover process running */ +	if (dbus_data->discover_state == DISCOVER_OFF) +		remote_name_resolve(dbus_data); -	return send_reply_and_unref(conn, reply); +	return error_request_deferred(conn, msg);  }  static DBusHandlerResult handle_dev_get_remote_alias_req(DBusConnection *conn, DBusMessage *msg, void *data) @@ -1492,7 +1513,7 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D  		/* get the first element */  		addr = (bdaddr_t *) (dbus_data->discovered_devices)->data; -		memcpy(&cp.bdaddr, addr, sizeof(bdaddr_t)); +		bacpy(&cp.bdaddr, addr);  		rq.ocf = OCF_REMOTE_NAME_REQ_CANCEL;  		rq.cparam = &cp; diff --git a/hcid/dbus-error.c b/hcid/dbus-error.c index 100de9b0..375456bd 100644 --- a/hcid/dbus-error.c +++ b/hcid/dbus-error.c @@ -90,6 +90,13 @@ DBusHandlerResult error_not_available(DBusConnection *conn, DBusMessage *msg)  							"Not available"));  } +DBusHandlerResult error_request_deferred(DBusConnection *conn, DBusMessage *msg) +{ +	return send_reply_and_unref(conn, +		dbus_message_new_error(msg, ERROR_INTERFACE ".RequestDeferred", +							"Request Deferred")); +} +  DBusHandlerResult error_not_connected(DBusConnection *conn, DBusMessage *msg)  {  	return send_reply_and_unref(conn, diff --git a/hcid/dbus.c b/hcid/dbus.c index 919f7456..ac00e8d1 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -122,15 +122,15 @@ int bonding_requests_find(const void *data, const void *user_data)  int remote_name_find_by_bdaddr(const void *data, const void *user_data)  {  	const struct discovered_dev_info *dev = data; -	const bdaddr_t *baddr = user_data; +	const bdaddr_t *bdaddr = user_data; -	if (memcmp(dev->bdaddr, baddr, sizeof(*baddr)) == 0) +	if (memcmp(dev->bdaddr, bdaddr, sizeof(*bdaddr)) == 0)  		return 0;  	return -1;  } -int remote_name_find_by_name_status(const void *data, const void *user_data) +static int remote_name_find_by_name_status(const void *data, const void *user_data)  {  	const struct discovered_dev_info *dev = data;  	const name_status_t *name_status = user_data; @@ -141,7 +141,7 @@ int remote_name_find_by_name_status(const void *data, const void *user_data)  	return -1;  } -static int remote_name_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name_status) +int remote_name_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name_status)  {  	struct discovered_dev_info *dev = NULL;  	struct slist *l; @@ -161,11 +161,10 @@ static int remote_name_append(struct slist **list, bdaddr_t *bdaddr, name_status  		return -1;  	dev->bdaddr = malloc(sizeof(*dev->bdaddr)); -	memcpy(dev->bdaddr, bdaddr, sizeof(*dev->bdaddr)); +	bacpy(dev->bdaddr, bdaddr);  	dev->name_status = name_status;  	*list = slist_append(*list, dev); -  	return 0;  } @@ -246,7 +245,7 @@ int get_default_dev_id(void)  	return default_dev;  } -static int dev_append_signal_args(DBusMessage *signal, int first, va_list var_args) +static inline int dev_append_signal_args(DBusMessage *signal, int first, va_list var_args)  {  	void *value;  	DBusMessageIter iter; @@ -629,12 +628,17 @@ failed:  	bt_free(local_addr);  } -static inline int remote_name_resolve(struct hci_dbus_data *dbus_data) +int remote_name_resolve(struct hci_dbus_data *dbus_data)  { +	struct hci_request rq; +	evt_cmd_status rp; +	remote_name_req_cp cp; +	bdaddr_t tmp;  	struct discovered_dev_info *dev; +	DBusMessage *message = NULL;  	struct slist *l = NULL; -	remote_name_req_cp cp; -	int dd; +	char *peer_addr = NULL; +	int dd, req_sent, ret_val = 0;  	name_status_t name_status = NAME_PENDING;  	/*get the next remote address */ @@ -654,16 +658,70 @@ static inline int remote_name_resolve(struct hci_dbus_data *dbus_data)  	if (dd < 0)  		return -1; -	memset(&cp, 0, sizeof(cp)); -	bacpy(&cp.bdaddr, dev->bdaddr); -	cp.pscan_rep_mode = 0x02; +	memset(&rq, 0, sizeof(rq)); +	rq.ogf    = OGF_LINK_CTL; +	rq.ocf    = OCF_REMOTE_NAME_REQ; +	rq.cparam = &cp; +	rq.clen   = REMOTE_NAME_REQ_CP_SIZE; +	rq.rparam = &rp; +	rq.rlen   = EVT_CMD_STATUS_SIZE; +	rq.event  = EVT_CMD_STATUS; + +	/* send at least one request or return failed if the list is empty */ +	do { +		req_sent = 1; + +		memset(&cp, 0, sizeof(cp)); +		bacpy(&cp.bdaddr, dev->bdaddr); +		cp.pscan_rep_mode = 0x02; + +		baswap(&tmp, dev->bdaddr); peer_addr = batostr(&tmp); + +		if (hci_send_req(dd, &rq, 100) < 0) { +			error("Unable to send the HCI remote name request: %s (%d)", +				strerror(errno), errno); +			message = dev_signal_factory(dbus_data->dev_id, "RemoteNameFailed", +							DBUS_TYPE_STRING, &peer_addr, +							DBUS_TYPE_INVALID); +			req_sent = 0; +		} + +		if (rp.status) { +			error("Remote name request failed with status 0x%02x", rp.status); +			message = dev_signal_factory(dbus_data->dev_id, "RemoteNameFailed", +							DBUS_TYPE_STRING, &peer_addr, +							DBUS_TYPE_INVALID); +			req_sent = 0; +		} + +		send_reply_and_unref(connection, message); + +		free(peer_addr); + +		/* if failed, request the next element */ +		if (!req_sent) { +			/* remove the element from the list */ +			dbus_data->discovered_devices = slist_remove(dbus_data->discovered_devices, dev); +			free(dev->bdaddr); +			free(dev); + +			/* get the next element */ +			l = slist_find(dbus_data->discovered_devices, &name_status, remote_name_find_by_name_status); + +			if (!l) { +				/* no more devices: exit */ +				ret_val = -1; +				goto failed; +			} -	hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, -						REMOTE_NAME_REQ_CP_SIZE, &cp); +			dev = l->data; +		} +	} while (!req_sent); +failed:  	hci_close_dev(dd); -	return 0; +	return ret_val;  }  void hcid_dbus_inquiry_complete(bdaddr_t *local) @@ -686,17 +744,13 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local)  	snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id);  	if (dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { -		if (pdata->discover_state == DISCOVER_RUNNING_WITH_NAMES) { -			/* start name resolving */ +		if (!remote_name_resolve(pdata)) {  			pdata->discover_state = RESOLVING_NAMES; - -			if (!remote_name_resolve(pdata)) -				goto failed; /* skip, sending the first name to resolve */ -			 -			pdata->discover_state = DISCOVER_OFF; /* no names to resolve */ - +			goto failed; /* skip - there is name to resolve */  		} +		pdata->discover_state = DISCOVER_OFF; +  		/* free discovered devices list */  		slist_foreach(pdata->discovered_devices, discovered_device_free, NULL);  		slist_free(pdata->discovered_devices); @@ -822,26 +876,17 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i  			goto failed; /* don't sent the name again */  	} -	signal_name = dbus_message_new_signal(path, ADAPTER_INTERFACE, -						"RemoteNameUpdated"); -	if (signal_name == NULL) { -		error("Can't allocate D-Bus message"); -		goto failed; -	} -  	snprintf(filename, PATH_MAX, "%s/%s/names", STORAGEDIR, local_addr); -  	name = textfile_get(filename, peer_addr);  	if (name) { -		dbus_message_append_args(signal_name, -					 DBUS_TYPE_STRING, &peer_addr, -					 DBUS_TYPE_STRING, &name, -					 DBUS_TYPE_INVALID); - -		if (dbus_connection_send(connection, signal_name, NULL) == FALSE) -			error("Can't send D-Bus remote name updated signal"); +		signal_name = dev_signal_factory(pdata->dev_id, "RemoteNameUpdate", +							DBUS_TYPE_STRING, &peer_addr, +							DBUS_TYPE_STRING, &name, +							DBUS_TYPE_INVALID); +		send_reply_and_unref(connection, signal_name); +		free(name);  		name_status = NAME_SENT;  	} @@ -854,15 +899,8 @@ failed:  	if (signal_device)  		dbus_message_unref(signal_device); -	if (signal_name) -		dbus_message_unref(signal_name); -  	bt_free(local_addr);  	bt_free(peer_addr); - -	if (name) -		bt_free(name); -  }  void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name) @@ -891,67 +929,41 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char  	/* if the requested name failed, don't send signal and request the next name */  	if (status) -		goto request_next; - - -	/* send the remote name update signal */ -	message = dbus_message_new_signal(path, ADAPTER_INTERFACE, -						"RemoteNameUpdated"); -	if (message == NULL) { -		error("Can't allocate D-Bus message"); -		goto failed; -	} - -	dbus_message_append_args(message, -					DBUS_TYPE_STRING, &peer_addr, -					DBUS_TYPE_STRING, &name, -					DBUS_TYPE_INVALID); - -	if (dbus_connection_send(connection, message, NULL) == FALSE) { -		error("Can't send D-Bus remote name updated signal"); -		goto failed; -	} - -	dbus_connection_flush(connection); - -request_next: -	if (!pdata->requestor_name) -		goto failed; /* requested by an external app */ - +		message = dev_signal_factory(pdata->dev_id, "RemoteNameFailed", +						DBUS_TYPE_STRING, &peer_addr, +						DBUS_TYPE_INVALID); +	else  +		message = dev_signal_factory(pdata->dev_id, "RemoteNameUpdated", +					     	DBUS_TYPE_STRING, &peer_addr, +						DBUS_TYPE_STRING, &name, +						DBUS_TYPE_INVALID); + +	send_reply_and_unref(connection, message); + +	/* check if there is more devices to request names */  	if (!remote_name_resolve(pdata)) -		goto failed; /* skip: there is more remote name to resolve */ +		goto failed; /* skip if a new request has been sent */  	/* free discovered devices list */  	slist_foreach(pdata->discovered_devices, discovered_device_free, NULL);  	slist_free(pdata->discovered_devices);  	pdata->discovered_devices = NULL; -	if (message) -		dbus_message_unref(message); -	 -	message = dbus_message_new_signal(path, ADAPTER_INTERFACE, -						"DiscoveryCompleted"); -	if (message == NULL) { -		error("Can't allocate D-Bus message"); -		goto failed; -	} - -	if (dbus_connection_send(connection, message, NULL) == FALSE) { -		error("Can't send D-Bus discovery completed signal"); -		goto failed; -	} +	if (pdata->discover_state != DISCOVER_OFF) { +		message = dbus_message_new_signal(path, ADAPTER_INTERFACE, +						  "DiscoveryCompleted"); -	dbus_connection_flush(connection); +		send_reply_and_unref(connection, message); -	free(pdata->requestor_name); -	pdata->requestor_name = NULL; +		if (pdata->requestor_name) { +			free(pdata->requestor_name); +			pdata->requestor_name = NULL; +		} -	pdata->discover_state = DISCOVER_OFF; +		pdata->discover_state = DISCOVER_OFF; +	}  failed: -	if (message) -		dbus_message_unref(message); -  	bt_free(local_addr);  	bt_free(peer_addr);  } diff --git a/hcid/dbus.h b/hcid/dbus.h index 98d89658..8eba6a95 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -82,7 +82,7 @@ typedef enum {  typedef enum {  	NAME_PENDING,  	NAME_SENT -}name_status_t; +} name_status_t;  struct discovered_dev_info {  	bdaddr_t *bdaddr; @@ -142,6 +142,7 @@ DBusHandlerResult error_out_of_memory(DBusConnection *conn, DBusMessage *msg);  DBusHandlerResult error_no_such_adapter(DBusConnection *conn, DBusMessage *msg);  DBusHandlerResult error_unknown_address(DBusConnection *conn, DBusMessage *msg);  DBusHandlerResult error_not_available(DBusConnection *conn, DBusMessage *msg); +DBusHandlerResult error_request_deferred(DBusConnection *conn, DBusMessage *msg);  DBusHandlerResult error_not_connected(DBusConnection *conn, DBusMessage *msg);  DBusHandlerResult error_unsupported_major_class(DBusConnection *conn, DBusMessage *msg);  DBusHandlerResult error_connection_attempt_failed(DBusConnection *conn, DBusMessage *msg, int err); @@ -185,6 +186,10 @@ static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusM  void discovered_device_free(void *data, void *user_data);  int bonding_requests_find(const void *data, const void *user_data); +int remote_name_find_by_bdaddr(const void *data, const void *user_data); +int remote_name_append(struct slist **list, bdaddr_t *bdaddr, name_status_t name_status); +int remote_name_resolve(struct hci_dbus_data *dbus_data); +  /*   * Scanning modes, used by DEV_SET_MODE   * off: remote devices are not allowed to find or connect to this device | 
