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 "usb_io_manage.h"
17 #include "usb_raw_api_library.h"
18 #include "usbd_wrapper.h"
19
20 #define HDF_LOG_TAG USB_IO_MANAGE
21
22 static const int MAX_ERROR_TIMES = 20;
23
IoCancelRequest(struct UsbInterfacePool * interfacePool,const struct UsbHostRequest * hostRequest)24 static bool IoCancelRequest(struct UsbInterfacePool *interfacePool, const struct UsbHostRequest *hostRequest)
25 {
26 struct UsbIfRequest *requestObj = NULL;
27
28 if (hostRequest == NULL) {
29 HDF_LOGE("%{public}s:%{public}d hostRequest is NULL", __func__, __LINE__);
30 return true;
31 }
32
33 requestObj = (struct UsbIfRequest *)hostRequest->privateObj;
34 if (requestObj == NULL) {
35 HDF_LOGE("%{public}s:%{public}d get request error", __func__, __LINE__);
36 return true;
37 }
38
39 if (interfacePool->ioProcessStopStatus != USB_POOL_PROCESS_RUNNING) {
40 UsbCancelRequest(&requestObj->request);
41 }
42
43 return (requestObj->request.compInfo.status == USB_REQUEST_CANCELLED);
44 }
45
IoSendProcess(const void * interfacePoolArg)46 static int32_t IoSendProcess(const void *interfacePoolArg)
47 {
48 if (interfacePoolArg == NULL) {
49 HDF_LOGE("%{public}s: invalid param", __func__);
50 return HDF_ERR_INVALID_PARAM;
51 }
52
53 struct UsbInterfacePool *interfacePool = (struct UsbInterfacePool *)interfacePoolArg;
54 struct UsbHostRequest *submitRequest = NULL;
55 int32_t ret;
56 int32_t i;
57 int32_t errorTimes = 0;
58
59 while (errorTimes < MAX_ERROR_TIMES) {
60 submitRequest = NULL;
61 /* Get a request from curretn submit queue */
62 ret = UsbIoGetRequest(&interfacePool->submitRequestQueue, &submitRequest);
63
64 if (interfacePool->ioProcessStopStatus != USB_POOL_PROCESS_RUNNING) {
65 if (submitRequest != NULL) {
66 submitRequest->status = USB_REQUEST_ERROR;
67 UsbIoSetRequestCompletionInfo(submitRequest);
68 }
69 break;
70 }
71
72 if (ret != HDF_SUCCESS || submitRequest == NULL) {
73 ++errorTimes;
74 HDF_LOGE("%{public}s:%{public}d ret=%{public}d errtimes=%{public}d", __func__, __LINE__, ret, errorTimes);
75 continue;
76 }
77 errorTimes = 0;
78
79 if (IoCancelRequest(interfacePool, submitRequest)) {
80 continue;
81 }
82
83 for (i = 0; i < USB_IO_SUBMIT_RETRY_TIME_CNT; i++) {
84 ret = RawSubmitRequest(submitRequest);
85 if (ret != HDF_SUCCESS) {
86 continue;
87 }
88 /* Submit success */
89 OsalSemPost(&interfacePool->ioSem);
90 break;
91 }
92
93 if (i >= USB_IO_SUBMIT_RETRY_TIME_CNT) {
94 HDF_LOGE("%{public}s:%{public}d submit request failed", __func__, __LINE__);
95 submitRequest->status = USB_REQUEST_ERROR;
96 UsbIoSetRequestCompletionInfo(submitRequest);
97 continue;
98 }
99 }
100 HDF_LOGD("%{public}s, stop. errorTimes=%{public}d", __func__, errorTimes);
101 return 0;
102 }
103
InitializeIoProcess(struct UsbInterfacePool * interfacePool)104 static void InitializeIoProcess(struct UsbInterfacePool *interfacePool)
105 {
106 if (!interfacePool->ioProcessTid) {
107 interfacePool->ioProcessTid = RawGetTid();
108 }
109 }
110
IoAsyncReceiveProcess(const void * interfacePoolArg)111 static int32_t IoAsyncReceiveProcess(const void *interfacePoolArg)
112 {
113 if (interfacePoolArg == NULL) {
114 HDF_LOGE("%{public}s: invalid param", __func__);
115 return HDF_ERR_INVALID_PARAM;
116 }
117
118 struct UsbInterfacePool *interfacePool = (struct UsbInterfacePool *)interfacePoolArg;
119 if (RawRegisterSignal() != HDF_SUCCESS) {
120 HDF_LOGE("%{public}s:%{public}d RawRegisterSignal error", __func__, __LINE__);
121 }
122
123 HDF_LOGD("%{public}s, enter recv thread", __func__);
124 while (true) {
125 InitializeIoProcess(interfacePool);
126 if (interfacePool->device == NULL) {
127 HDF_LOGE("%{public}s:%{public}d interfacePool->device is NULL!", __func__, __LINE__);
128 OsalMSleep(USB_IO_SLEEP_MS_TIME);
129 continue;
130 }
131
132 if (interfacePool->device->devHandle == NULL) {
133 HDF_LOGE("%{public}s:%{public}d interfacePool->device->devHandle is NULL!", __func__, __LINE__);
134 OsalMSleep(USB_IO_SLEEP_MS_TIME);
135 continue;
136 }
137
138 int32_t ret = OsalSemWait(&interfacePool->ioSem, HDF_WAIT_FOREVER);
139 if (ret != HDF_SUCCESS) {
140 HDF_LOGE("sem wait failed: %{public}d", ret);
141 }
142
143 if (interfacePool->ioProcessStopStatus != USB_POOL_PROCESS_RUNNING ||
144 interfacePool->ioRecvProcessStopStatus != USB_POOL_PROCESS_RUNNING) {
145 break;
146 }
147
148 ret = RawHandleRequest(interfacePool->device->devHandle);
149 if (ret == HDF_DEV_ERR_NO_DEVICE) {
150 HDF_LOGE("%{public}s dev is not found ret: %{public}d", __func__, ret);
151 break;
152 }
153
154 if (ret < 0) {
155 HDF_LOGE("%{public}s RawHandleRequest failed ret: %{public}d", __func__, ret);
156 OsalMSleep(USB_IO_SLEEP_MS_TIME);
157 continue;
158 }
159 }
160 HDF_LOGD("%{public}s, recv thread end. ", __func__);
161 OsalMutexLock(&interfacePool->ioStopLock);
162 interfacePool->ioProcessStopStatus = USB_POOL_PROCESS_STOPED;
163 interfacePool->ioRecvProcessStopStatus = USB_POOL_PROCESS_STOPED;
164 OsalSemPost(&interfacePool->submitRequestQueue.sem);
165 OsalMutexUnlock(&interfacePool->ioStopLock);
166
167 return HDF_SUCCESS;
168 }
169
UsbIoCreateQueue(const struct UsbInterfacePool * interfacePool)170 HDF_STATUS UsbIoCreateQueue(const struct UsbInterfacePool *interfacePool)
171 {
172 if (interfacePool == NULL) {
173 HDF_LOGE("%{public}s: invalid param", __func__);
174 return HDF_ERR_INVALID_PARAM;
175 }
176
177 DListHeadInit((struct DListHead *)&interfacePool->submitRequestQueue.entry);
178 OsalMutexInit((struct OsalMutex *)&interfacePool->submitRequestQueue.mutex);
179 OsalSemInit((struct OsalSem *)&interfacePool->submitRequestQueue.sem, 0);
180
181 return HDF_SUCCESS;
182 }
183
UsbIoDestroyQueue(const struct UsbInterfacePool * interfacePool)184 HDF_STATUS UsbIoDestroyQueue(const struct UsbInterfacePool *interfacePool)
185 {
186 if (interfacePool == NULL) {
187 HDF_LOGE("%{public}s: invalid param", __func__);
188 return HDF_ERR_INVALID_PARAM;
189 }
190
191 if (!DListIsEmpty(&interfacePool->submitRequestQueue.entry)) {
192 HDF_LOGE("%{public}s:%{public}d submitRequestQueue is not empty", __func__, __LINE__);
193 return HDF_FAILURE;
194 }
195
196 OsalMutexDestroy((struct OsalMutex *)&interfacePool->submitRequestQueue.mutex);
197 OsalSemDestroy((struct OsalSem *)&interfacePool->submitRequestQueue.sem);
198
199 return HDF_SUCCESS;
200 }
201
UsbIoSendRequest(const struct UsbMessageQueue * msgQueue,const struct UsbHostRequest * request)202 int32_t UsbIoSendRequest(const struct UsbMessageQueue *msgQueue, const struct UsbHostRequest *request)
203 {
204 if ((msgQueue == NULL) || (request == NULL)) {
205 HDF_LOGE("%{public}s:%{public}d invalid parameter", __func__, __LINE__);
206 return HDF_ERR_INVALID_PARAM;
207 }
208
209 OsalMutexLock((struct OsalMutex *)&msgQueue->mutex);
210 DListInsertTail((struct DListHead *)&request->list, (struct DListHead *)&msgQueue->entry);
211 OsalMutexUnlock((struct OsalMutex *)&msgQueue->mutex);
212
213 OsalSemPost((struct OsalSem *)&msgQueue->sem);
214
215 return HDF_SUCCESS;
216 }
217
UsbIoGetRequest(const struct UsbMessageQueue * msgQueue,struct UsbHostRequest ** request)218 HDF_STATUS UsbIoGetRequest(const struct UsbMessageQueue *msgQueue, struct UsbHostRequest **request)
219 {
220 HDF_STATUS ret;
221 struct UsbHostRequest *reqEntry = NULL;
222
223 if ((msgQueue == NULL) || (request == NULL)) {
224 ret = HDF_ERR_INVALID_OBJECT;
225 HDF_LOGE("%{public}s:%{public}d invalid parameter", __func__, __LINE__);
226 return ret;
227 }
228
229 ret = OsalSemWait((struct OsalSem *)&msgQueue->sem, HDF_WAIT_FOREVER);
230 if (ret != HDF_SUCCESS) {
231 HDF_LOGE("%{public}s:%{public}d OsalSemWait failed, ret=%{public}d", __func__, __LINE__, ret);
232 goto ERROR;
233 }
234
235 OsalMutexLock((struct OsalMutex *)&msgQueue->mutex);
236 if (DListIsEmpty(&msgQueue->entry)) {
237 ret = HDF_SUCCESS;
238 OsalMutexUnlock((struct OsalMutex *)&msgQueue->mutex);
239 goto ERROR;
240 }
241 if (msgQueue->entry.next == NULL || msgQueue->entry.next->prev == NULL ||
242 msgQueue->entry.prev == NULL || msgQueue->entry.prev->next == NULL) {
243 ret = HDF_ERR_INVALID_OBJECT;
244 OsalMutexUnlock((struct OsalMutex *)&msgQueue->mutex);
245 goto ERROR;
246 }
247 reqEntry = DLIST_FIRST_ENTRY(&msgQueue->entry, struct UsbHostRequest, list);
248 if (reqEntry == NULL || reqEntry->list.prev == NULL || reqEntry->list.next == NULL ||
249 reqEntry->list.prev->next != &reqEntry->list || reqEntry->list.next->prev != &reqEntry->list) {
250 ret = HDF_ERR_INVALID_OBJECT;
251 HDF_LOGE("%{public}s:%{public}d list node is invalid", __func__, __LINE__);
252 OsalMutexUnlock((struct OsalMutex *)&msgQueue->mutex);
253 goto ERROR;
254 }
255 if (reqEntry->list.prev != NULL && reqEntry->list.next != NULL) {
256 DListRemove(&reqEntry->list);
257 } else {
258 HDF_LOGE("%{public}s: The node prev or next is NULL", __func__);
259 }
260 *request = (struct UsbHostRequest *)reqEntry;
261 OsalMutexUnlock((struct OsalMutex *)&msgQueue->mutex);
262
263 return HDF_SUCCESS;
264
265 ERROR:
266 *request = NULL;
267 return ret;
268 }
269
UsbIoStart(struct UsbInterfacePool * interfacePool)270 HDF_STATUS UsbIoStart(struct UsbInterfacePool *interfacePool)
271 {
272 struct OsalThreadParam threadCfg;
273 if (interfacePool == NULL) {
274 HDF_LOGE("%{public}s:%{public}d", __func__, __LINE__);
275 return HDF_ERR_INVALID_PARAM;
276 }
277
278 OsalMutexLock(&interfacePool->ioStopLock);
279 interfacePool->ioProcessStopStatus = USB_POOL_PROCESS_RUNNING;
280 interfacePool->ioRecvProcessStopStatus = USB_POOL_PROCESS_RUNNING;
281 OsalSemInit(&interfacePool->ioSem, 0);
282 OsalMutexUnlock(&interfacePool->ioStopLock);
283
284 /* create IoSendProcess thread */
285 HDF_STATUS ret = memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
286 if (ret != EOK) {
287 HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__);
288 return ret;
289 }
290 threadCfg.name = "usb io send process";
291 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
292 threadCfg.stackSize = USB_IO_SEND_PROCESS_STACK_SIZE;
293
294 ret = OsalThreadCreate(&interfacePool->ioSendProcess, (OsalThreadEntry)IoSendProcess, (void *)interfacePool);
295 if (ret != HDF_SUCCESS) {
296 HDF_LOGE("%{public}s:%{public}d OsalThreadCreate failed, ret=%{public}d ", __func__, __LINE__, ret);
297 return ret;
298 }
299
300 ret = OsalThreadStart(&interfacePool->ioSendProcess, &threadCfg);
301 if (ret != HDF_SUCCESS) {
302 HDF_LOGE("%{public}s:%{public}d OsalThreadStart failed, ret=%{public}d ", __func__, __LINE__, ret);
303 goto ERR_DESTROY_SEND;
304 }
305
306 /* create IoAsyncReceiveProcess thread */
307 (void)memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
308 threadCfg.name = "usb io async receive process";
309 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
310 threadCfg.stackSize = USB_IO_RECEIVE_PROCESS_STACK_SIZE;
311
312 ret = OsalThreadCreate(&interfacePool->ioAsyncReceiveProcess, (void *)IoAsyncReceiveProcess, (void *)interfacePool);
313 if (ret != HDF_SUCCESS) {
314 HDF_LOGE("%{public}s:%{public}d OsalThreadCreate failed, ret=%{public}d ", __func__, __LINE__, ret);
315 goto ERR_DESTROY_SEND;
316 }
317
318 ret = OsalThreadStart(&interfacePool->ioAsyncReceiveProcess, &threadCfg);
319 if (ret != HDF_SUCCESS) {
320 HDF_LOGE("%{public}s:%{public}d OsalThreadStart failed, ret=%{public}d ", __func__, __LINE__, ret);
321 goto ERR_DESTROY_RECV;
322 }
323
324 return HDF_SUCCESS;
325
326 ERR_DESTROY_SEND:
327 OsalThreadDestroy(&interfacePool->ioAsyncReceiveProcess);
328 ERR_DESTROY_RECV:
329 OsalThreadDestroy(&interfacePool->ioSendProcess);
330
331 return ret;
332 }
333
UsbIoRecvProcessStop(struct UsbInterfacePool * interfacePool)334 HDF_STATUS UsbIoRecvProcessStop(struct UsbInterfacePool *interfacePool)
335 {
336 if ((interfacePool == NULL) || (interfacePool->device == NULL) || (interfacePool->device->devHandle == NULL)) {
337 HDF_LOGE("%{public}s:%{public}d param is NULL", __func__, __LINE__);
338 return HDF_ERR_INVALID_PARAM;
339 }
340 if ((interfacePool->ioRecvProcessStopStatus != USB_POOL_PROCESS_STOPED)) {
341 OsalMutexLock(&interfacePool->ioStopLock);
342 interfacePool->ioRecvProcessStopStatus = USB_POOL_PROCESS_STOP;
343 OsalSemPost(&interfacePool->submitRequestQueue.sem);
344 OsalMutexUnlock(&interfacePool->ioStopLock);
345 }
346 return HDF_SUCCESS;
347 }
348
UsbIoStop(struct UsbInterfacePool * interfacePool)349 HDF_STATUS UsbIoStop(struct UsbInterfacePool *interfacePool)
350 {
351 if ((interfacePool == NULL) || (interfacePool->device == NULL) || (interfacePool->device->devHandle == NULL)) {
352 HDF_LOGE("%{public}s:%{public}d param is NULL", __func__, __LINE__);
353 return HDF_ERR_INVALID_PARAM;
354 }
355 if ((interfacePool->ioProcessStopStatus != USB_POOL_PROCESS_STOPED)) {
356 OsalMutexLock(&interfacePool->ioStopLock);
357 interfacePool->ioProcessStopStatus = USB_POOL_PROCESS_STOP;
358 OsalSemPost(&interfacePool->ioSem);
359 OsalSemPost(&interfacePool->submitRequestQueue.sem);
360 OsalMutexUnlock(&interfacePool->ioStopLock);
361
362 if (RawKillSignal(interfacePool->device->devHandle, interfacePool->ioProcessTid) != HDF_SUCCESS) {
363 HDF_LOGE(
364 "%{public}s:%{public}d RawKillSignal ioProcessTid=%{public}d failed",
365 __func__, __LINE__, interfacePool->ioProcessTid);
366 }
367 }
368 int32_t i = 0;
369 while (interfacePool->ioProcessStopStatus != USB_POOL_PROCESS_STOPED) {
370 i++;
371 OsalMSleep(USB_IO_SLEEP_MS_TIME);
372 if (i > USB_IO_STOP_WAIT_MAX_TIME) {
373 HDF_LOGD("%{public}s:%{public}d", __func__, __LINE__);
374 break;
375 }
376 }
377
378 HDF_STATUS ret = OsalThreadDestroy(&interfacePool->ioSendProcess);
379 if (ret != HDF_SUCCESS) {
380 HDF_LOGE("%{public}s:%{public}d OsalThreadDestroy failed, ret=%{public}d ", __func__, __LINE__, ret);
381 return ret;
382 }
383 ret = OsalThreadDestroy(&interfacePool->ioAsyncReceiveProcess);
384 if (ret != HDF_SUCCESS) {
385 HDF_LOGE("%{public}s:%{public}d OsalThreadDestroy failed, ret=%{public}d ", __func__, __LINE__, ret);
386 } else {
387 OsalSemDestroy(&interfacePool->ioSem);
388 }
389 return ret;
390 }
391
UsbIoSetRequestCompletionInfo(const void * requestArg)392 void UsbIoSetRequestCompletionInfo(const void *requestArg)
393 {
394 if (requestArg == NULL) {
395 HDF_LOGE("%{public}s:%{public}d parameter error. ", __func__, __LINE__);
396 return;
397 }
398
399 struct UsbHostRequest *hostRequest = (struct UsbHostRequest *)requestArg;
400 struct UsbIfRequest *requestObj = (struct UsbIfRequest *)hostRequest->privateObj;
401 if (requestObj == NULL) {
402 HDF_LOGE("%{public}s:%{public}d get request error. ", __func__, __LINE__);
403 return;
404 }
405 requestObj->request.compInfo.buffer = hostRequest->buffer;
406 requestObj->request.compInfo.length = hostRequest->length;
407 requestObj->request.compInfo.actualLength = (uint32_t)hostRequest->actualLength;
408 requestObj->request.compInfo.status = hostRequest->status;
409 requestObj->request.compInfo.userData = hostRequest->userData;
410 if ((hostRequest->requestType & USB_DDK_ENDPOINT_XFERTYPE_MASK) == USB_DDK_ENDPOINT_XFER_CONTROL) {
411 requestObj->request.compInfo.buffer = requestObj->request.compInfo.buffer + USB_RAW_CONTROL_SETUP_SIZE;
412 }
413
414 /* Fill in the request completion information. */
415 /* Call user callback function. */
416 if (hostRequest->userCallback) {
417 hostRequest->userCallback(&requestObj->request);
418 }
419
420 if (requestObj->isSyncReq) {
421 OsalSemPost(&hostRequest->sem);
422 }
423 }
424