diff options
| author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-04-18 21:01:11 +0000 | 
|---|---|---|
| committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-04-18 21:01:11 +0000 | 
| commit | 9575f385006817d43cdd5bacadd0b37f2e02bc9a (patch) | |
| tree | 085331c32733f1a84acb52815696170819c13a46 | |
| parent | d168dc64106e440a149718436e63912b18e0064e (diff) | |
Added HCI cmds queue to retrieve remote infos
| -rw-r--r-- | hcid/dbus-todo.txt | 25 | ||||
| -rw-r--r-- | hcid/dbus.c | 83 | ||||
| -rw-r--r-- | hcid/hcid.h | 20 | ||||
| -rw-r--r-- | hcid/security.c | 146 | 
4 files changed, 159 insertions, 115 deletions
| diff --git a/hcid/dbus-todo.txt b/hcid/dbus-todo.txt index b906a55d..3fecc3eb 100644 --- a/hcid/dbus-todo.txt +++ b/hcid/dbus-todo.txt @@ -7,25 +7,6 @@ Date: 2006/04/11  Description: Review these errors. The usage of "Does not exists"  and "Not available" are confusing. -* pending HCI requests -Date: 2006/04/11 -Description: The D-Bus authentication method creates automatically -an ACL connection when required and disconnects when the procedure -finishes. When the HCI connection complete arrives, remote name/ -version/features are queued. Considering that the authentication -is not queued, when this procedure finishes and the disconnect is -requested, the remaining elements in the queue can't be executed. - -* active connections verification -Date: 2006/04/11 -Description: get_bdaddr function is called frequently in the -security.c file. In a real usage scenario, the disconnect -command can be sent by another process or BlueZ D-Bus method. -On this case if there is pending request confirmation(eg: remote -version complete or remote features complete), when the -confirmation arrives the bdaddr can't be retrieved because -there isn't active connection anymore. Suggestion: keep a active -connection list instead of call the get_bdaddr frequently. Keep -in mind that D-Bus data already has a list to store active -connections. - +* code standard for sending msg function +Date: 2006/04/13 +Description: use send_reply_and_unref when possible. diff --git a/hcid/dbus.c b/hcid/dbus.c index 3354da5f..cd864215 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -578,8 +578,7 @@ void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci)  void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status)  {  	struct hci_dbus_data *pdata; -	DBusMessage *msg_reply = NULL; -	DBusMessage *msg_signal = NULL; +	DBusMessage *message = NULL;  	char *local_addr, *peer_addr;  	const char *name;  	bdaddr_t tmp; @@ -615,49 +614,38 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u  	 */  	name = status ? "BondingFailed" : "BondingCreated";  	/* authentication signal */ -	msg_signal = dbus_message_new_signal(path, ADAPTER_INTERFACE, name); - -	if (msg_signal == NULL) { -		error("Can't allocate D-Bus message"); -		goto failed; -	} - -	dbus_message_append_args(msg_signal, -					 DBUS_TYPE_STRING, &peer_addr, -					 DBUS_TYPE_INVALID); - -	if (dbus_connection_send(connection, msg_signal, NULL) == FALSE) { -		error("Can't send D-Bus bonding created signal"); -		goto failed; -	} +	message = dev_signal_factory(pdata->dev_id, name, +					DBUS_TYPE_STRING, &peer_addr, +					DBUS_TYPE_INVALID); -	dbus_connection_flush(connection); +	send_reply_and_unref(connection, message);  	if (!pdata->bonding)  		goto failed; /* skip: no bonding req pending */ -	msg_reply = dbus_msg_new_authentication_return(pdata->bonding->rq, status); -	if (dbus_connection_send(connection, msg_reply, NULL) == FALSE) { -		error("Can't send D-Bus reply for create bonding request"); -		goto failed; -	} - -	/* FIXME: disconnect if required */  	if (pdata->bonding->disconnect) {  		struct slist *l;  		l = slist_find(pdata->active_conn, peer, active_conn_find_by_bdaddr);  		if (l) {  			struct active_conn_info *con = l->data; -			int dd = hci_open_dev(pdata->dev_id); -			/* Send the HCI disconnect command */ -			if (hci_disconnect(dd, con->handle, HCI_OE_USER_ENDED_CONNECTION, 100) < 0) { -				error("Disconnect failed"); -			} -			hci_close_dev(dd); +			struct hci_req_data *data; +			disconnect_cp cp; +			memset(&cp, 0, sizeof(cp)); + +			cp.handle = con->handle; +			cp.reason = HCI_OE_USER_ENDED_CONNECTION; + +			data = hci_req_data_new(pdata->dev_id, peer, OGF_LINK_CTL, +						OCF_DISCONNECT, EVT_DISCONN_COMPLETE, +						&cp, DISCONNECT_CP_SIZE); +			hci_req_queue_append(data);  		}  	} +	message = dbus_msg_new_authentication_return(pdata->bonding->rq, status); +	send_reply_and_unref(connection, message); +  	bonding_request_free(pdata->bonding);  	pdata->bonding = NULL; @@ -665,12 +653,6 @@ void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, const u  	pdata->requestor_name = NULL;  failed: -	if (msg_signal) -		dbus_message_unref(msg_signal); - -	if (msg_reply) -		dbus_message_unref(msg_reply); -  	bt_free(local_addr);  	bt_free(peer_addr);  } @@ -1234,13 +1216,32 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle  		goto failed;  	dev = l->data; -	/* add in the active connetions list */ +  	baswap(&tmp, &dev->bdaddr); peer_addr = batostr(&tmp); -	/* Sent the remote device disconnected signal */ -	message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceDisconnected"); +	/* clean pending HCI cmds */ +	hci_req_queue_remove(pdata->dev_id, &dev->bdaddr); -	dbus_message_append_args(message, +	/* Check if there is a pending Bonding */ +	if (pdata->bonding) { +		message = dev_signal_factory(pdata->dev_id, "BondingFailed", +						DBUS_TYPE_STRING, &peer_addr, +						DBUS_TYPE_INVALID); + +		send_reply_and_unref(connection, message); + +		message = dbus_msg_new_authentication_return(pdata->bonding->rq, status); +		send_reply_and_unref(connection, message); + +		bonding_request_free(pdata->bonding); +		pdata->bonding = NULL; + +		free(pdata->requestor_name); +		pdata->requestor_name = NULL; +	} + +	/* Sent the remote device disconnected signal */ +	message = dev_signal_factory(pdata->dev_id, "RemoteDeviceDisconnected",  					DBUS_TYPE_STRING, &peer_addr,  					DBUS_TYPE_INVALID); diff --git a/hcid/hcid.h b/hcid/hcid.h index 2f5d74c1..066f9358 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -84,6 +84,26 @@ struct hcid_opts {  };  extern struct hcid_opts hcid; +typedef enum { +	REQ_PENDING, +	REQ_SENT +} req_status_t; + +struct hci_req_data { +	int dev_id; +	int event; +	req_status_t status; +	bdaddr_t dba; +	uint16_t ogf; +	uint16_t ocf; +	void *cparam; +	int clen; +}; + +struct hci_req_data *hci_req_data_new(int dev_id, const bdaddr_t *dba, uint16_t ogf, uint16_t ocf, int event, const void *cparam, int clen); +void hci_req_queue_append(struct hci_req_data *data); +void hci_req_queue_remove(int dev_id, bdaddr_t *dba); +  #define HCID_SEC_NONE	0  #define HCID_SEC_AUTO	1  #define HCID_SEC_USER	2 diff --git a/hcid/security.c b/hcid/security.c index 72fcc9e6..6f0aa10f 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -62,17 +62,9 @@ static struct g_io_info io_data[HCI_MAX_DEV];  static int pairing = HCID_PAIRING_MULTI; -struct hci_req_data { -	int dev; -	uint16_t ogf; -	uint16_t ocf; -	void *cparam; -	int clen; -}; -  static struct slist *hci_req_queue = NULL; -static struct hci_req_data *hci_req_data_new(int dev, uint16_t ogf, uint16_t ocf, const void *cparam, int clen) +struct hci_req_data *hci_req_data_new(int dev_id, const bdaddr_t *dba, uint16_t ogf, uint16_t ocf, int event, const void *cparam, int clen)  {  	struct hci_req_data *data; @@ -87,48 +79,103 @@ static struct hci_req_data *hci_req_data_new(int dev, uint16_t ogf, uint16_t ocf  		free(data);  		return NULL;  	} - +	  	memcpy(data->cparam, cparam, clen); -	data->dev = dev; +	bacpy(&data->dba, dba); + +	data->dev_id = dev_id; +	data->status = REQ_PENDING;  	data->ogf = ogf;  	data->ocf = ocf; +	data->event = event;  	data->clen = clen;  	return data;  } -static int hci_req_find_by_dev(const void *data, const void *user_data) +void hci_req_queue_append(struct hci_req_data *data) +{ +	hci_req_queue = slist_append(hci_req_queue, data); +} + +void hci_req_queue_remove(int dev_id, bdaddr_t *dba) +{ +	struct slist *cur, *next; +	struct hci_req_data *req; + +	for (cur = hci_req_queue; cur != NULL; cur = next) { +		req = cur->data; +		next = cur->next; +		if ((req->dev_id != dev_id) || (bacmp(&req->dba, dba))) +			continue; + +		hci_req_queue = slist_remove(hci_req_queue, req); +		free(req->cparam); +		free(req); +	} +} + +static int hci_req_find_by_devid(const void *data, const void *user_data)  {  	const struct hci_req_data *req = data; -	const int *dev = user_data; +	const int *dev_id = user_data; -	return (*dev - req->dev); +	return (*dev_id - req->dev_id);  } -static int check_pending_hci_req(int dev) +static void check_pending_hci_req(int dev_id, int event)  {  	struct hci_req_data *data;  	struct slist *l; +	int dd, ret_val;  	if (!hci_req_queue) -		return -1; +		return; -	l = slist_find(hci_req_queue, &dev, hci_req_find_by_dev); +	/* find the first element(pending)*/ +	l = slist_find(hci_req_queue, &dev_id, hci_req_find_by_devid);  	if (!l) -		return -1; +		return;  	data = l->data; -	hci_send_cmd(dev, data->ogf, data->ocf, data->clen, data->cparam); +	/* skip if there is pending confirmation */ +	if (data->status == REQ_SENT) { +		if (data->event != event) +			return; + +		/* remove the confirmed cmd */ +		hci_req_queue = slist_remove(hci_req_queue, data); +		free(data->cparam); +		free(data); +	} + +	/* send the next pending cmd */ +	dd = hci_open_dev(dev_id); +	do { +		l = slist_find(hci_req_queue, &dev_id, hci_req_find_by_devid); + +		if (!l) +			goto failed; + +		data = l->data; +		data->status = REQ_SENT; +		 +		ret_val = hci_send_cmd(dd, data->ogf, data->ocf, data->clen, data->cparam); +		if (ret_val < 0) { +			hci_req_queue = slist_remove(hci_req_queue, data); +			free(data->cparam); +			free(data); +		} -	hci_req_queue = slist_remove(hci_req_queue, data); +	} while(ret_val < 0); -	free(data->cparam); -	free(data); +failed: +	hci_close_dev(dd); -	return 0; +	return;  }  static inline int get_bdaddr(int dev, bdaddr_t *sba, uint16_t handle, bdaddr_t *dba) @@ -412,9 +459,6 @@ static inline void remote_name_information(int dev, bdaddr_t *sba, void *ptr)  	}  	hcid_dbus_remote_name(sba, &dba, evt->status, name); - -	/* pending remote version or remote features */ -	check_pending_hci_req(dev);  }  static inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr) @@ -430,9 +474,6 @@ static inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr)  	write_version_info(sba, &dba, btohs(evt->manufacturer),  				evt->lmp_ver, btohs(evt->lmp_subver)); - -	/* pending remote features */ -	check_pending_hci_req(dev);  }  static inline void inquiry_complete(int dev, bdaddr_t *sba, void *ptr) @@ -531,23 +572,13 @@ static inline void remote_features_information(int dev, bdaddr_t *sba, void *ptr  	write_features_info(sba, &dba, evt->features);  } -static inline void name_resolve(int dev, bdaddr_t *bdaddr) -{ -	remote_name_req_cp cp; - -	memset(&cp, 0, sizeof(cp)); -	bacpy(&cp.bdaddr, bdaddr); -	cp.pscan_rep_mode = 0x02; - -	hci_send_cmd(dev, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, -						REMOTE_NAME_REQ_CP_SIZE, &cp); -} - -static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr) +static inline void conn_complete(int dev, int dev_id, bdaddr_t *sba, void *ptr)  {  	evt_conn_complete *evt = ptr;  	char filename[PATH_MAX]; +	remote_name_req_cp cp_name;  	bdaddr_t tmp; +	struct hci_req_data *data;  	char *str, *local_addr, *peer_addr;  	hcid_dbus_conn_complete(sba, evt->status, evt->handle, &evt->bdaddr); @@ -557,7 +588,16 @@ static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)  	update_lastused(sba, &evt->bdaddr); -	name_resolve(dev, &evt->bdaddr); +	/* Request remote name */ +	memset(&cp_name, 0, sizeof(cp_name)); +	bacpy(&cp_name.bdaddr, &evt->bdaddr); +	cp_name.pscan_rep_mode = 0x02; + +	data = hci_req_data_new(dev_id, &evt->bdaddr, OGF_LINK_CTL, +				OCF_REMOTE_NAME_REQ, EVT_REMOTE_NAME_REQ_COMPLETE, +				&cp_name, REMOTE_NAME_REQ_CP_SIZE); + +	hci_req_queue_append(data);  	/* check if the remote version needs be requested */  	baswap(&tmp, sba); local_addr = batostr(&tmp); @@ -568,15 +608,15 @@ static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)  	str = textfile_get(filename, peer_addr);  	if (!str) { -		struct hci_req_data *data;  		read_remote_version_cp cp;  		cp.handle = evt->handle; -		data = hci_req_data_new(dev, OGF_LINK_CTL, OCF_READ_REMOTE_VERSION, -						&cp, READ_REMOTE_VERSION_CP_SIZE); +		data = hci_req_data_new(dev_id, &evt->bdaddr, OGF_LINK_CTL, +					OCF_READ_REMOTE_VERSION, EVT_READ_REMOTE_VERSION_COMPLETE, +					&cp, READ_REMOTE_VERSION_CP_SIZE); -		hci_req_queue = slist_append(hci_req_queue, data); +		hci_req_queue_append(data);  	} else {  		/* skip: remote version found */  		free(str); @@ -588,15 +628,15 @@ static inline void conn_complete(int dev, bdaddr_t *sba, void *ptr)  	str = textfile_get(filename, peer_addr);  	if (!str) { -		struct hci_req_data *data;  		read_remote_features_cp cp;  		cp.handle = evt->handle; -		data = hci_req_data_new(dev, OGF_LINK_CTL, OCF_READ_REMOTE_FEATURES, -						&cp, READ_REMOTE_FEATURES_CP_SIZE); +		data = hci_req_data_new(dev_id, &evt->bdaddr, OGF_LINK_CTL, +					OCF_READ_REMOTE_FEATURES, EVT_READ_REMOTE_FEATURES_COMPLETE, +					&cp, READ_REMOTE_FEATURES_CP_SIZE); -		hci_req_queue = slist_append(hci_req_queue, data); +		hci_req_queue_append(data);  	} else {  		/* skip: remote features found */  		free(str); @@ -702,7 +742,7 @@ static gboolean io_security_event(GIOChannel *chan, GIOCondition cond, gpointer  		break;  	case EVT_CONN_COMPLETE: -		conn_complete(dev, &di->bdaddr, ptr); +		conn_complete(dev, di->dev_id, &di->bdaddr, ptr);  		break;  	case EVT_DISCONN_COMPLETE: @@ -713,6 +753,8 @@ static gboolean io_security_event(GIOChannel *chan, GIOCondition cond, gpointer  		auth_complete(dev, &di->bdaddr, ptr);  		break;  	} +	/* check for pending cmd request */ +	check_pending_hci_req(di->dev_id, eh->evt);  	if (hci_test_bit(HCI_SECMGR, &di->flags))  		return TRUE; | 
