1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "hdf_log.h"
32 #include "device_resource_if.h"
33 #include "hdf_usb.h"
34 
35 #define USB_CONTROLLER_LIST_NAME  "controller_list"
36 #define USB_NODE_MATCH_ATTR       "hisilicon,hi35xx-xhci"
37 #define USB_MAX_CFG_LEN           8
38 #define USB_CONTROL_NAME_LEN      32
39 #define USB_CFG_UNIT              2
40 
41 struct UsbConfig {
42     uint32_t type;
43     uint32_t unit;
44     uint32_t start;
45     uint32_t end;
46     uint32_t count;
47 };
48 
49 struct UsbInfo {
50     struct UsbConfig cfg[USB_MAX_CFG_LEN];
51     uint32_t len;
52 };
53 
GetHdfUsbNode(const struct DeviceResourceIface * instance)54 static const struct DeviceResourceNode *GetHdfUsbNode(const struct DeviceResourceIface *instance)
55 {
56     const struct DeviceResourceNode *root = instance->GetRootNode();
57 
58     if (root == NULL) {
59         HDF_LOGE("%s get root node is null\n", __func__);
60         return NULL;
61     }
62 
63     return instance->GetNodeByMatchAttr(root, USB_NODE_MATCH_ATTR);
64 }
65 
GetUsbControllerParam(const struct DeviceResourceIface * instance,const struct DeviceResourceNode * node,struct UsbConfig * cfg)66 static int GetUsbControllerParam(const struct DeviceResourceIface *instance, const struct DeviceResourceNode *node,
67     struct UsbConfig *cfg)
68 {
69     int ret;
70 
71     ret = instance->GetUint32(node, "res_type", &cfg->type, 0);
72     if (ret != HDF_SUCCESS) {
73         HDF_LOGE("%s: read res_type fail", __func__);
74         return HDF_FAILURE;
75     }
76     ret = instance->GetUint32(node, "res_unit", &cfg->unit, 0);
77     if (ret != HDF_SUCCESS) {
78         HDF_LOGE("%s: read res unit fail", __func__);
79         return HDF_FAILURE;
80     }
81     ret = instance->GetUint32(node, "res_start", &cfg->start, 0);
82     if (ret != HDF_SUCCESS) {
83         HDF_LOGE("%s: read res type fail", __func__);
84         return HDF_FAILURE;
85     }
86     ret = instance->GetUint32(node, "res_end", &cfg->end, 0);
87     if (ret != HDF_SUCCESS) {
88         HDF_LOGE("%s: read res end fail", __func__);
89         return HDF_FAILURE;
90     }
91     ret = instance->GetUint32(node, "res_count", &cfg->count, 0);
92     if (ret != HDF_SUCCESS) {
93         HDF_LOGE("%s: read res count fail", __func__);
94         return HDF_FAILURE;
95     }
96     return HDF_SUCCESS;
97 }
98 
ProcControllorParam(const struct DeviceResourceIface * instance,const struct DeviceResourceNode * node,const char * name,add_res_callback_t callback,struct UsbInfo * info)99 static int ProcControllorParam(const struct DeviceResourceIface *instance, const struct DeviceResourceNode *node,
100     const char *name, add_res_callback_t callback, struct UsbInfo *info)
101 {
102     const char *ctrlName = NULL;
103     uint32_t index = 0;
104 
105     const struct DeviceResourceNode *subNode = node->child;
106     if (subNode == NULL) {
107         return HDF_FAILURE;
108     }
109 
110     DEV_RES_NODE_FOR_EACH_CHILD_NODE(node, subNode) {
111         if (index >= info->len) {
112             break;
113         }
114         struct UsbConfig *cfg = &(info->cfg[index]);
115         int32_t ret = instance->GetString(subNode, "controller", &ctrlName, NULL);
116         if (ret != HDF_SUCCESS) {
117             HDF_LOGE("%s: read res_type fail", __func__);
118             return HDF_FAILURE;
119         }
120 
121         if (strcmp(name, ctrlName) != 0) {
122             HDF_LOGI("%s: no match name", __func__);
123             continue;
124         }
125 
126         ret = GetUsbControllerParam(instance, subNode, cfg);
127         if (ret != HDF_SUCCESS) {
128             HDF_LOGE("%s: read controller param fail", __func__);
129             return HDF_FAILURE;
130         }
131         callback(name, cfg->type, cfg->unit, cfg->start, cfg->end, cfg->count);
132         index++;
133     }
134 
135     return HDF_SUCCESS;
136 }
137 
HdfUsbInitParam(device_t dev,add_res_callback_t callback)138 static void HdfUsbInitParam(device_t dev, add_res_callback_t callback)
139 {
140     const struct DeviceResourceIface *devResInstance = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
141     if (devResInstance == NULL) {
142         HDF_LOGE("%s get devResInstance node is null", __func__);
143         return;
144     }
145     const struct DeviceResourceNode *hdfUsbNode = GetHdfUsbNode(devResInstance);
146     if (hdfUsbNode == NULL) {
147         HDF_LOGE("%s get hdf usb node is null", __func__);
148         return;
149     }
150 
151     int32_t count = devResInstance->GetElemNum(hdfUsbNode, USB_CONTROLLER_LIST_NAME);
152     if ((count <= 0) || (count > USB_MAX_CFG_LEN / USB_CFG_UNIT)) {
153         HDF_LOGE("%s get elemnum failed", __func__);
154         return;
155     }
156 
157     struct UsbInfo info = {0};
158     info.len = USB_MAX_CFG_LEN;
159     const char *ctrlName = NULL;
160     for (int32_t i = 0; i < count; i++) {
161         int32_t ret = devResInstance->GetStringArrayElem(hdfUsbNode, USB_CONTROLLER_LIST_NAME, i, &ctrlName, NULL);
162         if (ret != HDF_SUCCESS) {
163             HDF_LOGE("%s get hdf usb list name fail", __func__);
164             return;
165         }
166 
167         device_add_child(dev, ctrlName, 0);
168         ret = ProcControllorParam(devResInstance, hdfUsbNode, ctrlName, callback, &info);
169         if (ret != HDF_SUCCESS) {
170             HDF_LOGI("%s proc usb controllor not match, goto next", __func__);
171         }
172     }
173 }
174 
UsbResourceInit(device_t dev,add_res_callback_t callback)175 void UsbResourceInit(device_t dev, add_res_callback_t callback)
176 {
177     if (callback == NULL) {
178         HDF_LOGE("usb resource init failed");
179         return;
180     }
181 
182     HdfUsbInitParam(dev, callback);
183 }
184