From 12ccf5ea0fa53059e0870a49b67a36bdd21fe0c8 Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Tue, 30 Jan 2024 18:24:59 +0800 Subject: [PATCH] Monitor: Remove handle before assigning It is possible to have some handles not removed, for example the host may decide not to wait for disconnection complete event when it is suspending. In this case, when the peer device reconnected, we might have two of the some handle assigned and create problem down the road. This patch solves the issue by always removing any previous handles when assigning a new handle if they are the same. Reviewed-by: Zhengping Jiang --- monitor/packet.c | 79 ++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/monitor/packet.c b/monitor/packet.c index 42e711caf..164cc82bb 100644 --- a/monitor/packet.c +++ b/monitor/packet.c @@ -189,59 +189,66 @@ static struct packet_conn_data *lookup_parent(uint16_t handle) return NULL; } -static void assign_handle(uint16_t index, uint16_t handle, uint8_t type, - uint8_t *dst, uint8_t dst_type) +static struct packet_conn_data *release_handle(uint16_t handle) { int i; for (i = 0; i < MAX_CONN; i++) { - if (conn_list[i].handle == 0xffff) { - hci_devba(index, (bdaddr_t *)conn_list[i].src); + struct packet_conn_data *conn = &conn_list[i]; + + if (conn->handle == handle) { + if (conn->destroy) + conn->destroy(conn->data); - conn_list[i].index = index; - conn_list[i].handle = handle; - conn_list[i].type = type; + queue_destroy(conn->tx_q, free); + queue_destroy(conn->chan_q, free); + memset(conn, 0, sizeof(*conn)); + conn->handle = 0xffff; + return conn; + } + } - if (!dst) { - struct packet_conn_data *p; + return NULL; +} - /* If destination is not set attempt to use the - * parent one if that exists. - */ - p = lookup_parent(handle); - if (p) { - memcpy(conn_list[i].dst, p->dst, - sizeof(conn_list[i].dst)); - conn_list[i].dst_type = p->dst_type; - } +static void assign_handle(uint16_t index, uint16_t handle, uint8_t type, + uint8_t *dst, uint8_t dst_type) +{ + struct packet_conn_data *conn = release_handle(handle); + int i; + if (!conn) { + for (i = 0; i < MAX_CONN; i++) { + if (conn_list[i].handle == 0xffff) { + conn = &conn_list[i]; break; } - - memcpy(conn_list[i].dst, dst, sizeof(conn_list[i].dst)); - conn_list[i].dst_type = dst_type; - break; } } -} -static void release_handle(uint16_t handle) -{ - int i; + if (!conn) + return; - for (i = 0; i < MAX_CONN; i++) { - struct packet_conn_data *conn = &conn_list[i]; + hci_devba(index, (bdaddr_t *)conn->src); - if (conn->handle == handle) { - if (conn->destroy) - conn->destroy(conn->data); + conn->index = index; + conn->handle = handle; + conn->type = type; - queue_destroy(conn->tx_q, free); - queue_destroy(conn->chan_q, free); - memset(conn, 0, sizeof(*conn)); - conn->handle = 0xffff; - break; + if (!dst) { + struct packet_conn_data *p; + + /* If destination is not set attempt to use the parent one if + * that exists. + */ + p = lookup_parent(handle); + if (p) { + memcpy(conn->dst, p->dst, sizeof(conn->dst)); + conn->dst_type = p->dst_type; } + } else { + memcpy(conn->dst, dst, sizeof(conn->dst)); + conn->dst_type = dst_type; } } -- 2.47.3