1 /*
2 * Copyright (c) 2023-2025 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 #include <unordered_map>
24
25 #include "edm_errors.h"
26 #include "hilog_wrapper.h"
27 #include "usb_config_desc_parser.h"
28 #include "usb_ddk_types.h"
29 #include "v1_1/usb_ddk_service.h"
30
31 using namespace OHOS::ExternalDeviceManager;
32 namespace {
33 OHOS::sptr<OHOS::HDI::Usb::Ddk::V1_1::IUsbDdk> g_ddk = nullptr;
34 std::unordered_map<int32_t, int32_t> g_errorMap = {
35 {HDF_SUCCESS, USB_DDK_SUCCESS},
36 {HDF_ERR_NOT_SUPPORT, USB_DDK_INVALID_OPERATION},
37 {HDF_FAILURE, USB_DDK_INVALID_OPERATION},
38 {HDF_ERR_INVALID_PARAM, USB_DDK_INVALID_PARAMETER},
39 {HDF_ERR_BAD_FD, USB_DDK_INVALID_PARAMETER},
40 {HDF_ERR_NOPERM, USB_DDK_NO_PERM},
41 {HDF_DEV_ERR_NO_MEMORY, USB_DDK_MEMORY_ERROR},
42 {HDF_ERR_OUT_OF_RANGE, USB_DDK_MEMORY_ERROR},
43 {HDF_ERR_IO, USB_DDK_IO_FAILED},
44 {HDF_ERR_TIMEOUT, USB_DDK_TIMEOUT}
45 };
46 } // namespace
47
TransToUsbCode(int32_t ret)48 static int32_t TransToUsbCode(int32_t ret)
49 {
50 if ((g_errorMap.find(ret) != g_errorMap.end())) {
51 return g_errorMap[ret];
52 } else {
53 return ret;
54 }
55 }
56
OH_Usb_Init()57 int32_t OH_Usb_Init()
58 {
59 g_ddk = OHOS::HDI::Usb::Ddk::V1_1::IUsbDdk::Get();
60 if (g_ddk == nullptr) {
61 EDM_LOGE(MODULE_USB_DDK, "get ddk failed");
62 return USB_DDK_INVALID_OPERATION;
63 }
64
65 return TransToUsbCode(g_ddk->Init());
66 }
67
OH_Usb_Release()68 void OH_Usb_Release()
69 {
70 if (g_ddk == nullptr) {
71 EDM_LOGE(MODULE_USB_DDK, "ddk is null");
72 return;
73 }
74 g_ddk->Release();
75 g_ddk.clear();
76 }
77
OH_Usb_ReleaseResource()78 int32_t OH_Usb_ReleaseResource()
79 {
80 if (g_ddk == nullptr) {
81 EDM_LOGE(MODULE_USB_DDK, "ddk is null");
82 return USB_DDK_INVALID_OPERATION;
83 }
84 int32_t ret = TransToUsbCode(g_ddk->Release());
85 if (ret != USB_DDK_SUCCESS) {
86 EDM_LOGE(MODULE_USB_DDK, "release failed: %{public}d", ret);
87 }
88 g_ddk.clear();
89 return ret;
90 }
91
OH_Usb_GetDeviceDescriptor(uint64_t deviceId,UsbDeviceDescriptor * desc)92 int32_t OH_Usb_GetDeviceDescriptor(uint64_t deviceId, UsbDeviceDescriptor *desc)
93 {
94 if (g_ddk == nullptr) {
95 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
96 return USB_DDK_INVALID_OPERATION;
97 }
98 if (desc == nullptr) {
99 EDM_LOGE(MODULE_USB_DDK, "param is null");
100 return USB_DDK_INVALID_PARAMETER;
101 }
102
103 auto tmpDesc = reinterpret_cast<OHOS::HDI::Usb::Ddk::V1_1::UsbDeviceDescriptor *>(desc);
104 int32_t ret = TransToUsbCode(g_ddk->GetDeviceDescriptor(deviceId, *tmpDesc));
105 if (ret != USB_DDK_SUCCESS) {
106 EDM_LOGE(MODULE_USB_DDK, "get device desc failed: %{public}d", ret);
107 return ret;
108 }
109 return USB_DDK_SUCCESS;
110 }
111
OH_Usb_GetConfigDescriptor(uint64_t deviceId,uint8_t configIndex,struct UsbDdkConfigDescriptor ** const config)112 int32_t OH_Usb_GetConfigDescriptor(
113 uint64_t deviceId, uint8_t configIndex, struct UsbDdkConfigDescriptor ** const config)
114 {
115 if (g_ddk == nullptr) {
116 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
117 return USB_DDK_INVALID_OPERATION;
118 }
119 if (config == nullptr) {
120 EDM_LOGE(MODULE_USB_DDK, "param is null");
121 return USB_DDK_INVALID_PARAMETER;
122 }
123 std::vector<uint8_t> configDescriptor;
124 int32_t ret = TransToUsbCode(g_ddk->GetConfigDescriptor(deviceId, configIndex, configDescriptor));
125 if (ret != USB_DDK_SUCCESS) {
126 EDM_LOGE(MODULE_USB_DDK, "get config desc failed");
127 return ret;
128 }
129
130 return ParseUsbConfigDescriptor(configDescriptor, config);
131 }
132
OH_Usb_FreeConfigDescriptor(UsbDdkConfigDescriptor * const config)133 void OH_Usb_FreeConfigDescriptor(UsbDdkConfigDescriptor * const config)
134 {
135 return FreeUsbConfigDescriptor(config);
136 }
137
OH_Usb_ClaimInterface(uint64_t deviceId,uint8_t interfaceIndex,uint64_t * interfaceHandle)138 int32_t OH_Usb_ClaimInterface(uint64_t deviceId, uint8_t interfaceIndex, uint64_t *interfaceHandle)
139 {
140 if (g_ddk == nullptr) {
141 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
142 return USB_DDK_INVALID_OPERATION;
143 }
144 if (interfaceHandle == nullptr) {
145 EDM_LOGE(MODULE_USB_DDK, "param is null");
146 return USB_DDK_INVALID_PARAMETER;
147 }
148
149 return TransToUsbCode(g_ddk->ClaimInterface(deviceId, interfaceIndex, *interfaceHandle));
150 }
151
OH_Usb_ReleaseInterface(uint64_t interfaceHandle)152 int32_t OH_Usb_ReleaseInterface(uint64_t interfaceHandle)
153 {
154 if (g_ddk == nullptr) {
155 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
156 return USB_DDK_INVALID_OPERATION;
157 }
158
159 return TransToUsbCode(g_ddk->ReleaseInterface(interfaceHandle));
160 }
161
OH_Usb_SelectInterfaceSetting(uint64_t interfaceHandle,uint8_t settingIndex)162 int32_t OH_Usb_SelectInterfaceSetting(uint64_t interfaceHandle, uint8_t settingIndex)
163 {
164 if (g_ddk == nullptr) {
165 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
166 return USB_DDK_INVALID_OPERATION;
167 }
168
169 return TransToUsbCode(g_ddk->SelectInterfaceSetting(interfaceHandle, settingIndex));
170 }
171
OH_Usb_GetCurrentInterfaceSetting(uint64_t interfaceHandle,uint8_t * settingIndex)172 int32_t OH_Usb_GetCurrentInterfaceSetting(uint64_t interfaceHandle, uint8_t *settingIndex)
173 {
174 if (g_ddk == nullptr) {
175 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
176 return USB_DDK_INVALID_OPERATION;
177 }
178
179 if (settingIndex == nullptr) {
180 EDM_LOGE(MODULE_USB_DDK, "param is null");
181 return USB_DDK_INVALID_PARAMETER;
182 }
183
184 return TransToUsbCode(g_ddk->GetCurrentInterfaceSetting(interfaceHandle, *settingIndex));
185 }
186
OH_Usb_SendControlReadRequest(uint64_t interfaceHandle,const UsbControlRequestSetup * setup,uint32_t timeout,uint8_t * data,uint32_t * dataLen)187 int32_t OH_Usb_SendControlReadRequest(
188 uint64_t interfaceHandle, const UsbControlRequestSetup *setup, uint32_t timeout, uint8_t *data, uint32_t *dataLen)
189 {
190 if (g_ddk == nullptr) {
191 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
192 return USB_DDK_INVALID_OPERATION;
193 }
194
195 if (setup == nullptr || data == nullptr || dataLen == nullptr) {
196 EDM_LOGE(MODULE_USB_DDK, "param is null");
197 return USB_DDK_INVALID_PARAMETER;
198 }
199
200 auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_1::UsbControlRequestSetup *>(setup);
201 std::vector<uint8_t> dataTmp;
202 int32_t ret = TransToUsbCode(g_ddk->SendControlReadRequest(interfaceHandle, *tmpSetUp, timeout, dataTmp));
203 if (ret != 0) {
204 EDM_LOGE(MODULE_USB_DDK, "send control req failed");
205 return ret;
206 }
207
208 if (*dataLen < dataTmp.size()) {
209 EDM_LOGE(MODULE_USB_DDK, "The data is too small");
210 return USB_DDK_INVALID_PARAMETER;
211 }
212
213 if (memcpy_s(data, *dataLen, dataTmp.data(), dataTmp.size()) != 0) {
214 EDM_LOGE(MODULE_USB_DDK, "copy data failed");
215 return USB_DDK_MEMORY_ERROR;
216 }
217 *dataLen = dataTmp.size();
218 return USB_DDK_SUCCESS;
219 }
220
OH_Usb_SendControlWriteRequest(uint64_t interfaceHandle,const UsbControlRequestSetup * setup,uint32_t timeout,const uint8_t * data,uint32_t dataLen)221 int32_t OH_Usb_SendControlWriteRequest(uint64_t interfaceHandle, const UsbControlRequestSetup *setup, uint32_t timeout,
222 const uint8_t *data, uint32_t dataLen)
223 {
224 if (g_ddk == nullptr) {
225 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
226 return USB_DDK_INVALID_OPERATION;
227 }
228
229 if (setup == nullptr || data == nullptr) {
230 EDM_LOGE(MODULE_USB_DDK, "param is null");
231 return USB_DDK_INVALID_PARAMETER;
232 }
233
234 auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_1::UsbControlRequestSetup *>(setup);
235 std::vector<uint8_t> dataTmp(data, data + dataLen);
236 return TransToUsbCode(g_ddk->SendControlWriteRequest(interfaceHandle, *tmpSetUp, timeout, dataTmp));
237 }
238
OH_Usb_SendPipeRequest(const UsbRequestPipe * pipe,UsbDeviceMemMap * devMmap)239 int32_t OH_Usb_SendPipeRequest(const UsbRequestPipe *pipe, UsbDeviceMemMap *devMmap)
240 {
241 if (g_ddk == nullptr) {
242 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
243 return USB_DDK_INVALID_OPERATION;
244 }
245
246 if (pipe == nullptr || devMmap == nullptr || devMmap->address == nullptr) {
247 EDM_LOGE(MODULE_USB_DDK, "param is null");
248 return USB_DDK_INVALID_PARAMETER;
249 }
250
251 auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_1::UsbRequestPipe *>(pipe);
252 return TransToUsbCode(g_ddk->SendPipeRequest(
253 *tmpSetUp, devMmap->size, devMmap->offset, devMmap->bufferLength, devMmap->transferedLength));
254 }
255
OH_Usb_SendPipeRequestWithAshmem(const UsbRequestPipe * pipe,DDK_Ashmem * ashmem)256 int32_t OH_Usb_SendPipeRequestWithAshmem(const UsbRequestPipe *pipe, DDK_Ashmem *ashmem)
257 {
258 if (g_ddk == nullptr) {
259 EDM_LOGE(MODULE_USB_DDK, "invalid obj");
260 return USB_DDK_INVALID_OPERATION;
261 }
262
263 if (pipe == nullptr || ashmem == nullptr || ashmem->address == nullptr) {
264 EDM_LOGE(MODULE_USB_DDK, "param is null");
265 return USB_DDK_INVALID_PARAMETER;
266 }
267
268 auto tmpSetUp = reinterpret_cast<const OHOS::HDI::Usb::Ddk::V1_1::UsbRequestPipe *>(pipe);
269 std::vector<uint8_t> address = std::vector<uint8_t>(ashmem->address, ashmem->address + ashmem->size);
270 OHOS::HDI::Usb::Ddk::V1_1::UsbAshmem usbAshmem = {ashmem->ashmemFd, address, ashmem->size, 0, ashmem->size, 0};
271 return TransToUsbCode(g_ddk->SendPipeRequestWithAshmem(*tmpSetUp, usbAshmem, ashmem->transferredLength));
272 }
273
OH_Usb_CreateDeviceMemMap(uint64_t deviceId,size_t size,UsbDeviceMemMap ** devMmap)274 int32_t OH_Usb_CreateDeviceMemMap(uint64_t deviceId, size_t size, UsbDeviceMemMap **devMmap)
275 {
276 if (devMmap == nullptr) {
277 EDM_LOGE(MODULE_USB_DDK, "invalid param");
278 return USB_DDK_INVALID_PARAMETER;
279 }
280
281 int32_t fd = -1;
282 int32_t ret = TransToUsbCode(g_ddk->GetDeviceMemMapFd(deviceId, fd));
283 if (ret != USB_DDK_SUCCESS) {
284 EDM_LOGE(MODULE_USB_DDK, "get fd failed, errno=%{public}d", errno);
285 return ret;
286 }
287 ftruncate(fd, size);
288
289 auto buffer = static_cast<uint8_t *>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
290 if (buffer == MAP_FAILED) {
291 EDM_LOGE(MODULE_USB_DDK, "mmap failed, errno=%{public}d", errno);
292 return USB_DDK_MEMORY_ERROR;
293 }
294
295 UsbDeviceMemMap *memMap = new UsbDeviceMemMap({buffer, size, 0, size, 0});
296 if (memMap == nullptr) {
297 EDM_LOGE(MODULE_USB_DDK, "alloc dev mem failed, errno=%{public}d", errno);
298 return USB_DDK_MEMORY_ERROR;
299 }
300
301 *devMmap = memMap;
302 return USB_DDK_SUCCESS;
303 }
304
OH_Usb_DestroyDeviceMemMap(UsbDeviceMemMap * devMmap)305 void OH_Usb_DestroyDeviceMemMap(UsbDeviceMemMap *devMmap)
306 {
307 if (devMmap == nullptr) {
308 EDM_LOGE(MODULE_USB_DDK, "devMmap is nullptr");
309 return;
310 }
311
312 if (munmap(devMmap->address, devMmap->size) != 0) {
313 EDM_LOGE(MODULE_USB_DDK, "munmap failed, errno=%{public}d", errno);
314 return;
315 }
316 delete devMmap;
317 }
318
OH_Usb_GetDevices(struct Usb_DeviceArray * devices)319 int32_t OH_Usb_GetDevices(struct Usb_DeviceArray *devices)
320 {
321 if (g_ddk == nullptr) {
322 EDM_LOGE(MODULE_USB_DDK, "%{public}s: invalid obj", __func__);
323 return USB_DDK_INVALID_OPERATION;
324 }
325 if (devices == nullptr) {
326 EDM_LOGE(MODULE_USB_DDK, "%{public}s: param is null", __func__);
327 return USB_DDK_INVALID_PARAMETER;
328 }
329
330 std::vector<uint64_t> deviceIds;
331 int32_t ret = TransToUsbCode(g_ddk->GetDevices(deviceIds));
332 if (ret != USB_DDK_SUCCESS) {
333 EDM_LOGE(MODULE_USB_DDK, "%{public}s: get devices failed", __func__);
334 return ret;
335 }
336
337 devices->num = deviceIds.size();
338 for (size_t i = 0; i < deviceIds.size(); i++) {
339 devices->deviceIds[i] = deviceIds[i];
340 }
341
342 return USB_DDK_SUCCESS;
343 }