1/*
2 * Copyright (c) 2023 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 "mock_linux_adapter.h"
17
18constexpr uint32_t DESCRIPTORSLENGTH = 111;
19constexpr uint32_t SEM_WAIT_FOREVER = 0xFFFFFFFF;
20constexpr uint8_t ACTIVE_NUM = 1;
21constexpr uint32_t BULK_LEN = 256;
22constexpr uint32_t CAPS = 509;
23constexpr uint8_t BLENGTH = 18;
24constexpr uint16_t BCDUSB = 800;
25constexpr uint8_t MAX_PACKET_SIZE = 9;
26constexpr uint16_t ID_VENDOR = 8711;
27constexpr uint16_t ID_PRODUCT = 24;
28constexpr uint16_t BCD_DEVICE = 547;
29constexpr uint8_t I_PRODUCT = 2;
30constexpr uint8_t I_SERIAL_NUMBER = 3;
31constexpr uint32_t CFG_LEN = 93;
32
33static UsbDeviceHandle *g_usbHandle = nullptr;
34static UsbDevice *g_dev = nullptr;
35static UsbHostRequest *g_sprq = nullptr;
36static OsalSem g_completeSem;
37
38static std::array<uint8_t, DESCRIPTORSLENGTH> g_buf = {
39    0x12, 0x01, 0x20, 0x03, 0x00, 0x00, 0x00, 0x09, 0x07, 0x22, 0x18, 0x00, 0x23, 0x02, 0x01, 0x02,
40    0x03, 0x01, 0x09, 0x02, 0x5D, 0x00, 0x02, 0x01, 0x04, 0xC0, 0x3E, 0x08, 0x0B, 0x00, 0x02, 0x02,
41    0x02, 0x01, 0x07, 0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x05, 0x05, 0x24, 0x00, 0x10,
42    0x01, 0x05, 0x24, 0x01, 0x00, 0x01, 0x04, 0x24, 0x02, 0x02, 0x05, 0x24, 0x06, 0x00, 0x01, 0x07,
43    0x05, 0x81, 0x03, 0x0A, 0x00, 0x09, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x01, 0x00,
44    0x02, 0x0A, 0x00, 0x02, 0x06, 0x07, 0x05, 0x82, 0x02, 0x00, 0x04, 0x00, 0x06, 0x30, 0x00, 0x00,
45    0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x00, 0x04, 0x00, 0x06, 0x30, 0x00, 0x00, 0x00, 0x00
46};
47
48static int32_t FillUsbDeviceHandle(UsbDeviceHandle *handle)
49{
50    UsbDeviceDescriptor dec = {BLENGTH, 1, BCDUSB, 0, 0, 0, MAX_PACKET_SIZE, ID_VENDOR,
51        ID_PRODUCT, BCD_DEVICE, 1, I_PRODUCT, I_SERIAL_NUMBER, 1};
52
53    handle->claimedInterfaces = 0;
54    handle->caps = CAPS;
55    handle->dev->portNum = 0;
56    handle->dev->speed = USB_DDK_SPEED_UNKNOWN;
57    handle->dev->activeConfig = 0;
58    handle->dev->deviceDescriptor = dec;
59    handle->dev->configDescriptors->actualLen = CFG_LEN;
60    return HDF_SUCCESS;
61}
62
63int32_t FuncAdapterInit(const UsbSession *session)
64{
65    (void)session;
66    OsalSemInit(&g_completeSem, 0);
67    return HDF_SUCCESS;
68}
69
70void FuncAdapterExit(const UsbSession *session)
71{
72    (void)session;
73    OsalSemDestroy(&g_completeSem);
74}
75
76static bool OsDeviceCompare(HdfSListNode *listEntry, uint32_t searchKey)
77{
78    UsbDevice *dev = reinterpret_cast<UsbDevice *>(listEntry);
79    if (dev == nullptr) {
80        HDF_LOGE("%{public}s: invalid param listEntry", __func__);
81        return false;
82    }
83
84    if ((dev->busNum == (searchKey >> BUS_OFFSET)) && (dev->devAddr == (searchKey & 0xFF))) {
85        return true;
86    }
87
88    return false;
89}
90
91static UsbDeviceHandle *OsGetDeviceHandle(UsbSession *session, uint8_t busNum, uint8_t usbAddr)
92{
93    if (session == nullptr) {
94        HDF_LOGE("%{public}s: invalid param session", __func__);
95        return nullptr;
96    }
97    UsbDeviceHandle *handle = nullptr;
98    OsalMutexLock(&session->lock);
99    UsbDevice *dev = reinterpret_cast<UsbDevice *>(
100        HdfSListSearch(&session->usbDevs, (busNum << BUS_OFFSET) | usbAddr, OsDeviceCompare));
101    if (dev != nullptr) {
102        handle = dev->devHandle;
103        AdapterAtomicInc(&dev->refcnt);
104    }
105    OsalMutexUnlock(&session->lock);
106
107    return handle;
108}
109
110static UsbDeviceHandle *OsCallocDeviceHandle(void)
111{
112    UsbDeviceHandle *usbHandle = static_cast<UsbDeviceHandle *>(RawUsbMemCalloc(sizeof(UsbDeviceHandle)));
113    if (usbHandle == nullptr) {
114        HDF_LOGE("%{public}s: allocate g_usbHandle failed", __func__);
115        return nullptr;
116    }
117    OsalMutexInit(&usbHandle->lock);
118
119    return usbHandle;
120}
121
122static UsbDevice *OsAllocDevice(UsbSession *session, UsbDeviceHandle *handle)
123{
124    UsbDevice *dev = static_cast<UsbDevice *>(RawUsbMemCalloc(sizeof(UsbDevice)));
125    if (dev == nullptr) {
126        HDF_LOGE("%{public}s: RawUsbMemCalloc failed", __func__);
127        return nullptr;
128    }
129
130    dev->session = session;
131    dev->devHandle = handle;
132    RawRequestListInit(dev);
133    handle->dev = dev;
134
135    return dev;
136}
137static int32_t OsReadDescriptors(UsbDevice *dev)
138{
139    dev->descriptors = static_cast<uint8_t *>(RawUsbMemAlloc(DESCRIPTORSLENGTH));
140    dev->descriptorsLength = DESCRIPTORSLENGTH;
141    if (memcpy_s(dev->descriptors, dev->descriptorsLength, g_buf.data(), DESCRIPTORSLENGTH) != EOK) {
142        HDF_LOGE("%{public}s: memcpy_s failed", __func__);
143        return HDF_FAILURE;
144    }
145    return HDF_SUCCESS;
146}
147
148static int32_t OsParseConfigDescriptors(UsbDevice *dev)
149{
150    UsbDeviceDescriptor *deviceDesc = static_cast<UsbDeviceDescriptor *>(dev->descriptors);
151    uint8_t numConfigs = deviceDesc->bNumConfigurations;
152    if (numConfigs == 0) {
153        return HDF_SUCCESS;
154    }
155    dev->configDescriptors =
156        static_cast<UsbDeviceConfigDescriptor *>(RawUsbMemAlloc(numConfigs * sizeof(UsbDeviceConfigDescriptor)));
157    if (dev->configDescriptors == nullptr) {
158        HDF_LOGE("%{public}s: RawUsbMemAlloc failed.", __func__);
159        return HDF_ERR_MALLOC_FAIL;
160    }
161    uint8_t *buffer = static_cast<uint8_t *>(dev->descriptors) + USB_DDK_DT_DEVICE_SIZE;
162    size_t descLen = dev->descriptorsLength - USB_DDK_DT_DEVICE_SIZE;
163    for (uint8_t i = 0; i < numConfigs; i++) {
164        if (descLen < USB_DDK_DT_CONFIG_SIZE) {
165            HDF_LOGE("%{public}s: read %{public}zu", __func__, descLen);
166            RawUsbMemFree(dev->configDescriptors);
167            return HDF_ERR_IO;
168        }
169        UsbConfigDescriptor *configDesc = reinterpret_cast<UsbConfigDescriptor *>(buffer);
170        if ((configDesc->bDescriptorType != USB_DDK_DT_CONFIG) || (configDesc->bLength < USB_DDK_DT_CONFIG_SIZE)) {
171            HDF_LOGE("%{public}s: config desc error: type 0x%{public}02x, length %{public}u",
172                __func__, configDesc->bDescriptorType, configDesc->bLength);
173            RawUsbMemFree(dev->configDescriptors);
174            return HDF_ERR_IO;
175        }
176        uint16_t configLen = LE16_TO_CPU(configDesc->wTotalLength);
177        if (configLen < USB_DDK_DT_CONFIG_SIZE) {
178            HDF_LOGE("invalid wTotalLength value %{public}u", configLen);
179            RawUsbMemFree(dev->configDescriptors);
180            return HDF_ERR_IO;
181        }
182        if (configLen > descLen) {
183            HDF_LOGI("%{public}s: read %{public}zu/%{public}u", __func__, descLen, configLen);
184            configLen = static_cast<uint16_t>(descLen);
185        }
186        dev->configDescriptors[i].desc = configDesc;
187        dev->configDescriptors[i].actualLen = configLen;
188        buffer += configLen;
189        descLen -= configLen;
190    }
191    return HDF_SUCCESS;
192}
193
194static int32_t OsInitDevice(UsbDevice *dev, uint8_t busNum, uint8_t devAddr)
195{
196    UsbDeviceHandle *devHandle = dev->devHandle;
197    dev->busNum = busNum;
198    dev->devAddr = devAddr;
199    devHandle->caps = CAPS;
200    dev->descriptorsLength = 0;
201
202    int32_t ret = OsReadDescriptors(dev);
203    if (ret != HDF_SUCCESS) {
204        HDF_LOGE("%{public}s: OsReadDescriptors failed ret = %{pubilc}d", __func__, ret);
205        return ret;
206    }
207    ret = OsParseConfigDescriptors(dev);
208    if (ret != HDF_SUCCESS) {
209        HDF_LOGE("%{public}s: OsParseConfigDescriptors failed ret = %{pubilc}d", __func__, ret);
210        return ret;
211    }
212    ret = memcpy_s(&dev->deviceDescriptor, sizeof(UsbDeviceDescriptor), dev->descriptors, USB_DDK_DT_DEVICE_SIZE);
213    if (ret != EOK) {
214        HDF_LOGE("%{public}s: memcpy_s failed ret = %{public}d", __func__, ret);
215        ret = HDF_ERR_IO;
216    }
217    return ret;
218}
219
220UsbDeviceHandle *FuncAdapterOpenDevice(UsbSession *session, uint8_t busNum, uint8_t usbAddr)
221{
222    g_usbHandle = OsGetDeviceHandle(session, busNum, usbAddr);
223    if (g_usbHandle != nullptr) {
224        return g_usbHandle;
225    }
226
227    g_usbHandle = OsCallocDeviceHandle();
228    if (g_usbHandle == nullptr) {
229        return nullptr;
230    }
231
232    g_dev = OsAllocDevice(session, g_usbHandle);
233    if (g_dev == nullptr) {
234        OsalMutexDestroy(&g_usbHandle->lock);
235        RawUsbMemFree(g_usbHandle);
236        return nullptr;
237    }
238
239    int32_t ret = OsInitDevice(g_dev, busNum, usbAddr);
240    if (ret != HDF_SUCCESS) {
241        RawUsbMemFree(g_dev);
242        return nullptr;
243    }
244
245    OsalAtomicSet(&g_dev->refcnt, 1);
246    // add the new device to the device list on session
247    OsalMutexLock(&session->lock);
248    HdfSListAdd(&session->usbDevs, &g_dev->list);
249    OsalMutexUnlock(&session->lock);
250    (void)FillUsbDeviceHandle(g_usbHandle);
251    return g_usbHandle;
252}
253
254void FuncAdapterCloseDevice(UsbDeviceHandle *handle)
255{
256    struct UsbDevice *dev = NULL;
257
258    if ((handle == NULL) || (handle->dev == NULL)) {
259        HDF_LOGE("%{public}s:%{public}d invalid param", __func__, __LINE__);
260        return;
261    }
262
263    dev = handle->dev;
264    if (AdapterAtomicDec(&dev->refcnt) > 0) {
265        return;
266    }
267
268    OsalMutexLock(&dev->session->lock);
269    HdfSListRemove(&dev->session->usbDevs, &dev->list);
270    OsalMutexUnlock(&dev->session->lock);
271
272    if (dev->configDescriptors) {
273        RawUsbMemFree(dev->configDescriptors);
274    }
275    if (dev->descriptors) {
276        RawUsbMemFree(dev->descriptors);
277    }
278    RawUsbMemFree(dev);
279    OsalMutexDestroy(&handle->lock);
280    RawUsbMemFree(handle);
281}
282
283int32_t FuncAdapterGetConfigDescriptor(const UsbDevice *dev, uint8_t configIndex, void *buffer, size_t len)
284{
285    UsbDeviceConfigDescriptor *config = nullptr;
286    uint8_t i;
287    if (dev == nullptr || buffer == nullptr || (configIndex > dev->deviceDescriptor.bNumConfigurations)) {
288        return HDF_ERR_INVALID_PARAM;
289    }
290    configIndex = 1;
291    for (i = 0; i < dev->deviceDescriptor.bNumConfigurations; i++) {
292        if (configIndex == dev->configDescriptors[i].desc->bConfigurationValue) {
293            config = &dev->configDescriptors[i];
294            break;
295        }
296    }
297
298    if (config == nullptr) {
299        HDF_LOGE("%{public}s: config is null", __func__);
300        return HDF_ERR_BAD_FD;
301    }
302    int32_t lenTmp = MIN(static_cast<int32_t>(len), static_cast<int32_t>(config->actualLen));
303    if (memcpy_s(buffer, lenTmp, config->desc, lenTmp) != EOK) {
304        HDF_LOGE("%{public}s: memcpy_s failed", __func__);
305        return HDF_ERR_IO;
306    }
307    return lenTmp;
308}
309
310static int32_t OsGetActiveConfig(UsbDevice *dev, int32_t fd)
311{
312    (void)fd;
313    if (dev == nullptr) {
314        HDF_LOGE("%{public}s: invalid param dev", __func__);
315        return HDF_ERR_INVALID_PARAM;
316    }
317    dev->activeConfig = 0;
318    return HDF_SUCCESS;
319}
320
321int32_t FuncAdapterGetConfiguration(const UsbDeviceHandle *handle, uint8_t *activeConfig)
322{
323    if (handle == nullptr || activeConfig == nullptr || handle->dev == nullptr) {
324        HDF_LOGE("%{public}s: invalid param", __func__);
325        return HDF_ERR_INVALID_PARAM;
326    }
327
328    int32_t ret = OsGetActiveConfig(handle->dev, handle->fd);
329    if (ret != HDF_SUCCESS) {
330        return ret;
331    }
332
333    *activeConfig = handle->dev->activeConfig;
334    if (*activeConfig == 0) {
335        HDF_LOGI("%{public}s: activeConfig is zero", __func__);
336    }
337    return HDF_SUCCESS;
338}
339
340int32_t FuncAdapterSetConfiguration(UsbDeviceHandle *handle, int32_t activeConfig)
341{
342    if (handle == nullptr || handle->dev == nullptr) {
343        HDF_LOGE("%{public}s: invalid param", __func__);
344        return HDF_ERR_INVALID_PARAM;
345    }
346    handle->dev->activeConfig = ACTIVE_NUM;
347    return HDF_SUCCESS;
348}
349
350int32_t FuncAdapterClaimInterface(const UsbDeviceHandle *handle, uint32_t interfaceNumber)
351{
352    (void)handle;
353    (void)interfaceNumber;
354    return HDF_SUCCESS;
355}
356
357int32_t FuncAdapterReleaseInterface(const UsbDeviceHandle *handle, uint32_t interfaceNumber)
358{
359    (void)handle;
360    (void)interfaceNumber;
361    return HDF_SUCCESS;
362}
363
364int32_t FuncAdapterSetInterface(const UsbDeviceHandle *handle, uint8_t interface, uint8_t altSetting)
365{
366    (void)handle;
367    (void)interface;
368    (void)altSetting;
369    return HDF_SUCCESS;
370}
371
372int32_t FuncAdapterClearHalt(const UsbDeviceHandle *handle, uint32_t endPoint)
373{
374    (void)handle;
375    (void)endPoint;
376    return HDF_SUCCESS;
377}
378
379int32_t FuncAdapterResetDevice(const UsbDeviceHandle *handle)
380{
381    (void)handle;
382    return HDF_SUCCESS;
383}
384
385UsbHostRequest *FuncAdapterAllocRequest(const UsbDeviceHandle *handle, int32_t isoPackets, size_t len)
386{
387    void *memBuf = nullptr;
388    UsbHostRequest *request;
389
390    if (handle == nullptr) {
391        HDF_LOGE("%{public}s: invalid param", __func__);
392        return nullptr;
393    }
394    size_t allocSize = sizeof(UsbHostRequest) + (sizeof(UsbIsoPacketDesc) * static_cast<size_t>(isoPackets)) +
395        (sizeof(unsigned char) * len);
396    memBuf = RawUsbMemCalloc(allocSize);
397    if (memBuf == nullptr) {
398        HDF_LOGE("%{public}s: alloc UsbHostRequest failed", __func__);
399        return nullptr;
400    }
401    request = static_cast<UsbHostRequest *>(memBuf);
402    g_sprq = request;
403    request->numIsoPackets = isoPackets;
404    request->buffer = static_cast<unsigned char *>(memBuf) + allocSize - len;
405    request->bufLen = len;
406    request->bulkUrb = RawUsbMemCalloc(sizeof(UsbAdapterUrb));
407    if (request->bulkUrb == nullptr) {
408        HDF_LOGE("%{public}s RawUsbMemAlloc fail", __func__);
409        RawUsbMemFree(memBuf);
410        return nullptr;
411    }
412    request->urbs = request->bulkUrb;
413    return request;
414}
415
416int32_t FuncAdapterFreeRequest(UsbHostRequest *request)
417{
418    if (request == nullptr) {
419        HDF_LOGE("%{public}s: invalid param", __func__);
420        return HDF_ERR_INVALID_PARAM;
421    }
422    if (request->bulkUrb != nullptr) {
423        RawUsbMemFree(request->bulkUrb);
424        request->urbs = nullptr;
425    }
426    if (request != nullptr) {
427        RawUsbMemFree(request);
428        request = nullptr;
429    }
430    return HDF_SUCCESS;
431}
432
433int32_t FuncAdapterSubmitRequest(UsbHostRequest *request)
434{
435    if (g_sprq == nullptr) {
436        HDF_LOGE("%{public}s: g_sprq nullptr", __func__);
437        return HDF_ERR_INVALID_PARAM;
438    }
439    g_sprq->status = request->status;
440    OsalSemPost(&g_completeSem);
441    return HDF_SUCCESS;
442}
443
444int32_t FuncAdapterCancelRequest(UsbHostRequest * const request)
445{
446    if (!((request->requestType == USB_REQUEST_TYPE_BULK) && (request->reqStatus == USB_REQUEST_ERROR))) {
447        request->reqStatus = USB_REQUEST_CANCELLED;
448    }
449    return HDF_SUCCESS;
450}
451
452static int32_t RequestCompletion(UsbHostRequest *request, UsbRequestStatus status)
453{
454    if (request == nullptr) {
455        HDF_LOGE("%{public}s: request is nullptr!", __func__);
456        return HDF_ERR_INVALID_PARAM;
457    }
458    request->status = status;
459    int32_t ret = memset_s(request->buffer, request->bufLen, ACTIVE_NUM, request->bufLen);
460    if (ret != EOK) {
461        HDF_LOGE("%{public}s: memset_s failed", __func__);
462        return ret;
463    }
464    if (request->callback) {
465        request->callback(static_cast<void *>(request));
466    }
467    return HDF_SUCCESS;
468}
469
470int32_t FuncAdapterUrbCompleteHandle(const UsbDeviceHandle *devHandle)
471{
472    uint32_t waitTime;
473    if (devHandle == nullptr) {
474        HDF_LOGE("%{public}s: invalid param", __func__);
475        return HDF_ERR_INVALID_PARAM;
476    }
477    waitTime = SEM_WAIT_FOREVER;
478    (void)OsalSemWait(&g_completeSem, waitTime);
479    if (g_sprq == nullptr) {
480        return HDF_SUCCESS;
481    }
482
483    UsbRequestStatus status = USB_REQUEST_COMPLETED;
484    if (g_sprq->length <= BULK_LEN) {
485        g_sprq->actualLength = ACTIVE_NUM;
486    } else {
487        g_sprq->actualLength = BULK_LEN;
488    }
489    return RequestCompletion(g_sprq, status);
490}
491