1/*
2 * Copyright (c) 2021-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 "device_resource_if.h"
17#include "hdf_base.h"
18#include "hdf_device_desc.h"
19#include "hdf_device_object.h"
20#include "hdf_log.h"
21#include "osal_mem.h"
22#include "osal_time.h"
23#include "securec.h"
24#include "usbfn_device.h"
25#include "usbfn_interface.h"
26#include "usbfn_request.h"
27
28#define HDF_LOG_TAG dev_usbfn
29#define UDC_NAME "invalid_udc_name"
30
31enum DevUsbFnCmd {
32    DEV_USBFN_INIT = 0x1,
33    DEV_USBFN_RELEASE,
34};
35
36struct DevUsbFnMgr {
37    struct IDeviceIoService service;
38    struct UsbFnDescriptorData descData;
39    struct HdfDeviceObject *device;
40    const char *udcName;
41};
42
43struct UsbFnDevice *g_fnDev = NULL;
44static int32_t UsbFnReleaseFuncDevice(void)
45{
46    int32_t ret;
47    if (g_fnDev == NULL) {
48        HDF_LOGE("%{public}s: fnDev is null", __func__);
49        return HDF_FAILURE;
50    }
51    ret = UsbFnRemoveDevice(g_fnDev);
52    if (ret == HDF_SUCCESS) {
53        g_fnDev = NULL;
54    } else {
55        HDF_LOGE("%{public}s: remove usb function device failed", __func__);
56    }
57
58    return ret;
59}
60
61static int32_t UsbFnRegistUsbfnDevice(struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
62{
63    struct HdfDeviceObject *device = client->device;
64    struct DevUsbFnMgr *devMgr = NULL;
65    struct UsbFnDevice *fnDev = NULL;
66    uint8_t value;
67    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
68
69    if (iface == NULL || iface->GetUint32 == NULL || device == NULL) {
70        HDF_LOGE("%{public}s: iface is invalid", __func__);
71        return HDF_FAILURE;
72    }
73    devMgr = (struct DevUsbFnMgr *)device->service;
74    if (HdfSbufReadUint8(data, &value) != true) {
75        HDF_LOGE("%{public}s: read sbuf failed", __func__);
76        return HDF_FAILURE;
77    }
78    HDF_LOGI("%{public}s: data=%{public}d, descriptor in %{public}s", __func__, value,
79        (devMgr->descData.type == USBFN_DESC_DATA_TYPE_DESC ? "code" : "hcs"));
80    devMgr->descData.functionMask = value;
81    fnDev = (struct UsbFnDevice *)UsbFnCreateDevice(devMgr->udcName, &devMgr->descData);
82    if (fnDev == NULL) {
83        HDF_LOGE("%{public}s: create usb function device failed", __func__);
84        if (!HdfSbufWriteInt8(reply, 0)) {
85            HDF_LOGE("%{public}s: fn_usbfn sbuf write error", __func__);
86        }
87        return HDF_FAILURE;
88    }
89    g_fnDev = fnDev;
90    if (!HdfSbufWriteInt8(reply, value)) {
91        HDF_LOGE("%{public}s: fn_usbfn sbuf write error", __func__);
92        return HDF_FAILURE;
93    }
94    HDF_LOGI("%{public}s: create device done, reply: %{public}d", __func__, value);
95    return HDF_SUCCESS;
96}
97
98static int32_t UsbFnDispatch(
99    struct HdfDeviceIoClient *client, int32_t cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
100{
101    int32_t ret;
102    if (client == NULL) {
103        HDF_LOGE("%{public}s: client is NULL", __func__);
104        return HDF_FAILURE;
105    }
106
107    if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) {
108        HDF_LOGE("%{public}s: check interface desc fail", __func__);
109        return HDF_ERR_INVALID_PARAM;
110    }
111
112    switch (cmdId) {
113        case DEV_USBFN_INIT:
114            ret = UsbFnRegistUsbfnDevice(client, data, reply);
115            if (ret != HDF_SUCCESS) {
116                HDF_LOGE("%{public}s: create usbfn device failed", __func__);
117            }
118            break;
119        case DEV_USBFN_RELEASE:
120            ret = UsbFnReleaseFuncDevice();
121            break;
122        default:
123            ret = HDF_ERR_INVALID_OBJECT;
124            HDF_LOGE("%{public}s: unknown cmd id %{public}d", __func__, cmdId);
125            break;
126    }
127    return ret;
128}
129
130/* HdfDriverEntry implementations */
131static int32_t UsbFnDriverBind(struct HdfDeviceObject *device)
132{
133    struct DevUsbFnMgr *devMgr = NULL;
134    if (device == NULL) {
135        HDF_LOGE("%{public}s: device is null", __func__);
136        return HDF_FAILURE;
137    }
138    devMgr = (struct DevUsbFnMgr *)OsalMemCalloc(sizeof(*devMgr));
139    if (devMgr == NULL) {
140        HDF_LOGE("%{public}s: usbfn Alloc usb devMgr failed", __func__);
141        return HDF_FAILURE;
142    }
143
144    if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) {
145        HDF_LOGE("%{public}s: Set Desc fail!", __func__);
146        OsalMemFree(devMgr);
147        return HDF_FAILURE;
148    }
149
150    devMgr->device = device;
151    device->service = &(devMgr->service);
152    devMgr->device->service->Dispatch = UsbFnDispatch;
153    return HDF_SUCCESS;
154}
155
156static int32_t UsbFnDriverInit(struct HdfDeviceObject *device)
157{
158    struct DevUsbFnMgr *devMgr = NULL;
159    uint8_t useHcs;
160
161    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
162    if (iface == NULL || iface->GetUint32 == NULL || device == NULL) {
163        HDF_LOGE("%{public}s: iface is invalid", __func__);
164        return HDF_FAILURE;
165    }
166    devMgr = (struct DevUsbFnMgr *)device->service;
167    if (iface->GetString(device->property, "udc_name", &devMgr->udcName, UDC_NAME) != HDF_SUCCESS) {
168        HDF_LOGE("%{public}s: read udc_name failed, use default: %{public}s", __func__, UDC_NAME);
169        return HDF_FAILURE;
170    }
171    HDF_LOGI("%{public}s: udcName=%{public}s", __func__, devMgr->udcName);
172    if (iface->GetUint8(device->property, "use_hcs", &useHcs, 0) != HDF_SUCCESS) {
173        HDF_LOGE("%{public}s: read use_hcs fail, use default", __func__);
174    }
175    HDF_LOGI("%{public}s: use descriptor in %{public}s", __func__, (useHcs == 1) ? "hcs" : "code");
176    /* force use descripto in hcs, refer to sample for use descriptor in code */
177    devMgr->descData.type = USBFN_DESC_DATA_TYPE_PROP;
178    devMgr->descData.property = device->property;
179    return HDF_SUCCESS;
180}
181
182static void UsbFnDriverRelease(struct HdfDeviceObject *device)
183{
184    struct DevUsbFnMgr *devMgr = NULL;
185    devMgr = (struct DevUsbFnMgr *)device->service;
186    if (devMgr == NULL) {
187        HDF_LOGE("%{public}s: descriptor is NULL", __func__);
188        return;
189    }
190    OsalMemFree(devMgr);
191}
192
193struct HdfDriverEntry g_usbFnDriverEntry = {
194    .moduleVersion = 1,
195    .moduleName = "usbfn",
196    .Bind = UsbFnDriverBind,
197    .Init = UsbFnDriverInit,
198    .Release = UsbFnDriverRelease,
199};
200
201HDF_INIT(g_usbFnDriverEntry);
202