1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "usb_protocol.h"
17094332d3Sopenharmony_ci#include "usb_io_manage.h"
18094332d3Sopenharmony_ci#include "usbd_wrapper.h"
19094332d3Sopenharmony_ci
20094332d3Sopenharmony_ci#define HDF_LOG_TAG USB_PROTOCOL
21094332d3Sopenharmony_ci
22094332d3Sopenharmony_ciint32_t UsbProtocalFillControlSetup(const unsigned char *setup, const struct UsbControlRequest *ctrlReq)
23094332d3Sopenharmony_ci{
24094332d3Sopenharmony_ci    struct UsbRawControlSetup *setupData = (struct UsbRawControlSetup *)setup;
25094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
26094332d3Sopenharmony_ci    if ((setup == NULL) || (ctrlReq == NULL)) {
27094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d invalid parameter", __func__, __LINE__);
28094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
29094332d3Sopenharmony_ci    }
30094332d3Sopenharmony_ci
31094332d3Sopenharmony_ci    setupData->requestType = ctrlReq->reqType;
32094332d3Sopenharmony_ci    setupData->request     = ctrlReq->request;
33094332d3Sopenharmony_ci    setupData->value       = CPU_TO_LE16(ctrlReq->value);
34094332d3Sopenharmony_ci    setupData->index       = CPU_TO_LE16(ctrlReq->index);
35094332d3Sopenharmony_ci    setupData->length      = CPU_TO_LE16(ctrlReq->length);
36094332d3Sopenharmony_ci
37094332d3Sopenharmony_ci    return ret;
38094332d3Sopenharmony_ci}
39094332d3Sopenharmony_ci
40094332d3Sopenharmony_cistatic int32_t CreateCtrPipe(const struct UsbInterfacePool *pool)
41094332d3Sopenharmony_ci{
42094332d3Sopenharmony_ci    int32_t ret = 0;
43094332d3Sopenharmony_ci    struct UsbSdkInterface *interfaceObj = NULL;
44094332d3Sopenharmony_ci    struct UsbPipe *pipe = NULL;
45094332d3Sopenharmony_ci
46094332d3Sopenharmony_ci    if (pool == NULL) {
47094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d invalid param pool", __func__, __LINE__);
48094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
49094332d3Sopenharmony_ci    }
50094332d3Sopenharmony_ci
51094332d3Sopenharmony_ci    ret = UsbIfCreatInterfaceObj(pool, &interfaceObj);
52094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
53094332d3Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
54094332d3Sopenharmony_ci    }
55094332d3Sopenharmony_ci    interfaceObj->interface.info.interfaceIndex = USB_CTRL_INTERFACE_ID;
56094332d3Sopenharmony_ci    interfaceObj->interface.info.pipeNum = 1;
57094332d3Sopenharmony_ci    interfaceObj->altSettingId = 0;
58094332d3Sopenharmony_ci    interfaceObj->interface.info.curAltSetting = 0;
59094332d3Sopenharmony_ci    ret = UsbIfCreatPipeObj(interfaceObj, &pipe);
60094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
61094332d3Sopenharmony_ci        return HDF_ERR_IO;
62094332d3Sopenharmony_ci    }
63094332d3Sopenharmony_ci
64094332d3Sopenharmony_ci    pipe->info.pipeId = 0;
65094332d3Sopenharmony_ci    pipe->info.pipeAddress = 0;
66094332d3Sopenharmony_ci    pipe->info.pipeDirection = USB_PIPE_DIRECTION_OUT;
67094332d3Sopenharmony_ci    pipe->info.pipeType = USB_PIPE_TYPE_CONTROL;
68094332d3Sopenharmony_ci
69094332d3Sopenharmony_ci    return ret;
70094332d3Sopenharmony_ci}
71094332d3Sopenharmony_ci
72094332d3Sopenharmony_cistatic int32_t UsbInterfaceInit(struct UsbSdkInterface *interfaceObj,
73094332d3Sopenharmony_ci    const struct UsbRawInterfaceDescriptor *iface, const struct UsbRawInterface *altsettings)
74094332d3Sopenharmony_ci{
75094332d3Sopenharmony_ci    struct UsbInterfaceInfo *ptr = NULL;
76094332d3Sopenharmony_ci
77094332d3Sopenharmony_ci    if ((interfaceObj == NULL) || (iface == NULL)) {
78094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid parameter", __func__);
79094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
80094332d3Sopenharmony_ci    }
81094332d3Sopenharmony_ci    ptr = &interfaceObj->interface.info;
82094332d3Sopenharmony_ci    ptr->pipeNum = iface->interfaceDescriptor.bNumEndpoints;
83094332d3Sopenharmony_ci    ptr->interfaceClass = iface->interfaceDescriptor.bInterfaceClass;
84094332d3Sopenharmony_ci    ptr->interfaceSubClass = iface->interfaceDescriptor.bInterfaceSubClass;
85094332d3Sopenharmony_ci    ptr->interfaceProtocol = iface->interfaceDescriptor.bInterfaceProtocol;
86094332d3Sopenharmony_ci    ptr->interfaceIndex = iface->interfaceDescriptor.bInterfaceNumber;
87094332d3Sopenharmony_ci    ptr->altSettings = altsettings->numAltsetting;
88094332d3Sopenharmony_ci    ptr->curAltSetting = USB_DEFAULT_ALTSETTING;
89094332d3Sopenharmony_ci
90094332d3Sopenharmony_ci    interfaceObj->altSettingId = iface->interfaceDescriptor.bAlternateSetting;
91094332d3Sopenharmony_ci
92094332d3Sopenharmony_ci    return HDF_SUCCESS;
93094332d3Sopenharmony_ci}
94094332d3Sopenharmony_ci
95094332d3Sopenharmony_cistatic int32_t UsbPipeInit(struct UsbPipe *pipe, const struct UsbRawEndpointDescriptor *ep)
96094332d3Sopenharmony_ci{
97094332d3Sopenharmony_ci    if ((pipe == NULL) || (ep == NULL)) {
98094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid parameter", __func__);
99094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
100094332d3Sopenharmony_ci    }
101094332d3Sopenharmony_ci
102094332d3Sopenharmony_ci    pipe->info.pipeId = ep->endpointDescriptor.bEndpointAddress;
103094332d3Sopenharmony_ci    pipe->info.maxPacketSize = ep->endpointDescriptor.wMaxPacketSize;
104094332d3Sopenharmony_ci    pipe->info.interval = ep->endpointDescriptor.bInterval;
105094332d3Sopenharmony_ci    pipe->info.pipeType =  ep->endpointDescriptor.bmAttributes & USB_DDK_ENDPOINT_XFERTYPE_MASK;
106094332d3Sopenharmony_ci    pipe->info.pipeAddress = ep->endpointDescriptor.bEndpointAddress & USB_DDK_ENDPOINT_NUMBER_MASK;
107094332d3Sopenharmony_ci    pipe->info.pipeDirection = ep->endpointDescriptor.bEndpointAddress & USB_DDK_ENDPOINT_DIR_MASK;
108094332d3Sopenharmony_ci    return HDF_SUCCESS;
109094332d3Sopenharmony_ci}
110094332d3Sopenharmony_ci
111094332d3Sopenharmony_cistatic const struct UsbRawInterface *UsbGetInterfaceFromConfig(
112094332d3Sopenharmony_ci    const struct UsbRawConfigDescriptor *config, uint8_t idx)
113094332d3Sopenharmony_ci{
114094332d3Sopenharmony_ci    if (config == NULL) {
115094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param", __func__);
116094332d3Sopenharmony_ci        return NULL;
117094332d3Sopenharmony_ci    }
118094332d3Sopenharmony_ci    if (config->configDescriptor.bNumInterfaces < idx + 1) {
119094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: invalid param", __func__);
120094332d3Sopenharmony_ci        return NULL;
121094332d3Sopenharmony_ci    }
122094332d3Sopenharmony_ci
123094332d3Sopenharmony_ci    return config->interface[idx];
124094332d3Sopenharmony_ci}
125094332d3Sopenharmony_ci
126094332d3Sopenharmony_ci/* The default AltSetting is 0 */
127094332d3Sopenharmony_cistatic const struct UsbRawInterfaceDescriptor *UsbGetInterfaceDesc(
128094332d3Sopenharmony_ci    const struct UsbRawInterface *altSetting, uint8_t settingIndex)
129094332d3Sopenharmony_ci{
130094332d3Sopenharmony_ci    if (altSetting == NULL) {
131094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d invalid param altSetting", __func__, __LINE__);
132094332d3Sopenharmony_ci        return NULL;
133094332d3Sopenharmony_ci    }
134094332d3Sopenharmony_ci
135094332d3Sopenharmony_ci    return &altSetting->altsetting[settingIndex];
136094332d3Sopenharmony_ci}
137094332d3Sopenharmony_ci
138094332d3Sopenharmony_cistatic const struct UsbRawEndpointDescriptor *UsbGetEpDesc(
139094332d3Sopenharmony_ci    const struct UsbRawInterfaceDescriptor *ifDes, uint8_t idx)
140094332d3Sopenharmony_ci{
141094332d3Sopenharmony_ci    if (ifDes == NULL) {
142094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d invalid param ifDes", __func__, __LINE__);
143094332d3Sopenharmony_ci        return NULL;
144094332d3Sopenharmony_ci    }
145094332d3Sopenharmony_ci    if (ifDes->interfaceDescriptor.bNumEndpoints < (idx + 1)) {
146094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:invalid param numEp:%{public}d+idx:%{public}hhu",
147094332d3Sopenharmony_ci            __func__, ifDes->interfaceDescriptor.bNumEndpoints, idx);
148094332d3Sopenharmony_ci        return NULL;
149094332d3Sopenharmony_ci    }
150094332d3Sopenharmony_ci
151094332d3Sopenharmony_ci    return &ifDes->endPoint[idx];
152094332d3Sopenharmony_ci}
153094332d3Sopenharmony_ci
154094332d3Sopenharmony_cistatic int32_t UsbProtocalCreatePipeObj(
155094332d3Sopenharmony_ci    const struct UsbRawInterfaceDescriptor *ifDes, const struct UsbSdkInterface *interfaceObj)
156094332d3Sopenharmony_ci{
157094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
158094332d3Sopenharmony_ci    const struct UsbRawEndpointDescriptor *ep = NULL;
159094332d3Sopenharmony_ci    struct UsbPipe *pipe = NULL;
160094332d3Sopenharmony_ci
161094332d3Sopenharmony_ci    for (int32_t cnep = 0; cnep < ifDes->interfaceDescriptor.bNumEndpoints; cnep++) {
162094332d3Sopenharmony_ci        if (ifDes->interfaceDescriptor.bNumEndpoints > USB_MAXENDPOINTS) {
163094332d3Sopenharmony_ci            HDF_LOGE("%{public}s:%{public}d bNumEndpoints=%{public}d is error",
164094332d3Sopenharmony_ci                __func__, __LINE__, ifDes->interfaceDescriptor.bNumEndpoints);
165094332d3Sopenharmony_ci            ret = HDF_DEV_ERR_NORANGE;
166094332d3Sopenharmony_ci            break;
167094332d3Sopenharmony_ci        }
168094332d3Sopenharmony_ci        ep = UsbGetEpDesc(ifDes, cnep);
169094332d3Sopenharmony_ci        if (ep == NULL) {
170094332d3Sopenharmony_ci            ret = HDF_ERR_INVALID_PARAM;
171094332d3Sopenharmony_ci            break;
172094332d3Sopenharmony_ci        }
173094332d3Sopenharmony_ci        ret = UsbIfCreatPipeObj(interfaceObj, &pipe);
174094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
175094332d3Sopenharmony_ci            break;
176094332d3Sopenharmony_ci        }
177094332d3Sopenharmony_ci        ret = UsbPipeInit(pipe, ep);
178094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
179094332d3Sopenharmony_ci            break;
180094332d3Sopenharmony_ci        }
181094332d3Sopenharmony_ci    }
182094332d3Sopenharmony_ci
183094332d3Sopenharmony_ci    return ret;
184094332d3Sopenharmony_ci}
185094332d3Sopenharmony_ci
186094332d3Sopenharmony_cistatic int32_t UsbProtocalCreatInterfaceObj(const struct UsbRawConfigDescriptor *config,
187094332d3Sopenharmony_ci    const struct UsbInterfacePool *interfacePool)
188094332d3Sopenharmony_ci{
189094332d3Sopenharmony_ci    uint8_t j;
190094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
191094332d3Sopenharmony_ci    const struct UsbRawInterface *itface = NULL;
192094332d3Sopenharmony_ci    const struct UsbRawInterfaceDescriptor *ifDes = NULL;
193094332d3Sopenharmony_ci    struct UsbSdkInterface *interfaceObj = NULL;
194094332d3Sopenharmony_ci
195094332d3Sopenharmony_ci    for (int32_t i = 0; i < config->configDescriptor.bNumInterfaces; i++) {
196094332d3Sopenharmony_ci        itface = UsbGetInterfaceFromConfig(config, i);
197094332d3Sopenharmony_ci        if (itface == NULL) {
198094332d3Sopenharmony_ci            ret = HDF_ERR_INVALID_PARAM;
199094332d3Sopenharmony_ci            goto ERROR;
200094332d3Sopenharmony_ci        }
201094332d3Sopenharmony_ci
202094332d3Sopenharmony_ci        for (j = 0; j < itface->numAltsetting; j++) {
203094332d3Sopenharmony_ci            ifDes = UsbGetInterfaceDesc(itface, j);
204094332d3Sopenharmony_ci            if (ifDes == NULL) {
205094332d3Sopenharmony_ci                ret = HDF_ERR_INVALID_PARAM;
206094332d3Sopenharmony_ci                goto ERROR;
207094332d3Sopenharmony_ci            }
208094332d3Sopenharmony_ci
209094332d3Sopenharmony_ci            ret = UsbIfCreatInterfaceObj(interfacePool, &interfaceObj);
210094332d3Sopenharmony_ci            if (ret != HDF_SUCCESS) {
211094332d3Sopenharmony_ci                goto ERROR;
212094332d3Sopenharmony_ci            }
213094332d3Sopenharmony_ci
214094332d3Sopenharmony_ci            ret = UsbInterfaceInit(interfaceObj, ifDes, itface);
215094332d3Sopenharmony_ci            if (ret != 0) {
216094332d3Sopenharmony_ci                ret = HDF_ERR_IO;
217094332d3Sopenharmony_ci                goto ERROR;
218094332d3Sopenharmony_ci            }
219094332d3Sopenharmony_ci
220094332d3Sopenharmony_ci            ret = UsbProtocalCreatePipeObj(ifDes, interfaceObj);
221094332d3Sopenharmony_ci            if (ret != HDF_SUCCESS) {
222094332d3Sopenharmony_ci                goto ERROR;
223094332d3Sopenharmony_ci            }
224094332d3Sopenharmony_ci        }
225094332d3Sopenharmony_ci    }
226094332d3Sopenharmony_ci
227094332d3Sopenharmony_ciERROR:
228094332d3Sopenharmony_ci    return ret;
229094332d3Sopenharmony_ci}
230094332d3Sopenharmony_ci
231094332d3Sopenharmony_ciint32_t UsbProtocalParseDescriptor(struct UsbDeviceHandle *devHandle, uint8_t busNum, uint8_t devAddr)
232094332d3Sopenharmony_ci{
233094332d3Sopenharmony_ci    int32_t ret;
234094332d3Sopenharmony_ci    int32_t activeConfig = -1;
235094332d3Sopenharmony_ci    struct UsbInterfacePool *interfacePool = NULL;
236094332d3Sopenharmony_ci    struct UsbRawConfigDescriptor *config = NULL;
237094332d3Sopenharmony_ci
238094332d3Sopenharmony_ci    if ((devHandle == NULL) || (devHandle->dev == NULL) || (devHandle->dev->session == NULL)) {
239094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d invalid param", __func__, __LINE__);
240094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
241094332d3Sopenharmony_ci    }
242094332d3Sopenharmony_ci
243094332d3Sopenharmony_ci    ret = UsbIfCreatInterfacePool(devHandle->dev->session, busNum, devAddr, &interfacePool);
244094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
245094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d UsbIfCreatInterfacePool error", __func__, __LINE__);
246094332d3Sopenharmony_ci        return HDF_ERR_IO;
247094332d3Sopenharmony_ci    }
248094332d3Sopenharmony_ci    interfacePool->session = devHandle->dev->session;
249094332d3Sopenharmony_ci    interfacePool->device = devHandle->dev;
250094332d3Sopenharmony_ci    devHandle->dev->privateObject = (void *)interfacePool;
251094332d3Sopenharmony_ci
252094332d3Sopenharmony_ci    ret = CreateCtrPipe(interfacePool);
253094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
254094332d3Sopenharmony_ci        goto ERR;
255094332d3Sopenharmony_ci    }
256094332d3Sopenharmony_ci
257094332d3Sopenharmony_ci    ret = RawGetConfiguration(devHandle, &activeConfig);
258094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
259094332d3Sopenharmony_ci        goto ERR;
260094332d3Sopenharmony_ci    }
261094332d3Sopenharmony_ci
262094332d3Sopenharmony_ci    ret = RawGetConfigDescriptor(devHandle->dev, activeConfig, &config);
263094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
264094332d3Sopenharmony_ci        goto FREE_CONFIG;
265094332d3Sopenharmony_ci    }
266094332d3Sopenharmony_ci
267094332d3Sopenharmony_ci    ret = UsbProtocalCreatInterfaceObj(config, interfacePool);
268094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
269094332d3Sopenharmony_ci        goto FREE_CONFIG;
270094332d3Sopenharmony_ci    }
271094332d3Sopenharmony_ci
272094332d3Sopenharmony_ciFREE_CONFIG:
273094332d3Sopenharmony_ci    if (config != NULL) {
274094332d3Sopenharmony_ci        RawClearConfiguration(config);
275094332d3Sopenharmony_ci        RawUsbMemFree(config);
276094332d3Sopenharmony_ci        config = NULL;
277094332d3Sopenharmony_ci    }
278094332d3Sopenharmony_ci
279094332d3Sopenharmony_ci    if (ret == HDF_SUCCESS) {
280094332d3Sopenharmony_ci        return ret;
281094332d3Sopenharmony_ci    }
282094332d3Sopenharmony_ci
283094332d3Sopenharmony_ciERR:
284094332d3Sopenharmony_ci    (void)UsbIfDestroyInterfaceObj(interfacePool, NULL);
285094332d3Sopenharmony_ci    return ret;
286094332d3Sopenharmony_ci}
287094332d3Sopenharmony_ci
288