• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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