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 }