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