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