1f9f848faSopenharmony_ci/*
2f9f848faSopenharmony_ci * Copyright (c) 2013-2019, Huawei Technologies Co., Ltd. All rights reserved.
3f9f848faSopenharmony_ci * Copyright (c) 2020, Huawei Device Co., Ltd. All rights reserved.
4f9f848faSopenharmony_ci *
5f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
6f9f848faSopenharmony_ci * are permitted provided that the following conditions are met:
7f9f848faSopenharmony_ci *
8f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
9f9f848faSopenharmony_ci *    conditions and the following disclaimer.
10f9f848faSopenharmony_ci *
11f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12f9f848faSopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
13f9f848faSopenharmony_ci *    provided with the distribution.
14f9f848faSopenharmony_ci *
15f9f848faSopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16f9f848faSopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
17f9f848faSopenharmony_ci *    permission.
18f9f848faSopenharmony_ci *
19f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20f9f848faSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21f9f848faSopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f9f848faSopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23f9f848faSopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24f9f848faSopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25f9f848faSopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26f9f848faSopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27f9f848faSopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28f9f848faSopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29f9f848faSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30f9f848faSopenharmony_ci */
31f9f848faSopenharmony_ci
32f9f848faSopenharmony_ci/* Architecture Analysis
33f9f848faSopenharmony_ci *********************************************************************************************
34f9f848faSopenharmony_ci *      The USB Devices Topology    ---    Translate   -->  Binary Tree Map
35f9f848faSopenharmony_ci *               BUS                                             BUS
36f9f848faSopenharmony_ci *                |                                              /
37f9f848faSopenharmony_ci *       ---------------------                                  /
38f9f848faSopenharmony_ci *       |                   |                                 H01
39f9f848faSopenharmony_ci *      H01                 H02...                             / \
40f9f848faSopenharmony_ci *       |                   |                                /   \
41f9f848faSopenharmony_ci * ------------      ---------------                        H11    \---------H02
42f9f848faSopenharmony_ci * |          |      |             |         ------\        / \              / \
43f9f848faSopenharmony_ci *H11        H12... H21           H22...     -------\      /   \            /   \
44f9f848faSopenharmony_ci * |          |      |             |         -------/     D1   H12         H21  ...
45f9f848faSopenharmony_ci *D1         D2      |            D3         ------/           / \         / \
46f9f848faSopenharmony_ci *              ------------                                  /   \       /   \
47f9f848faSopenharmony_ci *              |          |                                 D2   ...    H31   \----H22
48f9f848faSopenharmony_ci *             H31        H32...                                          / \        / \
49f9f848faSopenharmony_ci *              |          |                                             /   \      /   \
50f9f848faSopenharmony_ci *             D4         D5                                            D4   H32   D3   ...
51f9f848faSopenharmony_ci *                                                                      / \
52f9f848faSopenharmony_ci *                                                                     /   \
53f9f848faSopenharmony_ci *                                                                    D5   ...
54f9f848faSopenharmony_ci *********************************************************************************************
55f9f848faSopenharmony_ci */
56f9f848faSopenharmony_ci
57f9f848faSopenharmony_ci#include <stdlib.h>
58f9f848faSopenharmony_ci#include <string.h>
59f9f848faSopenharmony_ci#include <los_printf_pri.h>
60f9f848faSopenharmony_ci
61f9f848faSopenharmony_ci#include "implementation/usb_btree.h"
62f9f848faSopenharmony_ci
63f9f848faSopenharmony_ci
64f9f848faSopenharmony_ci#ifdef USB_BINARY_TREE_DEBUG
65f9f848faSopenharmony_ci#define	BT_DEBUG(x...) dprintf(x)
66f9f848faSopenharmony_ci#else
67f9f848faSopenharmony_ci#define	BT_DEBUG(x...) do{}while(0)
68f9f848faSopenharmony_ci#endif
69f9f848faSopenharmony_ci
70f9f848faSopenharmony_ciextern usbd_bt_tree hub_tree;
71f9f848faSopenharmony_ci
72f9f848faSopenharmony_cistruct usbd_bt_node *
73f9f848faSopenharmony_ciusbd_create_bt_node(struct node_info *info)
74f9f848faSopenharmony_ci{
75f9f848faSopenharmony_ci	struct usbd_bt_node *node = (usbd_bt_node *)malloc(sizeof(usbd_bt_node));
76f9f848faSopenharmony_ci	if (node == NULL) {
77f9f848faSopenharmony_ci		PRINT_ERR("Binary tree node alloc failed!\n");
78f9f848faSopenharmony_ci		return (NULL);
79f9f848faSopenharmony_ci	}
80f9f848faSopenharmony_ci
81f9f848faSopenharmony_ci	(void)memset_s(&node->info, sizeof(node->info), 0, sizeof(node->info));
82f9f848faSopenharmony_ci	node->info.port_no = info->port_no;
83f9f848faSopenharmony_ci	node->info.nameunit = info->nameunit;
84f9f848faSopenharmony_ci	node->lbt_node = NULL;
85f9f848faSopenharmony_ci	node->rbt_node = NULL;
86f9f848faSopenharmony_ci
87f9f848faSopenharmony_ci	BT_DEBUG("[create node] %p %s %d\n", node, node->info.nameunit, node->info.port_no);
88f9f848faSopenharmony_ci	return (node);
89f9f848faSopenharmony_ci}
90f9f848faSopenharmony_ci
91f9f848faSopenharmony_civoid
92f9f848faSopenharmony_ciusbd_free_bt_node(usbd_bt_node *node)
93f9f848faSopenharmony_ci{
94f9f848faSopenharmony_ci	BT_DEBUG("[free node] %p %s %d\n", node, node->info.nameunit, node->info.port_no);
95f9f848faSopenharmony_ci
96f9f848faSopenharmony_ci	node->info.nameunit = NULL;
97f9f848faSopenharmony_ci	node->info.port_no = 0;
98f9f848faSopenharmony_ci	node->lbt_node = NULL;
99f9f848faSopenharmony_ci	node->rbt_node = NULL;
100f9f848faSopenharmony_ci
101f9f848faSopenharmony_ci	free(node);
102f9f848faSopenharmony_ci}
103f9f848faSopenharmony_ci
104f9f848faSopenharmony_cistatic void
105f9f848faSopenharmony_ciusbd_release_bt_node(usbd_bt_node *node)
106f9f848faSopenharmony_ci{
107f9f848faSopenharmony_ci	if (node == NULL)
108f9f848faSopenharmony_ci		return;
109f9f848faSopenharmony_ci
110f9f848faSopenharmony_ci	usbd_release_bt_node(node->lbt_node);
111f9f848faSopenharmony_ci	usbd_release_bt_node(node->rbt_node);
112f9f848faSopenharmony_ci
113f9f848faSopenharmony_ci	if (node->info.nameunit != NULL)
114f9f848faSopenharmony_ci		usbd_free_bt_node(node);
115f9f848faSopenharmony_ci}
116f9f848faSopenharmony_ci
117f9f848faSopenharmony_cistatic struct usbd_bt_node *
118f9f848faSopenharmony_ciusbd_pre_order_bt_node(usbd_bt_node *node, struct node_info *info)
119f9f848faSopenharmony_ci{
120f9f848faSopenharmony_ci	usbd_bt_node *l_node, *r_node;
121f9f848faSopenharmony_ci
122f9f848faSopenharmony_ci	if (node == NULL) {
123f9f848faSopenharmony_ci		return (NULL);
124f9f848faSopenharmony_ci	}
125f9f848faSopenharmony_ci
126f9f848faSopenharmony_ci	if (node->info.nameunit == info->nameunit) {
127f9f848faSopenharmony_ci		if (node->info.port_no == info->port_no) {
128f9f848faSopenharmony_ci			return (node);
129f9f848faSopenharmony_ci		}
130f9f848faSopenharmony_ci	}
131f9f848faSopenharmony_ci
132f9f848faSopenharmony_ci	l_node = usbd_pre_order_bt_node(node->lbt_node, info);
133f9f848faSopenharmony_ci	if (l_node != NULL) {
134f9f848faSopenharmony_ci		return (l_node);
135f9f848faSopenharmony_ci	}
136f9f848faSopenharmony_ci	r_node = usbd_pre_order_bt_node(node->rbt_node, info);
137f9f848faSopenharmony_ci	if (r_node != NULL) {
138f9f848faSopenharmony_ci		return (r_node);
139f9f848faSopenharmony_ci	}
140f9f848faSopenharmony_ci
141f9f848faSopenharmony_ci	return (NULL);
142f9f848faSopenharmony_ci}
143f9f848faSopenharmony_ci
144f9f848faSopenharmony_cistatic bool f_find_device = false;
145f9f848faSopenharmony_cistatic struct usbd_bt_node *
146f9f848faSopenharmony_ciusbd_pre_order_hub_node(usbd_bt_node *node, char *devname, uint8_t *port_num)
147f9f848faSopenharmony_ci{
148f9f848faSopenharmony_ci	usbd_bt_node *l_node, *r_node;
149f9f848faSopenharmony_ci
150f9f848faSopenharmony_ci	if (node == NULL) {
151f9f848faSopenharmony_ci		return (NULL);
152f9f848faSopenharmony_ci	}
153f9f848faSopenharmony_ci
154f9f848faSopenharmony_ci	if (!strncmp(node->info.nameunit, "uhub", strlen("uhub"))) {
155f9f848faSopenharmony_ci		BT_DEBUG("[Hub Node] %p %s %d %d\n", node, node->info.nameunit, node->info.port_no, *port_num);
156f9f848faSopenharmony_ci		if (node->lbt_node == NULL) {
157f9f848faSopenharmony_ci			(*port_num)--;
158f9f848faSopenharmony_ci		} else {
159f9f848faSopenharmony_ci			if (!strncmp(node->lbt_node->info.nameunit, devname, strlen(devname))) {
160f9f848faSopenharmony_ci				(*port_num)--;
161f9f848faSopenharmony_ci				if (*port_num == 0)
162f9f848faSopenharmony_ci					f_find_device = 1;
163f9f848faSopenharmony_ci			}
164f9f848faSopenharmony_ci		}
165f9f848faSopenharmony_ci		if (*port_num == 0) {
166f9f848faSopenharmony_ci			return (node->lbt_node);
167f9f848faSopenharmony_ci		}
168f9f848faSopenharmony_ci	}
169f9f848faSopenharmony_ci
170f9f848faSopenharmony_ci	l_node = usbd_pre_order_hub_node(node->lbt_node, devname, port_num);
171f9f848faSopenharmony_ci	if (l_node != NULL) {
172f9f848faSopenharmony_ci		return (l_node);
173f9f848faSopenharmony_ci	}
174f9f848faSopenharmony_ci	r_node = usbd_pre_order_hub_node(node->rbt_node, devname, port_num);
175f9f848faSopenharmony_ci	if (r_node != NULL) {
176f9f848faSopenharmony_ci		return (r_node);
177f9f848faSopenharmony_ci	}
178f9f848faSopenharmony_ci	return (NULL);
179f9f848faSopenharmony_ci}
180f9f848faSopenharmony_ci
181f9f848faSopenharmony_cistatic void
182f9f848faSopenharmony_ciusbd_per_order_hub_quantity(usbd_bt_node *node, uint8_t *port_qty)
183f9f848faSopenharmony_ci{
184f9f848faSopenharmony_ci	if (node == NULL) {
185f9f848faSopenharmony_ci		return;
186f9f848faSopenharmony_ci	}
187f9f848faSopenharmony_ci
188f9f848faSopenharmony_ci	if (!strncmp(node->info.nameunit, "uhub", strlen("uhub"))) {
189f9f848faSopenharmony_ci		if (node->lbt_node == NULL) {
190f9f848faSopenharmony_ci			(*port_qty)++;
191f9f848faSopenharmony_ci		} else {
192f9f848faSopenharmony_ci			if (strncmp(node->lbt_node->info.nameunit, "uhub", strlen("uhub"))) {
193f9f848faSopenharmony_ci				(*port_qty)++;
194f9f848faSopenharmony_ci			}
195f9f848faSopenharmony_ci		}
196f9f848faSopenharmony_ci	}
197f9f848faSopenharmony_ci
198f9f848faSopenharmony_ci	usbd_per_order_hub_quantity(node->lbt_node, port_qty);
199f9f848faSopenharmony_ci	usbd_per_order_hub_quantity(node->rbt_node, port_qty);
200f9f848faSopenharmony_ci}
201f9f848faSopenharmony_ci
202f9f848faSopenharmony_ciint
203f9f848faSopenharmony_ciusbd_get_hub_quantity(void)
204f9f848faSopenharmony_ci{
205f9f848faSopenharmony_ci	uint8_t quantity = 0;
206f9f848faSopenharmony_ci
207f9f848faSopenharmony_ci	usbd_per_order_hub_quantity(hub_tree, &quantity);
208f9f848faSopenharmony_ci
209f9f848faSopenharmony_ci	return (quantity);
210f9f848faSopenharmony_ci}
211f9f848faSopenharmony_ci
212f9f848faSopenharmony_cistruct usbd_bt_node *
213f9f848faSopenharmony_ciusbd_per_order_probe(usbd_bt_tree tree, char *devname, uint8_t *port_num)
214f9f848faSopenharmony_ci{
215f9f848faSopenharmony_ci	usbd_bt_node *node = usbd_pre_order_hub_node(tree, devname, port_num);
216f9f848faSopenharmony_ci
217f9f848faSopenharmony_ci	if ((node != NULL) && f_find_device) {
218f9f848faSopenharmony_ci		f_find_device = 0;
219f9f848faSopenharmony_ci		return (node);
220f9f848faSopenharmony_ci	}
221f9f848faSopenharmony_ci
222f9f848faSopenharmony_ci	return (NULL);
223f9f848faSopenharmony_ci}
224f9f848faSopenharmony_ci
225f9f848faSopenharmony_ciint
226f9f848faSopenharmony_ciusbd_insert_bt_node(usbd_bt_node *node, usbd_bt_tree tree, struct node_info *parent_info)
227f9f848faSopenharmony_ci{
228f9f848faSopenharmony_ci	usbd_bt_node *parent_node;
229f9f848faSopenharmony_ci
230f9f848faSopenharmony_ci	if ((node == NULL) || (tree == NULL) || (parent_info == NULL))
231f9f848faSopenharmony_ci		return (-1);
232f9f848faSopenharmony_ci
233f9f848faSopenharmony_ci	parent_node = usbd_pre_order_bt_node(tree, parent_info);
234f9f848faSopenharmony_ci	if (parent_node == NULL) {
235f9f848faSopenharmony_ci		PRINT_ERR("Find err, insert fail!\n");
236f9f848faSopenharmony_ci		return (-1);
237f9f848faSopenharmony_ci	}
238f9f848faSopenharmony_ci
239f9f848faSopenharmony_ci	if (parent_node->info.nameunit == node->info.nameunit) {  /* The same hub node. */
240f9f848faSopenharmony_ci		parent_node->rbt_node = node;
241f9f848faSopenharmony_ci	} else {  /* Other driver(hub or other) */
242f9f848faSopenharmony_ci		parent_node->lbt_node = node;
243f9f848faSopenharmony_ci	}
244f9f848faSopenharmony_ci
245f9f848faSopenharmony_ci	BT_DEBUG("[insert node] parent:%p %s %d\n \
246f9f848faSopenharmony_ci		    %s child :%p %s %d\n", \
247f9f848faSopenharmony_ci		    parent_node, parent_node->info.nameunit, parent_node->info.port_no,
248f9f848faSopenharmony_ci		    (parent_node->info.nameunit == node->info.nameunit ? "right" : "left"),
249f9f848faSopenharmony_ci		    node, node->info.nameunit, node->info.port_no);
250f9f848faSopenharmony_ci	return (0);
251f9f848faSopenharmony_ci}
252f9f848faSopenharmony_ci
253f9f848faSopenharmony_ciint
254f9f848faSopenharmony_ciusbd_remove_bt_node(usbd_bt_tree tree, struct node_info *p_info, struct node_info *rm_info)
255f9f848faSopenharmony_ci{
256f9f848faSopenharmony_ci	usbd_bt_node *rm_node;
257f9f848faSopenharmony_ci
258f9f848faSopenharmony_ci	if ((tree == NULL) || (p_info == NULL) || (rm_info == NULL))
259f9f848faSopenharmony_ci		return (-1);
260f9f848faSopenharmony_ci
261f9f848faSopenharmony_ci	rm_node = usbd_pre_order_bt_node(tree, rm_info);
262f9f848faSopenharmony_ci	if (rm_node == NULL) {
263f9f848faSopenharmony_ci		BT_DEBUG("Find err, remove fail!\n");
264f9f848faSopenharmony_ci		return (-1);
265f9f848faSopenharmony_ci	}
266f9f848faSopenharmony_ci
267f9f848faSopenharmony_ci	usbd_release_bt_node(rm_node);
268f9f848faSopenharmony_ci
269f9f848faSopenharmony_ci	/* release parent left node */
270f9f848faSopenharmony_ci	rm_node = usbd_pre_order_bt_node(tree, p_info);
271f9f848faSopenharmony_ci	if (rm_node == NULL) {
272f9f848faSopenharmony_ci		PRINT_ERR("Parent find err, remove fail!\n");
273f9f848faSopenharmony_ci		return (-1);
274f9f848faSopenharmony_ci	}
275f9f848faSopenharmony_ci	rm_node->lbt_node = NULL;
276f9f848faSopenharmony_ci
277f9f848faSopenharmony_ci	return (0);
278f9f848faSopenharmony_ci}
279f9f848faSopenharmony_ci
280