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