Re: [PATCH BlueZ 1/5] btdev: check error conditions for HCI_Create_Connection_Cancel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



to, 2023-07-27 kello 00:25 +0300, Pauli Virtanen kirjoitti:
> Create Connection Cancel shall return Command Complete with error status
> when there is no Create Connection that can be canceled.  In these
> cases, we should not send a (spurious) Connection Complete event.
> 
> Fix by keeping a list of pending Create Connection commands, and
> returning command errors if there is none pending at the moment.
> ---
>  emulator/btdev.c | 76 +++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 68 insertions(+), 8 deletions(-)
> 
> diff --git a/emulator/btdev.c b/emulator/btdev.c
> index 637f0bb98..0c75e71c0 100644
> --- a/emulator/btdev.c
> +++ b/emulator/btdev.c
> @@ -62,6 +62,7 @@ struct hook {
>  
>  #define MAX_HOOK_ENTRIES 16
>  #define MAX_EXT_ADV_SETS 3
> +#define MAX_PENDING_CONN 16
>  
>  struct btdev_conn {
>  	uint16_t handle;
> @@ -223,6 +224,8 @@ struct btdev {
>  	uint8_t  le_rl_enable;
>  	uint16_t le_rl_timeout;
>  
> +	struct btdev *pending_conn[MAX_PENDING_CONN];
> +
>  	uint8_t le_local_sk256[32];
>  
>  	uint16_t sync_train_interval;
> @@ -1211,10 +1214,36 @@ static struct btdev_conn *conn_link_bis(struct btdev *dev, struct btdev *remote,
>  	return conn;
>  }
>  
> +static void pending_conn_add(struct btdev *btdev, struct btdev *remote)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(btdev->pending_conn); ++i) {
> +		if (!btdev->pending_conn[i]) {
> +			btdev->pending_conn[i] = remote;
> +			return;
> +		}
> +	}
> +}
> +
> +static bool pending_conn_del(struct btdev *btdev, struct btdev *remote)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(btdev->pending_conn); ++i) {
> +		if (btdev->pending_conn[i] == remote) {
> +			btdev->pending_conn[i] = NULL;
> +			return true;
> +		}
> +	}
> +	return false;
> +}
> +
>  static void conn_complete(struct btdev *btdev,
>  					const uint8_t *bdaddr, uint8_t status)
>  {
>  	struct bt_hci_evt_conn_complete cc;
> +	struct btdev *remote = find_btdev_by_bdaddr(bdaddr);
>  
>  	if (!status) {
>  		struct btdev_conn *conn;
> @@ -1223,6 +1252,8 @@ static void conn_complete(struct btdev *btdev,
>  		if (!conn)
>  			return;
>  
> +		pending_conn_del(conn->link->dev, btdev);
> +
>  		cc.status = status;
>  		memcpy(cc.bdaddr, btdev->bdaddr, 6);
>  		cc.encr_mode = 0x00;
> @@ -1240,6 +1271,8 @@ static void conn_complete(struct btdev *btdev,
>  		cc.link_type = 0x01;
>  	}
>  
> +	pending_conn_del(btdev, remote);
> +
>  	cc.status = status;
>  	memcpy(cc.bdaddr, bdaddr, 6);
>  	cc.encr_mode = 0x00;
> @@ -1260,6 +1293,8 @@ static int cmd_create_conn_complete(struct btdev *dev, const void *data,
>  		memcpy(cr.dev_class, dev->dev_class, 3);
>  		cr.link_type = 0x01;
>  
> +		pending_conn_add(dev, remote);
> +
>  		send_event(remote, BT_HCI_EVT_CONN_REQUEST, &cr, sizeof(cr));
>  	} else {
>  		conn_complete(dev, cmd->bdaddr, BT_HCI_ERR_PAGE_TIMEOUT);
> @@ -1296,14 +1331,47 @@ static int cmd_add_sco_conn(struct btdev *dev, const void *data, uint8_t len)
>  	cc.encr_mode = 0x00;
>  
>  done:
> +	pending_conn_del(dev, conn->link->dev);
> +
>  	send_event(dev, BT_HCI_EVT_CONN_COMPLETE, &cc, sizeof(cc));
>  
>  	return 0;
>  }
>  
> +static bool match_bdaddr(const void *data, const void *match_data)
> +{
> +	const struct btdev_conn *conn = data;
> +	const uint8_t *bdaddr = match_data;
> +
> +	return !memcmp(conn->link->dev->bdaddr, bdaddr, 6);
> +}
> +
>  static int cmd_create_conn_cancel(struct btdev *dev, const void *data,
>  							uint8_t len)
>  {
> +	const struct bt_hci_cmd_create_conn_cancel *cmd = data;
> +	struct btdev *remote = find_btdev_by_bdaddr(cmd->bdaddr);
> +	struct btdev_conn *conn;
> +
> +	/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E page 1848
> +	 *
> +	 * If the connection is already established, and the
> +	 * HCI_Connection_Complete event has been sent, then the Controller
> +	 * shall return an HCI_Command_Complete event with the error code
> +	 * Connection Already Exists (0x0B). If the HCI_Create_Connection_Cancel
> +	 * command is sent to the Controller without a preceding
> +	 * HCI_Create_Connection command to the same device, the BR/EDR
> +	 * Controller shall return an HCI_Command_Complete event with the error
> +	 * code Unknown Connection Identifier (0x02).
> +	 */
> +	if (!pending_conn_del(dev, remote)) {
> +		conn = queue_find(dev->conns, match_bdaddr, cmd->bdaddr);
> +		if (conn)
> +			return -EEXIST;
> +
> +		return -ENOENT;
> +	}
> +
>  	cmd_status(dev, BT_HCI_ERR_SUCCESS, BT_HCI_CMD_CREATE_CONN_CANCEL);

This should have been Command_Complete not Command_Status.

For v2

>  
>  	return 0;
> @@ -1372,14 +1440,6 @@ static int cmd_link_key_reply(struct btdev *dev, const void *data, uint8_t len)
>  	return 0;
>  }
>  
> -static bool match_bdaddr(const void *data, const void *match_data)
> -{
> -	const struct btdev_conn *conn = data;
> -	const uint8_t *bdaddr = match_data;
> -
> -	return !memcmp(conn->link->dev->bdaddr, bdaddr, 6);
> -}
> -
>  static void auth_complete(struct btdev_conn *conn, uint8_t status)
>  {
>  	struct bt_hci_evt_auth_complete ev;




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux