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