1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "usb_protocol.h"
17#include "usb_io_manage.h"
18#include "usbd_wrapper.h"
19
20#define HDF_LOG_TAG USB_PROTOCOL
21
22int32_t UsbProtocalFillControlSetup(const unsigned char *setup, const struct UsbControlRequest *ctrlReq)
23{
24    struct UsbRawControlSetup *setupData = (struct UsbRawControlSetup *)setup;
25    int32_t ret = HDF_SUCCESS;
26    if ((setup == NULL) || (ctrlReq == NULL)) {
27        HDF_LOGE("%{public}s:%{public}d invalid parameter", __func__, __LINE__);
28        return HDF_ERR_INVALID_PARAM;
29    }
30
31    setupData->requestType = ctrlReq->reqType;
32    setupData->request     = ctrlReq->request;
33    setupData->value       = CPU_TO_LE16(ctrlReq->value);
34    setupData->index       = CPU_TO_LE16(ctrlReq->index);
35    setupData->length      = CPU_TO_LE16(ctrlReq->length);
36
37    return ret;
38}
39
40static int32_t CreateCtrPipe(const struct UsbInterfacePool *pool)
41{
42    int32_t ret = 0;
43    struct UsbSdkInterface *interfaceObj = NULL;
44    struct UsbPipe *pipe = NULL;
45
46    if (pool == NULL) {
47        HDF_LOGE("%{public}s:%{public}d invalid param pool", __func__, __LINE__);
48        return HDF_ERR_INVALID_PARAM;
49    }
50
51    ret = UsbIfCreatInterfaceObj(pool, &interfaceObj);
52    if (ret != HDF_SUCCESS) {
53        return HDF_ERR_MALLOC_FAIL;
54    }
55    interfaceObj->interface.info.interfaceIndex = USB_CTRL_INTERFACE_ID;
56    interfaceObj->interface.info.pipeNum = 1;
57    interfaceObj->altSettingId = 0;
58    interfaceObj->interface.info.curAltSetting = 0;
59    ret = UsbIfCreatPipeObj(interfaceObj, &pipe);
60    if (ret != HDF_SUCCESS) {
61        return HDF_ERR_IO;
62    }
63
64    pipe->info.pipeId = 0;
65    pipe->info.pipeAddress = 0;
66    pipe->info.pipeDirection = USB_PIPE_DIRECTION_OUT;
67    pipe->info.pipeType = USB_PIPE_TYPE_CONTROL;
68
69    return ret;
70}
71
72static int32_t UsbInterfaceInit(struct UsbSdkInterface *interfaceObj,
73    const struct UsbRawInterfaceDescriptor *iface, const struct UsbRawInterface *altsettings)
74{
75    struct UsbInterfaceInfo *ptr = NULL;
76
77    if ((interfaceObj == NULL) || (iface == NULL)) {
78        HDF_LOGE("%{public}s: invalid parameter", __func__);
79        return HDF_ERR_INVALID_PARAM;
80    }
81    ptr = &interfaceObj->interface.info;
82    ptr->pipeNum = iface->interfaceDescriptor.bNumEndpoints;
83    ptr->interfaceClass = iface->interfaceDescriptor.bInterfaceClass;
84    ptr->interfaceSubClass = iface->interfaceDescriptor.bInterfaceSubClass;
85    ptr->interfaceProtocol = iface->interfaceDescriptor.bInterfaceProtocol;
86    ptr->interfaceIndex = iface->interfaceDescriptor.bInterfaceNumber;
87    ptr->altSettings = altsettings->numAltsetting;
88    ptr->curAltSetting = USB_DEFAULT_ALTSETTING;
89
90    interfaceObj->altSettingId = iface->interfaceDescriptor.bAlternateSetting;
91
92    return HDF_SUCCESS;
93}
94
95static int32_t UsbPipeInit(struct UsbPipe *pipe, const struct UsbRawEndpointDescriptor *ep)
96{
97    if ((pipe == NULL) || (ep == NULL)) {
98        HDF_LOGE("%{public}s: invalid parameter", __func__);
99        return HDF_ERR_INVALID_PARAM;
100    }
101
102    pipe->info.pipeId = ep->endpointDescriptor.bEndpointAddress;
103    pipe->info.maxPacketSize = ep->endpointDescriptor.wMaxPacketSize;
104    pipe->info.interval = ep->endpointDescriptor.bInterval;
105    pipe->info.pipeType =  ep->endpointDescriptor.bmAttributes & USB_DDK_ENDPOINT_XFERTYPE_MASK;
106    pipe->info.pipeAddress = ep->endpointDescriptor.bEndpointAddress & USB_DDK_ENDPOINT_NUMBER_MASK;
107    pipe->info.pipeDirection = ep->endpointDescriptor.bEndpointAddress & USB_DDK_ENDPOINT_DIR_MASK;
108    return HDF_SUCCESS;
109}
110
111static const struct UsbRawInterface *UsbGetInterfaceFromConfig(
112    const struct UsbRawConfigDescriptor *config, uint8_t idx)
113{
114    if (config == NULL) {
115        HDF_LOGE("%{public}s: invalid param", __func__);
116        return NULL;
117    }
118    if (config->configDescriptor.bNumInterfaces < idx + 1) {
119        HDF_LOGE("%{public}s: invalid param", __func__);
120        return NULL;
121    }
122
123    return config->interface[idx];
124}
125
126/* The default AltSetting is 0 */
127static const struct UsbRawInterfaceDescriptor *UsbGetInterfaceDesc(
128    const struct UsbRawInterface *altSetting, uint8_t settingIndex)
129{
130    if (altSetting == NULL) {
131        HDF_LOGE("%{public}s:%{public}d invalid param altSetting", __func__, __LINE__);
132        return NULL;
133    }
134
135    return &altSetting->altsetting[settingIndex];
136}
137
138static const struct UsbRawEndpointDescriptor *UsbGetEpDesc(
139    const struct UsbRawInterfaceDescriptor *ifDes, uint8_t idx)
140{
141    if (ifDes == NULL) {
142        HDF_LOGE("%{public}s:%{public}d invalid param ifDes", __func__, __LINE__);
143        return NULL;
144    }
145    if (ifDes->interfaceDescriptor.bNumEndpoints < (idx + 1)) {
146        HDF_LOGE("%{public}s:invalid param numEp:%{public}d+idx:%{public}hhu",
147            __func__, ifDes->interfaceDescriptor.bNumEndpoints, idx);
148        return NULL;
149    }
150
151    return &ifDes->endPoint[idx];
152}
153
154static int32_t UsbProtocalCreatePipeObj(
155    const struct UsbRawInterfaceDescriptor *ifDes, const struct UsbSdkInterface *interfaceObj)
156{
157    int32_t ret = HDF_SUCCESS;
158    const struct UsbRawEndpointDescriptor *ep = NULL;
159    struct UsbPipe *pipe = NULL;
160
161    for (int32_t cnep = 0; cnep < ifDes->interfaceDescriptor.bNumEndpoints; cnep++) {
162        if (ifDes->interfaceDescriptor.bNumEndpoints > USB_MAXENDPOINTS) {
163            HDF_LOGE("%{public}s:%{public}d bNumEndpoints=%{public}d is error",
164                __func__, __LINE__, ifDes->interfaceDescriptor.bNumEndpoints);
165            ret = HDF_DEV_ERR_NORANGE;
166            break;
167        }
168        ep = UsbGetEpDesc(ifDes, cnep);
169        if (ep == NULL) {
170            ret = HDF_ERR_INVALID_PARAM;
171            break;
172        }
173        ret = UsbIfCreatPipeObj(interfaceObj, &pipe);
174        if (ret != HDF_SUCCESS) {
175            break;
176        }
177        ret = UsbPipeInit(pipe, ep);
178        if (ret != HDF_SUCCESS) {
179            break;
180        }
181    }
182
183    return ret;
184}
185
186static int32_t UsbProtocalCreatInterfaceObj(const struct UsbRawConfigDescriptor *config,
187    const struct UsbInterfacePool *interfacePool)
188{
189    uint8_t j;
190    int32_t ret = HDF_SUCCESS;
191    const struct UsbRawInterface *itface = NULL;
192    const struct UsbRawInterfaceDescriptor *ifDes = NULL;
193    struct UsbSdkInterface *interfaceObj = NULL;
194
195    for (int32_t i = 0; i < config->configDescriptor.bNumInterfaces; i++) {
196        itface = UsbGetInterfaceFromConfig(config, i);
197        if (itface == NULL) {
198            ret = HDF_ERR_INVALID_PARAM;
199            goto ERROR;
200        }
201
202        for (j = 0; j < itface->numAltsetting; j++) {
203            ifDes = UsbGetInterfaceDesc(itface, j);
204            if (ifDes == NULL) {
205                ret = HDF_ERR_INVALID_PARAM;
206                goto ERROR;
207            }
208
209            ret = UsbIfCreatInterfaceObj(interfacePool, &interfaceObj);
210            if (ret != HDF_SUCCESS) {
211                goto ERROR;
212            }
213
214            ret = UsbInterfaceInit(interfaceObj, ifDes, itface);
215            if (ret != 0) {
216                ret = HDF_ERR_IO;
217                goto ERROR;
218            }
219
220            ret = UsbProtocalCreatePipeObj(ifDes, interfaceObj);
221            if (ret != HDF_SUCCESS) {
222                goto ERROR;
223            }
224        }
225    }
226
227ERROR:
228    return ret;
229}
230
231int32_t UsbProtocalParseDescriptor(struct UsbDeviceHandle *devHandle, uint8_t busNum, uint8_t devAddr)
232{
233    int32_t ret;
234    int32_t activeConfig = -1;
235    struct UsbInterfacePool *interfacePool = NULL;
236    struct UsbRawConfigDescriptor *config = NULL;
237
238    if ((devHandle == NULL) || (devHandle->dev == NULL) || (devHandle->dev->session == NULL)) {
239        HDF_LOGE("%{public}s:%{public}d invalid param", __func__, __LINE__);
240        return HDF_ERR_INVALID_PARAM;
241    }
242
243    ret = UsbIfCreatInterfacePool(devHandle->dev->session, busNum, devAddr, &interfacePool);
244    if (ret != HDF_SUCCESS) {
245        HDF_LOGE("%{public}s:%{public}d UsbIfCreatInterfacePool error", __func__, __LINE__);
246        return HDF_ERR_IO;
247    }
248    interfacePool->session = devHandle->dev->session;
249    interfacePool->device = devHandle->dev;
250    devHandle->dev->privateObject = (void *)interfacePool;
251
252    ret = CreateCtrPipe(interfacePool);
253    if (ret != HDF_SUCCESS) {
254        goto ERR;
255    }
256
257    ret = RawGetConfiguration(devHandle, &activeConfig);
258    if (ret != HDF_SUCCESS) {
259        goto ERR;
260    }
261
262    ret = RawGetConfigDescriptor(devHandle->dev, activeConfig, &config);
263    if (ret != HDF_SUCCESS) {
264        goto FREE_CONFIG;
265    }
266
267    ret = UsbProtocalCreatInterfaceObj(config, interfacePool);
268    if (ret != HDF_SUCCESS) {
269        goto FREE_CONFIG;
270    }
271
272FREE_CONFIG:
273    if (config != NULL) {
274        RawClearConfiguration(config);
275        RawUsbMemFree(config);
276        config = NULL;
277    }
278
279    if (ret == HDF_SUCCESS) {
280        return ret;
281    }
282
283ERR:
284    (void)UsbIfDestroyInterfaceObj(interfacePool, NULL);
285    return ret;
286}
287
288