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