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 "usbfn_io_mgr.h"
17
18 #define HDF_LOG_TAG usbfn_io_mgr
19
ReqToIoData(struct UsbFnRequest * req,struct IoData * ioData,uint32_t aio,uint32_t timeout)20 static int ReqToIoData(struct UsbFnRequest *req, struct IoData *ioData,
21 uint32_t aio, uint32_t timeout)
22 {
23 if (req == NULL || ioData == NULL) {
24 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
25 return HDF_ERR_INVALID_PARAM;
26 }
27 struct ReqList *reqList = (struct ReqList *) req;
28 ioData->aio = aio;
29 if (req->type == USB_REQUEST_TYPE_PIPE_WRITE) {
30 ioData->read = 0;
31 } else if (req->type == USB_REQUEST_TYPE_PIPE_READ) {
32 ioData->read = 1;
33 }
34 ioData->buf = reqList->buf;
35 ioData->len = req->length;
36 ioData->timeout = timeout;
37
38 return 0;
39 }
40
OpenEp0AndMapAddr(struct UsbFnFuncMgr * funcMgr)41 int OpenEp0AndMapAddr(struct UsbFnFuncMgr *funcMgr)
42 {
43 int ret;
44 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
45 funcMgr->fd = fnOps->openPipe(funcMgr->name, 0);
46 if (funcMgr->fd <= 0) {
47 HDF_LOGE("%s:%d openPipe failed", __func__, __LINE__);
48 return HDF_ERR_IO;
49 }
50
51 ret = fnOps->queueInit(funcMgr->fd);
52 if (ret) {
53 HDF_LOGE("%s:%d queueInit failed", __func__, __LINE__);
54 return HDF_ERR_IO;
55 }
56 return 0;
57 }
58
GetReqType(struct UsbHandleMgr * handle,uint8_t pipe)59 static UsbFnRequestType GetReqType(struct UsbHandleMgr *handle, uint8_t pipe)
60 {
61 int ret;
62 struct UsbFnPipeInfo info;
63 UsbFnRequestType type = USB_REQUEST_TYPE_INVALID;
64 if (pipe > 0) {
65 ret = UsbFnIoMgrInterfaceGetPipeInfo(&(handle->intfMgr->interface), pipe - 1, &info);
66 if (ret) {
67 HDF_LOGE("%s:%d UsbFnMgrInterfaceGetPipeInfo err", __func__, __LINE__);
68 type = USB_REQUEST_TYPE_INVALID;
69 }
70 if (info.dir == USB_PIPE_DIRECTION_IN) {
71 type = USB_REQUEST_TYPE_PIPE_WRITE;
72 } else if (info.dir == USB_PIPE_DIRECTION_OUT) {
73 type = USB_REQUEST_TYPE_PIPE_READ;
74 }
75 }
76 return type;
77 }
78
UsbFnIoMgrRequestAlloc(struct UsbHandleMgr * handle,uint8_t pipe,uint32_t len)79 struct UsbFnRequest *UsbFnIoMgrRequestAlloc(struct UsbHandleMgr *handle, uint8_t pipe, uint32_t len)
80 {
81 int ret;
82 int ep;
83 uint8_t *mapAddr = NULL;
84 struct UsbFnRequest *req = NULL;
85 struct ReqList *reqList = NULL;
86 struct UsbFnInterfaceMgr *intfMgr = handle->intfMgr;
87 struct UsbFnFuncMgr *funcMgr = intfMgr->funcMgr;
88 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
89 if (pipe == 0) {
90 if (funcMgr->fd <= 0) {
91 ret = OpenEp0AndMapAddr(funcMgr);
92 if (ret) {
93 return NULL;
94 }
95 }
96 ep = funcMgr->fd;
97 } else {
98 ep = handle->fds[pipe - 1];
99 }
100 mapAddr = fnOps->mapAddr(ep, len);
101 if (mapAddr == NULL) {
102 HDF_LOGE("%s:%d mapAddr failed", __func__, __LINE__);
103 return NULL;
104 }
105
106 reqList = UsbFnMemCalloc(sizeof(struct ReqList));
107 if (reqList == NULL) {
108 HDF_LOGE("%s:%d UsbFnMemCalloc err", __func__, __LINE__);
109 return NULL;
110 }
111 req = &reqList->req;
112
113 if (pipe == 0) {
114 DListInsertTail(&reqList->entry, &funcMgr->reqEntry);
115 } else {
116 DListInsertTail(&reqList->entry, &handle->reqEntry);
117 }
118 reqList->handle = handle;
119 reqList->fd = ep;
120 reqList->buf = (uint32_t)mapAddr;
121 reqList->pipe = pipe;
122 reqList->bufLen = len;
123 req->length = len;
124 req->obj = handle->intfMgr->interface.object;
125 req->buf = mapAddr;
126 req->type = GetReqType(handle, pipe);
127
128 return req;
129 }
130
UsbFnIoMgrRequestFree(struct UsbFnRequest * req)131 int UsbFnIoMgrRequestFree(struct UsbFnRequest *req)
132 {
133 struct GenericMemory mem;
134 int ret;
135 if (req == NULL) {
136 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
137 return HDF_ERR_INVALID_PARAM;
138 }
139
140 struct ReqList *reqList = (struct ReqList *) req;
141 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
142
143 ret = fnOps->unmapAddr(req->buf, reqList->bufLen);
144 if (ret) {
145 HDF_LOGE("%s:%d ummapAddr failed, ret=%d ", __func__, __LINE__, ret);
146 return HDF_ERR_DEVICE_BUSY;
147 }
148 mem.size = reqList->bufLen;
149 mem.buf = (uint32_t)req->buf;
150 ret = fnOps->releaseBuf(reqList->fd, &mem);
151 if (ret) {
152 HDF_LOGE("%s:%d releaseBuf err", __func__, __LINE__);
153 return HDF_ERR_INVALID_PARAM;
154 }
155
156 DListRemove(&reqList->entry);
157 UsbFnMemFree(reqList);
158 return 0;
159 }
160
UsbFnIoMgrRequestSubmitAsync(struct UsbFnRequest * req)161 int UsbFnIoMgrRequestSubmitAsync(struct UsbFnRequest *req)
162 {
163 int ret;
164 struct IoData ioData = {0};
165 struct ReqList *reqList = NULL;
166 if (req == NULL) {
167 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
168 return HDF_ERR_INVALID_PARAM;
169 }
170 reqList = (struct ReqList *) req;
171 if (ReqToIoData(req, &ioData, 1, 0)) {
172 return HDF_ERR_IO;
173 }
174 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
175 ret = fnOps->pipeIo(reqList->fd, &ioData);
176
177 return ret;
178 }
179
UsbFnIoMgrRequestCancel(struct UsbFnRequest * req)180 int UsbFnIoMgrRequestCancel(struct UsbFnRequest *req)
181 {
182 int ret;
183 struct IoData ioData = {0};
184 struct ReqList *reqList = NULL;
185 if (req == NULL) {
186 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
187 return HDF_ERR_INVALID_PARAM;
188 }
189 reqList = (struct ReqList *) req;
190 if (ReqToIoData(req, &ioData, 1, 0)) {
191 return HDF_ERR_IO;
192 }
193 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
194 ret = fnOps->cancelIo(reqList->fd, &ioData);
195
196 return ret;
197 }
198
UsbFnIoMgrRequestGetStatus(struct UsbFnRequest * req,UsbRequestStatus * status)199 int UsbFnIoMgrRequestGetStatus(struct UsbFnRequest *req, UsbRequestStatus *status)
200 {
201 struct IoData ioData = {0};
202 struct ReqList *reqList;
203 if (req == NULL) {
204 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
205 return HDF_ERR_INVALID_PARAM;
206 }
207 reqList = (struct ReqList *) req;
208 if (ReqToIoData(req, &ioData, 1, 0)) {
209 return HDF_ERR_IO;
210 }
211 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
212 *status = -(fnOps->getReqStatus(reqList->fd, &ioData));
213
214 return 0;
215 }
216
UsbFnIoMgrRequestSubmitSync(struct UsbFnRequest * req,uint32_t timeout)217 int UsbFnIoMgrRequestSubmitSync(struct UsbFnRequest *req, uint32_t timeout)
218 {
219 int ret;
220 struct IoData ioData = {0};
221 struct ReqList *reqList;
222
223 if (req == NULL) {
224 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
225 return HDF_ERR_INVALID_PARAM;
226 }
227 reqList = (struct ReqList *) req;
228 if (ReqToIoData(req, &ioData, 0, timeout)) {
229 return HDF_ERR_IO;
230 }
231 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
232 ret = fnOps->pipeIo(reqList->fd, &ioData);
233 if (ret > 0) {
234 req->status = USB_REQUEST_COMPLETED;
235 req->actual = ret;
236 return 0;
237 }
238
239 return ret;
240 }
241
HandleInit(struct UsbHandleMgr * handle,struct UsbFnInterfaceMgr * interfaceMgr)242 static int HandleInit(struct UsbHandleMgr *handle, struct UsbFnInterfaceMgr *interfaceMgr)
243 {
244 int ret;
245 uint32_t i, j;
246 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
247
248 DListHeadInit(&handle->reqEntry);
249 handle->numFd = interfaceMgr->interface.info.numPipes;
250 for (i = 0; i < handle->numFd; i++) {
251 handle->fds[i] = fnOps->openPipe(interfaceMgr->funcMgr->name, interfaceMgr->startEpId + i);
252 if (handle->fds[i] <= 0) {
253 return HDF_ERR_IO;
254 }
255
256 ret = fnOps->queueInit(handle->fds[i]);
257 if (ret) {
258 HDF_LOGE("%s: queueInit failed ret = %d", __func__, ret);
259 return HDF_ERR_IO;
260 }
261
262 handle->reqEvent[i] = UsbFnMemCalloc(sizeof(struct UsbFnReqEvent) * MAX_REQUEST);
263 if (handle->reqEvent[i] == NULL) {
264 HDF_LOGE("%s: UsbFnMemCalloc failed", __func__);
265 goto FREE_EVENT;
266 }
267 }
268 handle->intfMgr = interfaceMgr;
269 return 0;
270
271 FREE_EVENT:
272 for (j = 0; j < i; j++) {
273 UsbFnMemFree(handle->reqEvent[j]);
274 }
275 return HDF_ERR_IO;
276 }
277
UsbFnIoMgrInterfaceOpen(struct UsbFnInterface * interface)278 struct UsbHandleMgr *UsbFnIoMgrInterfaceOpen(struct UsbFnInterface *interface)
279 {
280 int ret;
281 if (interface == NULL) {
282 return NULL;
283 }
284 struct UsbFnInterfaceMgr *interfaceMgr = (struct UsbFnInterfaceMgr *)interface;
285 if (interfaceMgr->isOpen) {
286 HDF_LOGE("%s: interface has opened", __func__);
287 return NULL;
288 }
289 struct UsbHandleMgr *handle = UsbFnMemCalloc(sizeof(struct UsbHandleMgr));
290 if (handle == NULL) {
291 return NULL;
292 }
293
294 ret = HandleInit(handle, interfaceMgr);
295 if (ret) {
296 HDF_LOGE("%s: HandleInit failed", __func__);
297 UsbFnMemFree(handle);
298 return NULL;
299 }
300
301 interfaceMgr->isOpen = true;
302 interfaceMgr->handle = handle;
303 return handle;
304 }
305
UsbFnIoMgrInterfaceClose(struct UsbHandleMgr * handle)306 int UsbFnIoMgrInterfaceClose(struct UsbHandleMgr *handle)
307 {
308 int ret;
309 uint32_t i;
310 if (handle == NULL) {
311 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
312 return HDF_ERR_INVALID_PARAM;
313 }
314 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
315 struct UsbFnInterfaceMgr *interfaceMgr = handle->intfMgr;
316
317 if (interfaceMgr == NULL || interfaceMgr->isOpen == false) {
318 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
319 return HDF_ERR_INVALID_PARAM;
320 }
321 for (i = 0; i < handle->numFd; i++) {
322 ret = fnOps->queueDel(handle->fds[i]);
323 if (ret) {
324 HDF_LOGE("%s:%d queueDel failed, ret=%d ", __func__, __LINE__, ret);
325 return HDF_ERR_DEVICE_BUSY;
326 }
327
328 ret = fnOps->closePipe(handle->fds[i]);
329 if (ret) {
330 HDF_LOGE("%s:%d closePipe failed, ret=%d ", __func__, __LINE__, ret);
331 return HDF_ERR_DEVICE_BUSY;
332 }
333 handle->fds[i] = -1;
334 UsbFnMemFree(handle->reqEvent[i]);
335 }
336
337 UsbFnMemFree(handle);
338 interfaceMgr->isOpen = false;
339 interfaceMgr->handle = NULL;
340 return 0;
341 }
342
UsbFnIoMgrInterfaceGetPipeInfo(struct UsbFnInterface * interface,uint8_t pipeId,struct UsbFnPipeInfo * info)343 int UsbFnIoMgrInterfaceGetPipeInfo(struct UsbFnInterface *interface,
344 uint8_t pipeId, struct UsbFnPipeInfo *info)
345 {
346 int ret;
347 int fd;
348 if (info == NULL || interface == NULL || pipeId >= interface->info.numPipes) {
349 HDF_LOGE("%s:%d INVALID_PARAM", __func__, __LINE__);
350 return HDF_ERR_INVALID_PARAM;
351 }
352 struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
353 struct UsbFnInterfaceMgr *interfaceMgr = (struct UsbFnInterfaceMgr *)interface;
354 if (interfaceMgr->isOpen) {
355 fd = interfaceMgr->handle->fds[pipeId];
356 ret = fnOps->getPipeInfo(fd, info);
357 if (ret) {
358 HDF_LOGE("%s: getPipeInfo failed", __func__);
359 return HDF_ERR_DEVICE_BUSY;
360 }
361 } else {
362 fd = fnOps->openPipe(interfaceMgr->funcMgr->name, interfaceMgr->startEpId + pipeId);
363 if (fd <= 0) {
364 HDF_LOGE("%s: openPipe failed", __func__);
365 return HDF_ERR_IO;
366 }
367 ret = fnOps->getPipeInfo(fd, info);
368 if (ret) {
369 fnOps->closePipe(fd);
370 HDF_LOGE("%s: getPipeInfo failed", __func__);
371 return HDF_ERR_DEVICE_BUSY;
372 }
373 fnOps->closePipe(fd);
374 }
375
376 info->id = pipeId;
377 return ret;
378 }
379