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