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 "usb_ddk_api.h"
17 #include <cerrno>
18 #include <memory.h>
19 #include <securec.h>
20 #include <sys/mman.h>
21 #include <unistd.h>
22 #include <vector>
23 
24 #include "edm_errors.h"
25 #include "hilog_wrapper.h"
26 #include "usb_config_desc_parser.h"
27 #include "usb_ddk_types.h"
28 #include "v1_0/usb_ddk_service.h"
29 
30 using namespace OHOS::ExternalDeviceManager;
31 namespace {
32 OHOS::sptr<OHOS::HDI::Usb::Ddk::V1_0::IUsbDdk> g_ddk = nullptr;
33 } // namespace
34 
OH_Usb_Init()35 int32_t OH_Usb_Init()
36 {
37     g_ddk = OHOS::HDI::Usb::Ddk::V1_0::IUsbDdk::Get();
38     if (g_ddk == nullptr) {
39         EDM_LOGE(MODULE_USB_DDK, "get ddk failed");
40         return USB_DDK_FAILED;
41     }
42 
43     return g_ddk->Init();
44 }
45 
OH_Usb_Release()46 void OH_Usb_Release()
47 {
48     if (g_ddk == nullptr) {
49         EDM_LOGE(MODULE_USB_DDK, "ddk is null");
50         return;
51     }
52     g_ddk->Release();
53     g_ddk.clear();
54 }
55 
OH_Usb_GetDeviceDescriptor(uint64_t deviceId,UsbDeviceDescriptor * desc)56 int32_t OH_Usb_GetDeviceDescriptor(uint64_t deviceId, UsbDeviceDescriptor *desc)
57 {
58     if (g_ddk == nullptr) {
59         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
60         return USB_DDK_INVALID_OPERATION;
61     }
62     if (desc == nullptr) {
63         EDM_LOGE(MODULE_USB_DDK, "param is null");
64         return USB_DDK_INVALID_PARAMETER;
65     }
66 
67     auto tmpDesc = reinterpret_cast<OHOS::HDI::Usb::Ddk::V1_0::UsbDeviceDescriptor *>(desc);
68     int32_t ret = g_ddk->GetDeviceDescriptor(deviceId, *tmpDesc);
69     if (ret != EDM_OK) {
70         EDM_LOGE(MODULE_USB_DDK, "get device desc failed: %{public}d", ret);
71         return ret;
72     }
73     return EDM_OK;
74 }
75 
OH_Usb_GetConfigDescriptor(uint64_t deviceId,uint8_t configIndex,struct UsbDdkConfigDescriptor ** const config)76 int32_t OH_Usb_GetConfigDescriptor(
77     uint64_t deviceId, uint8_t configIndex, struct UsbDdkConfigDescriptor ** const config)
78 {
79     if (g_ddk == nullptr) {
80         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
81         return USB_DDK_INVALID_OPERATION;
82     }
83     if (config == nullptr) {
84         EDM_LOGE(MODULE_USB_DDK, "param is null");
85         return USB_DDK_INVALID_PARAMETER;
86     }
87     std::vector<uint8_t> configDescriptor;
88     int32_t ret = g_ddk->GetConfigDescriptor(deviceId, configIndex, configDescriptor);
89     if (ret != EDM_OK) {
90         EDM_LOGE(MODULE_USB_DDK, "get config desc failed");
91         return ret;
92     }
93 
94     return ParseUsbConfigDescriptor(configDescriptor, config);
95 }
96 
OH_Usb_FreeConfigDescriptor(UsbDdkConfigDescriptor * const config)97 void OH_Usb_FreeConfigDescriptor(UsbDdkConfigDescriptor * const config)
98 {
99     return FreeUsbConfigDescriptor(config);
100 }
101 
OH_Usb_ClaimInterface(uint64_t deviceId,uint8_t interfaceIndex,uint64_t * interfaceHandle)102 int32_t OH_Usb_ClaimInterface(uint64_t deviceId, uint8_t interfaceIndex, uint64_t *interfaceHandle)
103 {
104     if (g_ddk == nullptr) {
105         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
106         return USB_DDK_INVALID_OPERATION;
107     }
108     if (interfaceHandle == nullptr) {
109         EDM_LOGE(MODULE_USB_DDK, "param is null");
110         return USB_DDK_INVALID_PARAMETER;
111     }
112 
113     return g_ddk->ClaimInterface(deviceId, interfaceIndex, *interfaceHandle);
114 }
115 
OH_Usb_ReleaseInterface(uint64_t interfaceHandle)116 int32_t OH_Usb_ReleaseInterface(uint64_t interfaceHandle)
117 {
118     if (g_ddk == nullptr) {
119         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
120         return USB_DDK_INVALID_OPERATION;
121     }
122 
123     return g_ddk->ReleaseInterface(interfaceHandle);
124 }
125 
OH_Usb_SelectInterfaceSetting(uint64_t interfaceHandle,uint8_t settingIndex)126 int32_t OH_Usb_SelectInterfaceSetting(uint64_t interfaceHandle, uint8_t settingIndex)
127 {
128     if (g_ddk == nullptr) {
129         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
130         return USB_DDK_INVALID_OPERATION;
131     }
132 
133     return g_ddk->SelectInterfaceSetting(interfaceHandle, settingIndex);
134 }
135 
OH_Usb_GetCurrentInterfaceSetting(uint64_t interfaceHandle,uint8_t * settingIndex)136 int32_t OH_Usb_GetCurrentInterfaceSetting(uint64_t interfaceHandle, uint8_t *settingIndex)
137 {
138     if (g_ddk == nullptr) {
139         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
140         return USB_DDK_INVALID_OPERATION;
141     }
142 
143     if (settingIndex == nullptr) {
144         EDM_LOGE(MODULE_USB_DDK, "param is null");
145         return USB_DDK_INVALID_PARAMETER;
146     }
147 
148     return g_ddk->GetCurrentInterfaceSetting(interfaceHandle, *settingIndex);
149 }
150 
OH_Usb_SendControlReadRequest(uint64_t interfaceHandle,const UsbControlRequestSetup * setup,uint32_t timeout,uint8_t * data,uint32_t * dataLen)151 int32_t OH_Usb_SendControlReadRequest(
152     uint64_t interfaceHandle, const UsbControlRequestSetup *setup, uint32_t timeout, uint8_t *data, uint32_t *dataLen)
153 {
154     if (g_ddk == nullptr) {
155         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
156         return USB_DDK_INVALID_OPERATION;
157     }
158 
159     if (setup == nullptr || data == nullptr || dataLen == nullptr) {
160         EDM_LOGE(MODULE_USB_DDK, "param is null");
161         return USB_DDK_INVALID_PARAMETER;
162     }
163 
164     auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_0::UsbControlRequestSetup *>(setup);
165     std::vector<uint8_t> dataTmp;
166     int32_t ret = g_ddk->SendControlReadRequest(interfaceHandle, *tmpSetUp, timeout, dataTmp);
167     if (ret != 0) {
168         EDM_LOGE(MODULE_USB_DDK, "send control req failed");
169         return ret;
170     }
171 
172     if (*dataLen < dataTmp.size()) {
173         EDM_LOGE(MODULE_USB_DDK, "The data is too small");
174         return USB_DDK_INVALID_PARAMETER;
175     }
176 
177     if (memcpy_s(data, *dataLen, dataTmp.data(), dataTmp.size()) != 0) {
178         EDM_LOGE(MODULE_USB_DDK, "copy data failed");
179         return USB_DDK_MEMORY_ERROR;
180     }
181     *dataLen = dataTmp.size();
182     return EDM_OK;
183 }
184 
OH_Usb_SendControlWriteRequest(uint64_t interfaceHandle,const UsbControlRequestSetup * setup,uint32_t timeout,const uint8_t * data,uint32_t dataLen)185 int32_t OH_Usb_SendControlWriteRequest(uint64_t interfaceHandle, const UsbControlRequestSetup *setup, uint32_t timeout,
186     const uint8_t *data, uint32_t dataLen)
187 {
188     if (g_ddk == nullptr) {
189         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
190         return USB_DDK_INVALID_OPERATION;
191     }
192 
193     if (setup == nullptr || data == nullptr) {
194         EDM_LOGE(MODULE_USB_DDK, "param is null");
195         return USB_DDK_INVALID_PARAMETER;
196     }
197 
198     auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_0::UsbControlRequestSetup *>(setup);
199     std::vector<uint8_t> dataTmp(data, data + dataLen);
200     return g_ddk->SendControlWriteRequest(interfaceHandle, *tmpSetUp, timeout, dataTmp);
201 }
202 
OH_Usb_SendPipeRequest(const UsbRequestPipe * pipe,UsbDeviceMemMap * devMmap)203 int32_t OH_Usb_SendPipeRequest(const UsbRequestPipe *pipe, UsbDeviceMemMap *devMmap)
204 {
205     if (g_ddk == nullptr) {
206         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
207         return USB_DDK_INVALID_OPERATION;
208     }
209 
210     if (pipe == nullptr || devMmap == nullptr || devMmap->address == nullptr) {
211         EDM_LOGE(MODULE_USB_DDK, "param is null");
212         return USB_DDK_INVALID_PARAMETER;
213     }
214 
215     auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_0::UsbRequestPipe *>(pipe);
216     return g_ddk->SendPipeRequest(
217         *tmpSetUp, devMmap->size, devMmap->offset, devMmap->bufferLength, devMmap->transferedLength);
218 }
219 
OH_Usb_SendPipeRequestWithAshmem(const UsbRequestPipe * pipe,DDK_Ashmem * ashmem)220 int32_t OH_Usb_SendPipeRequestWithAshmem(const UsbRequestPipe *pipe, DDK_Ashmem *ashmem)
221 {
222     if (g_ddk == nullptr) {
223         EDM_LOGE(MODULE_USB_DDK, "invalid obj");
224         return USB_DDK_INVALID_OPERATION;
225     }
226 
227     if (pipe == nullptr || ashmem == nullptr || ashmem->address == nullptr) {
228         EDM_LOGE(MODULE_USB_DDK, "param is null");
229         return USB_DDK_INVALID_PARAMETER;
230     }
231 
232     auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_0::UsbRequestPipe *>(pipe);
233     std::vector<uint8_t> address = std::vector<uint8_t>(ashmem->address, ashmem->address + ashmem->size);
234     OHOS::HDI::Usb::Ddk::V1_0::UsbAshmem usbAshmem = {ashmem->ashmemFd, address, ashmem->size, 0, ashmem->size, 0};
235     return g_ddk->SendPipeRequestWithAshmem(*tmpSetUp, usbAshmem, ashmem->transferredLength);
236 }
237 
OH_Usb_CreateDeviceMemMap(uint64_t deviceId,size_t size,UsbDeviceMemMap ** devMmap)238 int32_t OH_Usb_CreateDeviceMemMap(uint64_t deviceId, size_t size, UsbDeviceMemMap **devMmap)
239 {
240     if (devMmap == nullptr) {
241         EDM_LOGE(MODULE_USB_DDK, "invalid param");
242         return USB_DDK_INVALID_PARAMETER;
243     }
244 
245     int32_t fd = -1;
246     int32_t ret = g_ddk->GetDeviceMemMapFd(deviceId, fd);
247     if (ret != EDM_OK) {
248         EDM_LOGE(MODULE_USB_DDK, "get fd failed, errno=%{public}d", errno);
249         return ret;
250     }
251     ftruncate(fd, size);
252 
253     auto buffer = static_cast<uint8_t *>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
254     if (buffer == MAP_FAILED) {
255         EDM_LOGE(MODULE_USB_DDK, "mmap failed, errno=%{public}d", errno);
256         return USB_DDK_MEMORY_ERROR;
257     }
258 
259     UsbDeviceMemMap *memMap = new UsbDeviceMemMap({buffer, size, 0, size, 0});
260     if (memMap == nullptr) {
261         EDM_LOGE(MODULE_USB_DDK, "alloc dev mem failed, errno=%{public}d", errno);
262         return USB_DDK_MEMORY_ERROR;
263     }
264 
265     *devMmap = memMap;
266     return EDM_OK;
267 }
268 
OH_Usb_DestroyDeviceMemMap(UsbDeviceMemMap * devMmap)269 void OH_Usb_DestroyDeviceMemMap(UsbDeviceMemMap *devMmap)
270 {
271     if (devMmap == nullptr) {
272         EDM_LOGE(MODULE_USB_DDK, "devMmap is nullptr");
273         return;
274     }
275 
276     if (munmap(devMmap->address, devMmap->size) != 0) {
277         EDM_LOGE(MODULE_USB_DDK, "munmap failed, errno=%{public}d", errno);
278         return;
279     }
280     delete devMmap;
281 }