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 "cdcecm.h"
17 #include <unistd.h>
18 #include "device_resource_if.h"
19 #include "hdf_base.h"
20 #include "hdf_device_object.h"
21 #include "hdf_log.h"
22 #include "osal_mem.h"
23 #include "osal_sem.h"
24 #include "osal_time.h"
25 #include "securec.h"
26 #include "usbfn_device.h"
27 #include "usbfn_interface.h"
28 #include "usbfn_request.h"
29
30 #define HDF_LOG_TAG cdc_ecm
31 #define UDC_NAME "invalid_udc_name"
32
33 #define QUEUE_SIZE 8
34 #define WRITE_BUF_SIZE 8192
35 #define READ_BUF_SIZE 8192
36 #define ECM_STATUS_BYTECOUNT 16
37 #define ECM_BIT 9728000
38 #define USBCDC_LEN 2
39 #define RECEIVE_ALL_EVENTS 0xff
40 static const int32_t WAIT_UDC_MAX_LOOP = 3;
41 static const uint32_t WAIT_UDC_TIME = 100000;
42
43 static int32_t EcmInit(struct HdfDeviceObject *device);
44 static int32_t EcmRelease(struct HdfDeviceObject *device);
45
EcmBitrate(void)46 static inline unsigned EcmBitrate(void)
47 {
48 return ECM_BIT;
49 }
50
51 /* Usb Serial Related Functions */
UsbEcmStartTx(struct UsbEcm * port)52 static int32_t UsbEcmStartTx(struct UsbEcm *port)
53 {
54 struct DListHead *pool = &port->writePool;
55 if (port->ecm == NULL) {
56 return HDF_SUCCESS;
57 }
58
59 while (!port->writeBusy && !DListIsEmpty(pool)) {
60 struct UsbFnRequest *req = NULL;
61 uint32_t len;
62 if (port->writeStarted >= QUEUE_SIZE) {
63 break;
64 }
65 req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list);
66 OsalMutexLock(&port->lockWriteFifo);
67 len = DataFifoRead(&port->writeFifo, req->buf, port->ecm->dataInPipe.maxPacketSize);
68 OsalMutexUnlock(&port->lockWriteFifo);
69 if (len == 0) {
70 break;
71 }
72 req->length = len;
73 if (req->list.prev != NULL && req->list.next != NULL) {
74 DListRemove(&req->list);
75 } else {
76 HDF_LOGE("%{public}s: The node prev or next is NULL", __func__);
77 }
78 port->writeBusy = true;
79 int32_t ret = UsbFnSubmitRequestAsync(req);
80 port->writeBusy = false;
81 if (ret != HDF_SUCCESS) {
82 HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret);
83 DListInsertTail(&req->list, pool);
84 break;
85 }
86 port->writeStarted++;
87 /* if ecm is disconnect, abort immediately */
88 if (port->ecm == NULL) {
89 break;
90 }
91 }
92 return HDF_SUCCESS;
93 }
94
UsbEcmStartRx(struct UsbEcm * port)95 static uint32_t UsbEcmStartRx(struct UsbEcm *port)
96 {
97 struct DListHead *pool = &port->readPool;
98 struct UsbEcmPipe *out = &port->ecm->dataOutPipe;
99
100 while (!DListIsEmpty(pool)) {
101 struct UsbFnRequest *req = NULL;
102 int32_t ret;
103
104 if (port->readStarted >= QUEUE_SIZE) {
105 break;
106 }
107
108 req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list);
109 if (req->list.prev != NULL && req->list.next != NULL) {
110 DListRemove(&req->list);
111 } else {
112 HDF_LOGE("%{public}s: The node prev or next is NULL", __func__);
113 }
114 req->length = out->maxPacketSize;
115 ret = UsbFnSubmitRequestAsync(req);
116 if (ret != HDF_SUCCESS) {
117 HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret);
118 DListInsertTail(&req->list, pool);
119 break;
120 }
121 port->readStarted++;
122 /* if ecm is disconnect, abort immediately */
123 if (port->ecm == NULL) {
124 break;
125 }
126 }
127 return port->readStarted;
128 }
129
UsbEcmRxPush(struct UsbEcm * port)130 static void UsbEcmRxPush(struct UsbEcm *port)
131 {
132 struct DListHead *queue = &port->readQueue;
133 bool disconnect = false;
134
135 while (!DListIsEmpty(queue)) {
136 struct UsbFnRequest *req;
137
138 req = DLIST_FIRST_ENTRY(queue, struct UsbFnRequest, list);
139 switch (req->status) {
140 case USB_REQUEST_NO_DEVICE:
141 disconnect = true;
142 HDF_LOGV("%{public}s: the device is disconnected", __func__);
143 break;
144 case USB_REQUEST_COMPLETED:
145 break;
146 default:
147 HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status);
148 break;
149 }
150 if (req->actual && req->status == 0) {
151 uint32_t size = req->actual;
152 uint8_t *data = req->buf;
153 OsalMutexLock(&port->lockReadFifo);
154 if (DataFifoIsFull(&port->readFifo)) {
155 DataFifoSkip(&port->readFifo, size);
156 }
157 uint32_t count = DataFifoWrite(&port->readFifo, data, size);
158 if (count != size) {
159 HDF_LOGW("%{public}s: write %{public}u less than expected %{public}u", __func__, count, size);
160 }
161 OsalMutexUnlock(&port->lockReadFifo);
162 }
163 if (req->list.prev != NULL && req->list.next != NULL) {
164 DListRemove(&req->list);
165 } else {
166 HDF_LOGE("%{public}s: The node prev or next is NULL", __func__);
167 }
168 DListInsertTail(&req->list, &port->readPool);
169 port->readStarted--;
170 }
171
172 if (!disconnect && port->ecm) {
173 UsbEcmStartRx(port);
174 }
175 }
176
UsbEcmFreeRequests(const struct DListHead * head,int32_t * allocated)177 static void UsbEcmFreeRequests(const struct DListHead *head, int32_t *allocated)
178 {
179 struct UsbFnRequest *req = NULL;
180 while (!DListIsEmpty(head)) {
181 req = DLIST_FIRST_ENTRY(head, struct UsbFnRequest, list);
182 if (req->list.prev != NULL && req->list.next != NULL) {
183 DListRemove(&req->list);
184 } else {
185 HDF_LOGE("%{public}s: The node prev or next is NULL", __func__);
186 }
187 (void)UsbFnFreeRequest(req);
188 if (allocated) {
189 (*allocated)--;
190 }
191 }
192 }
193
UsbEcmReadComplete(uint8_t pipe,struct UsbFnRequest * req)194 static void UsbEcmReadComplete(uint8_t pipe, struct UsbFnRequest *req)
195 {
196 struct UsbEcm *port = (struct UsbEcm *)req->context;
197 OsalMutexLock(&port->lock);
198 DListInsertTail(&req->list, &port->readQueue);
199 UsbEcmRxPush(port);
200 OsalMutexUnlock(&port->lock);
201 }
202
UsbEcmWriteComplete(uint8_t pipe,struct UsbFnRequest * req)203 static void UsbEcmWriteComplete(uint8_t pipe, struct UsbFnRequest *req)
204 {
205 struct UsbEcm *port = (struct UsbEcm *)req->context;
206 OsalMutexLock(&port->lock);
207 DListInsertTail(&req->list, &port->writePool);
208 port->writeStarted--;
209
210 switch (req->status) {
211 case USB_REQUEST_COMPLETED:
212 UsbEcmStartTx(port);
213 break;
214 case USB_REQUEST_NO_DEVICE:
215 HDF_LOGV("%{public}s: ecm device was disconnected", __func__);
216 break;
217 default:
218 HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status);
219 break;
220 }
221 OsalMutexUnlock(&port->lock);
222 }
223
UsbEcmAllocReadRequests(struct UsbEcm * port,int32_t num)224 static int32_t UsbEcmAllocReadRequests(struct UsbEcm *port, int32_t num)
225 {
226 struct UsbEcmDevice *ecm = port->ecm;
227 struct DListHead *head = &port->readPool;
228 struct UsbFnRequest *req = NULL;
229 int32_t i;
230
231 for (i = 0; i < num; i++) {
232 req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataOutPipe.id, ecm->dataOutPipe.maxPacketSize);
233 if (!req) {
234 return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS;
235 }
236
237 req->complete = UsbEcmReadComplete;
238 req->context = port;
239 DListInsertTail(&req->list, head);
240 port->readAllocated++;
241 }
242 return HDF_SUCCESS;
243 }
244
UsbEcmAllocWriteRequests(struct UsbEcm * port,int32_t num)245 static int32_t UsbEcmAllocWriteRequests(struct UsbEcm *port, int32_t num)
246 {
247 struct UsbEcmDevice *ecm = port->ecm;
248 struct DListHead *head = &port->writePool;
249 struct UsbFnRequest *req = NULL;
250 int32_t i;
251
252 for (i = 0; i < num; i++) {
253 req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataInPipe.id, ecm->dataInPipe.maxPacketSize);
254 if (!req) {
255 return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS;
256 }
257
258 req->complete = UsbEcmWriteComplete;
259 req->context = port;
260 DListInsertTail(&req->list, head);
261 port->writeAllocated++;
262 }
263 return HDF_SUCCESS;
264 }
265
UsbEcmStartIo(struct UsbEcm * port)266 static int32_t UsbEcmStartIo(struct UsbEcm *port)
267 {
268 struct DListHead *head = &port->readPool;
269 int32_t ret = HDF_SUCCESS;
270 uint32_t started;
271
272 /* allocate requests for read/write */
273 if (port->readAllocated == 0) {
274 ret = UsbEcmAllocReadRequests(port, QUEUE_SIZE);
275 if (ret != HDF_SUCCESS) {
276 return ret;
277 }
278 }
279 if (port->writeAllocated == 0) {
280 ret = UsbEcmAllocWriteRequests(port, QUEUE_SIZE);
281 if (ret != HDF_SUCCESS) {
282 UsbEcmFreeRequests(head, &port->readAllocated);
283 return ret;
284 }
285 }
286
287 started = UsbEcmStartRx(port);
288 if (started) {
289 UsbEcmStartTx(port);
290 } else {
291 UsbEcmFreeRequests(head, &port->readAllocated);
292 UsbEcmFreeRequests(&port->writePool, &port->writeAllocated);
293 ret = HDF_ERR_IO;
294 }
295
296 return ret;
297 }
298
299
UsbEcmAllocFifo(struct DataFifo * fifo,uint32_t size)300 static int32_t UsbEcmAllocFifo(struct DataFifo *fifo, uint32_t size)
301 {
302 if (!DataFifoIsInitialized(fifo)) {
303 void *data = OsalMemAlloc(size);
304 if (data == NULL) {
305 HDF_LOGE("%{public}s: allocate fifo data buffer failed", __func__);
306 return HDF_ERR_MALLOC_FAIL;
307 }
308 DataFifoInit(fifo, size, data);
309 }
310 return HDF_SUCCESS;
311 }
312
UsbEcmOpen(struct UsbEcm * port)313 static int32_t UsbEcmOpen(struct UsbEcm *port)
314 {
315 int32_t ret;
316
317 if (port == NULL) {
318 return HDF_ERR_INVALID_PARAM;
319 }
320
321 OsalMutexLock(&port->lock);
322 ret = UsbEcmAllocFifo(&port->writeFifo, WRITE_BUF_SIZE);
323 if (ret != HDF_SUCCESS) {
324 HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
325 goto OUT;
326 }
327 ret = UsbEcmAllocFifo(&port->readFifo, READ_BUF_SIZE);
328 if (ret != HDF_SUCCESS) {
329 HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
330 goto OUT;
331 }
332 DataFifoReset(&port->writeFifo);
333 DataFifoReset(&port->readFifo);
334
335 if (port->refCount++) {
336 HDF_LOGE("%{public}s: refCount failed", __func__);
337 goto OUT;
338 }
339
340 /* the ecm is enabled, start the io stream */
341 if (port->ecm) {
342 HDF_LOGD("%{public}s: start usb io", __func__);
343 ret = UsbEcmStartIo(port);
344 if (ret != HDF_SUCCESS) {
345 goto OUT;
346 }
347 }
348
349 OUT:
350 OsalMutexUnlock(&port->lock);
351 return HDF_SUCCESS;
352 }
353
UsbEcmClose(struct UsbEcm * port)354 static int32_t UsbEcmClose(struct UsbEcm *port)
355 {
356 if (port == NULL) {
357 return HDF_ERR_INVALID_PARAM;
358 }
359
360 OsalMutexLock(&port->lock);
361 if (port->refCount != 1) {
362 --port->refCount;
363 goto OUT;
364 }
365
366 HDF_LOGD("%{public}s: close usb serial", __func__);
367
368 DataFifoReset(&port->writeFifo);
369 DataFifoReset(&port->readFifo);
370 port->refCount = 0;
371
372 OUT:
373 OsalMutexUnlock(&port->lock);
374 return HDF_SUCCESS;
375 }
376
UsbEcmRead(struct UsbEcm * port,struct HdfSBuf * reply)377 static int32_t UsbEcmRead(struct UsbEcm *port, struct HdfSBuf *reply)
378 {
379 uint32_t len;
380 int32_t ret = HDF_SUCCESS;
381 uint8_t *buf = NULL;
382 OsalMutexLock(&port->lock);
383 OsalMutexLock(&port->lockReadFifo);
384 if (DataFifoIsEmpty(&port->readFifo)) {
385 OsalMutexUnlock(&port->lockReadFifo);
386 OsalMutexUnlock(&port->lock);
387 return 0;
388 }
389
390 buf = (uint8_t *)OsalMemCalloc(DataFifoLen(&port->readFifo) + sizeof(uint32_t));
391 if (buf == NULL) {
392 HDF_LOGE("%{public}s: OsalMemCalloc error", __func__);
393 OsalMutexUnlock(&port->lockReadFifo);
394 OsalMutexUnlock(&port->lock);
395 return HDF_ERR_MALLOC_FAIL;
396 }
397
398 len = DataFifoRead(&port->readFifo, buf, DataFifoLen(&port->readFifo));
399 if (len == 0) {
400 HDF_LOGE("%{public}s: no data", __func__);
401 ret = HDF_ERR_IO;
402 OsalMutexUnlock(&port->lockReadFifo);
403 goto OUT;
404 }
405 OsalMutexUnlock(&port->lockReadFifo);
406
407 bool bufok = HdfSbufWriteBuffer(reply, (const void *)buf, len);
408 if (!bufok) {
409 HDF_LOGE("UsbEcmRead HdfSbufWriteBuffer error");
410 ret = HDF_ERR_IO;
411 goto OUT;
412 }
413
414 OUT:
415 if (port->ecm) {
416 UsbEcmStartRx(port);
417 }
418 OsalMemFree(buf);
419 OsalMutexUnlock(&port->lock);
420 return ret;
421 }
422
UsbEcmWrite(struct UsbEcm * port,struct HdfSBuf * data)423 static int32_t UsbEcmWrite(struct UsbEcm *port, struct HdfSBuf *data)
424 {
425 uint32_t size = 0;
426 uint8_t *buf = NULL;
427
428 if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) {
429 HDF_LOGE("UsbEcmWrite HdfSbufReadBuffer err");
430 return HDF_ERR_IO;
431 }
432
433 OsalMutexLock(&port->lock);
434 if (size > 0 && buf != NULL) {
435 OsalMutexLock(&port->lockWriteFifo);
436 size = DataFifoWrite(&port->writeFifo, buf, size);
437 OsalMutexUnlock(&port->lockWriteFifo);
438 }
439 if (port->ecm) {
440 UsbEcmStartTx(port);
441 }
442 OsalMutexUnlock(&port->lock);
443 return HDF_SUCCESS;
444 }
445
UsbFnNotifyRequest(struct UsbFnRequest * req,struct UsbEcmDevice * ecm)446 void UsbFnNotifyRequest(struct UsbFnRequest *req, struct UsbEcmDevice *ecm)
447 {
448 int32_t status;
449 ecm->notifyReq = NULL;
450 status = UsbFnSubmitRequestAsync(req);
451 if (status < 0) {
452 ecm->notifyReq = req;
453 HDF_LOGD("notify --> %{public}d", status);
454 }
455 }
456
EcmDoNotify(struct UsbEcmDevice * ecm)457 static void EcmDoNotify(struct UsbEcmDevice *ecm)
458 {
459 struct UsbFnRequest *req = ecm->notifyReq;
460 struct UsbCdcNotification *event = NULL;
461 uint32_t *data = NULL;
462
463 if (!req) {
464 return;
465 }
466 ecm->isOpen = true;
467 event = (struct UsbCdcNotification *)req->buf;
468 if (event == NULL) {
469 return;
470 }
471 switch (ecm->notifyState) {
472 case ECM_NOTIFY_NONE:
473 return;
474
475 case ECM_NOTIFY_CONNECT:
476 event->bNotificationType = USB_DDK_CDC_NOTIFY_NETWORK_CONNECTION;
477 if (ecm->isOpen) {
478 event->wValue = CPU_TO_LE16(1);
479 } else {
480 event->wValue = CPU_TO_LE16(0);
481 }
482 event->wLength = 0;
483 req->length = sizeof(*event);
484
485 HDF_LOGD("notify connect %{public}s", ecm->isOpen ? "true" : "false");
486 ecm->notifyState = ECM_NOTIFY_SPEED;
487 break;
488
489 case ECM_NOTIFY_SPEED:
490 event->bNotificationType = USB_DDK_CDC_NOTIFY_SPEED_CHANGE;
491 event->wValue = CPU_TO_LE16(0);
492 event->wLength = CPU_TO_LE16(0x08);
493 req->length = ECM_STATUS_BYTECOUNT;
494
495 /* SPEED_CHANGE data is up/down speeds in bits/sec */
496 data = (uint32_t *)((char *)req->buf + sizeof(*event));
497 data[0] = CPU_TO_LE32(EcmBitrate());
498 data[1] = data[0];
499
500 HDF_LOGD("notify speed %{public}d", EcmBitrate());
501 ecm->notifyState = ECM_NOTIFY_NONE;
502 break;
503
504 default:
505 break;
506 }
507 event->bmRequestType = 0xA1;
508 event->wIndex = CPU_TO_LE16(ecm->ctrlId);
509 UsbFnNotifyRequest(req, ecm);
510 }
511
EcmNotifyComplete(uint8_t pipe,struct UsbFnRequest * req)512 static void EcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req)
513 {
514 struct UsbEcmDevice *ecm = req->context;
515 struct UsbCdcNotification *event = req->buf;
516 ecm->notifyReq = req;
517 if (req->status == 0) {
518 EcmDoNotify(ecm);
519 } else {
520 HDF_LOGD("event %{public}d --> %{public}d", event->bNotificationType, req->status);
521 }
522 }
523
EcmSetup(const struct UsbEcmDevice * ecm,const struct UsbFnCtrlRequest * ctrl)524 static int32_t EcmSetup(const struct UsbEcmDevice *ecm, const struct UsbFnCtrlRequest *ctrl)
525 {
526 struct UsbFnRequest *req = ecm->ep0Req;
527 int32_t ret = -1;
528 uint16_t index = LE16_TO_CPU(ctrl->index);
529 uint16_t value = LE16_TO_CPU(ctrl->value);
530 uint16_t length = LE16_TO_CPU(ctrl->length);
531
532 switch ((ctrl->reqType << 0x08) | ctrl->request) {
533 case ((USB_DDK_DIR_OUT | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE) << 0x08) |
534 USB_DDK_CDC_SET_ETHERNET_PACKET_FILTER:
535 if (length != 0 || index != ecm->ctrlId) {
536 break;
537 }
538 HDF_LOGD("packet filter %{public}02x", value);
539 ret = 0;
540 break;
541
542 default:
543 HDF_LOGW(
544 "invalid control req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}hu",
545 ctrl->reqType, ctrl->request, value, index, length);
546 }
547
548 if (ret >= 0) {
549 HDF_LOGD("ecm req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}d",
550 ctrl->reqType, ctrl->request, value, index, length);
551 req->length = (uint32_t)ret;
552 ret = UsbFnSubmitRequestSync(req, 0);
553 if (ret < 0) {
554 HDF_LOGD("ecm req %{public}02x.%{public}02x response err %{public}d", ctrl->reqType, ctrl->request, ret);
555 }
556 }
557
558 return value;
559 }
560
EcmDeviceDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)561 static int32_t EcmDeviceDispatch(
562 struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
563 {
564 struct UsbEcmDevice *ecm = NULL;
565 struct UsbEcm *port = NULL;
566 int32_t ret;
567 if (client == NULL || client->device == NULL || client->device->service == NULL) {
568 HDF_LOGE("%{public}s: client is NULL", __func__);
569 return HDF_ERR_INVALID_OBJECT;
570 }
571 if (data == NULL || reply == NULL) {
572 HDF_LOGE("%{public}s: data or reply is NULL", __func__);
573 return HDF_ERR_INVALID_OBJECT;
574 }
575
576 if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) {
577 HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__);
578 return HDF_ERR_INVALID_PARAM;
579 }
580
581 switch (cmd) {
582 case USB_ECM_INIT:
583 return EcmInit(client->device);
584 case USB_ECM_RELEASE:
585 return EcmRelease(client->device);
586 default:
587 break;
588 }
589 ecm = (struct UsbEcmDevice *)client->device->service;
590 port = ecm->port;
591 if (port == NULL) {
592 return HDF_ERR_IO;
593 }
594 OsalMutexLock(&port->lockRW);
595 switch (cmd) {
596 case USB_ECM_OPEN:
597 ret = UsbEcmOpen(port);
598 break;
599 case USB_ECM_CLOSE:
600 ret = UsbEcmClose(port);
601 break;
602 case USB_ECM_READ:
603 ret = UsbEcmRead(port, reply);
604 break;
605 case USB_ECM_WRITE:
606 ret = UsbEcmWrite(port, data);
607 break;
608 default:
609 ret = HDF_ERR_NOT_SUPPORT;
610 break;
611 }
612 OsalMutexUnlock(&port->lockRW);
613 return ret;
614 }
615
EcmEnable(struct UsbEcmDevice * ecm)616 static int32_t EcmEnable(struct UsbEcmDevice *ecm)
617 {
618 (void)ecm;
619 return HDF_SUCCESS;
620 }
621
EcmDisable(const struct UsbEcmDevice * ecm)622 static void EcmDisable(const struct UsbEcmDevice *ecm)
623 {
624 (void)ecm;
625 return;
626 }
627
UsbEcmEventCallback(struct UsbFnEvent * event)628 static void UsbEcmEventCallback(struct UsbFnEvent *event)
629 {
630 struct UsbEcmDevice *ecm = NULL;
631
632 if (event == NULL || event->context == NULL) {
633 HDF_LOGE("%{public}s: event is null", __func__);
634 return;
635 }
636
637 ecm = (struct UsbEcmDevice *)event->context;
638 switch (event->type) {
639 case USBFN_STATE_BIND:
640 HDF_LOGI("%{public}s: receive bind event", __func__);
641 break;
642 case USBFN_STATE_UNBIND:
643 HDF_LOGI("%{public}s: receive unbind event", __func__);
644 break;
645 case USBFN_STATE_ENABLE:
646 HDF_LOGI("%{public}s: receive enable event", __func__);
647 EcmEnable(ecm);
648 break;
649 case USBFN_STATE_DISABLE:
650 HDF_LOGI("%{public}s: receive disable event", __func__);
651 EcmDisable(ecm);
652 break;
653 case USBFN_STATE_SETUP:
654 HDF_LOGI("%{public}s: receive setup event", __func__);
655 if (event->setup != NULL) {
656 EcmSetup(ecm, event->setup);
657 }
658 break;
659 case USBFN_STATE_SUSPEND:
660 HDF_LOGI("%{public}s: receive suspend event", __func__);
661 break;
662 case USBFN_STATE_RESUME:
663 HDF_LOGI("%{public}s: receive resume event", __func__);
664 break;
665 default:
666 break;
667 }
668 }
669
EcmAllocNotifyRequest(struct UsbEcmDevice * ecm)670 static int32_t EcmAllocNotifyRequest(struct UsbEcmDevice *ecm)
671 {
672 /* allocate notification request */
673 ecm->notifyReq =
674 UsbFnAllocRequest(ecm->ctrlIface.handle, ecm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN);
675 if (ecm->notifyReq == NULL) {
676 HDF_LOGE("%{public}s: allocate notify request failed", __func__);
677 return HDF_FAILURE;
678 }
679 ecm->notifyReq->complete = EcmNotifyComplete;
680 ecm->notifyReq->context = ecm;
681
682 return HDF_SUCCESS;
683 }
684
EcmAllocEp0Request(struct UsbEcmDevice * ecm)685 static int32_t EcmAllocEp0Request(struct UsbEcmDevice *ecm)
686 {
687 /* allocate notification request */
688 ecm->ep0Req = UsbFnAllocCtrlRequest(ecm->ctrlIface.handle, ECM_STATUS_BYTECOUNT);
689 if (ecm->ep0Req == NULL) {
690 HDF_LOGE("%{public}s: allocate ep0Req request failed", __func__);
691 return HDF_FAILURE;
692 }
693 return HDF_SUCCESS;
694 }
695
EcmParseEachPipe(struct UsbEcmDevice * ecm,struct UsbEcmInterface * iface)696 static int32_t EcmParseEachPipe(struct UsbEcmDevice *ecm, struct UsbEcmInterface *iface)
697 {
698 struct UsbFnInterface *fnIface = iface->fn;
699 uint32_t repetIdx = 0;
700 for (int32_t i = 0; i < fnIface->info.numPipes; i++) {
701 struct UsbFnPipeInfo pipeInfo;
702 (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo));
703 int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo);
704 if (ret != HDF_SUCCESS) {
705 HDF_LOGE("%{public}s: get pipe info error", __func__);
706 return HDF_FAILURE;
707 }
708
709 switch (pipeInfo.type) {
710 case USB_PIPE_TYPE_INTERRUPT:
711 ecm->notifyPipe.id = pipeInfo.id;
712 ecm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
713 ecm->ctrlIface = *iface;
714 break;
715 case USB_PIPE_TYPE_BULK:
716 if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
717 ecm->dataInPipe.id = pipeInfo.id;
718 ecm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
719 ecm->dataIface = *iface;
720 } else {
721 ecm->dataOutPipe.id = pipeInfo.id;
722 ecm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
723 }
724 break;
725 default:
726 if (repetIdx < WAIT_UDC_MAX_LOOP) {
727 usleep(WAIT_UDC_TIME);
728 i--;
729 }
730 repetIdx++;
731 HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type);
732 break;
733 }
734 }
735
736 return HDF_SUCCESS;
737 }
738
EcmParseEcmIface(struct UsbEcmDevice * ecm,struct UsbFnInterface * fnIface)739 static int32_t EcmParseEcmIface(struct UsbEcmDevice *ecm, struct UsbFnInterface *fnIface)
740 {
741 int32_t ret;
742 struct UsbEcmInterface iface;
743 UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface);
744 if (handle == NULL) {
745 HDF_LOGE("%{public}s: open interface failed", __func__);
746 return HDF_FAILURE;
747 }
748 iface.fn = fnIface;
749 iface.handle = handle;
750
751 ret = EcmParseEachPipe(ecm, &iface);
752 if (ret != HDF_SUCCESS) {
753 return HDF_FAILURE;
754 }
755 return HDF_SUCCESS;
756 }
757
EcmParseEachIface(struct UsbEcmDevice * ecm,struct UsbFnDevice * fnDev)758 static int32_t EcmParseEachIface(struct UsbEcmDevice *ecm, struct UsbFnDevice *fnDev)
759 {
760 struct UsbFnInterface *fnIface = NULL;
761 uint32_t i;
762
763 for (i = 0; i < fnDev->numInterfaces; i++) {
764 fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
765 if (fnIface == NULL) {
766 HDF_LOGE("%{public}s: get interface failed", __func__);
767 return HDF_FAILURE;
768 }
769
770 if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ETHERNET) {
771 (void)EcmParseEcmIface(ecm, fnIface);
772 fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1);
773 if (fnIface == NULL) {
774 HDF_LOGE("%{public}s: get interface failed", __func__);
775 return HDF_FAILURE;
776 }
777 (void)EcmParseEcmIface(ecm, fnIface);
778 return HDF_SUCCESS;
779 }
780 }
781
782 return HDF_FAILURE;
783 }
784
EcmCreateFuncDevice(struct UsbEcmDevice * ecm,struct DeviceResourceIface * iface)785 static int32_t EcmCreateFuncDevice(struct UsbEcmDevice *ecm, struct DeviceResourceIface *iface)
786 {
787 struct UsbFnDevice *fnDev = NULL;
788 int32_t ret;
789
790 if (iface->GetString(ecm->device->property, "udc_name", (const char **)&ecm->udcName, UDC_NAME) != HDF_SUCCESS) {
791 HDF_LOGE("%{public}s: read udc_name failed, use default", __func__);
792 return HDF_FAILURE;
793 }
794
795 fnDev = (struct UsbFnDevice *)UsbFnGetDevice(ecm->udcName);
796 if (fnDev == NULL) {
797 HDF_LOGE("%{public}s: create usb function device failed", __func__);
798 return HDF_FAILURE;
799 }
800
801 ret = EcmParseEachIface(ecm, fnDev);
802 if (ret != HDF_SUCCESS) {
803 HDF_LOGE("%{public}s: get pipes failed", __func__);
804 goto ERR;
805 }
806
807 ecm->fnDev = fnDev;
808 return HDF_SUCCESS;
809
810 ERR:
811 return ret;
812 }
813
EcmFreeNotifyRequest(struct UsbEcmDevice * ecm)814 static void EcmFreeNotifyRequest(struct UsbEcmDevice *ecm)
815 {
816 int32_t ret;
817
818 /* free notification request */
819 ret = UsbFnFreeRequest(ecm->notifyReq);
820 if (ret != HDF_SUCCESS) {
821 HDF_LOGE("%{public}s: free notify request failed", __func__);
822 return;
823 }
824 ecm->notifyReq = NULL;
825 }
826
EcmReleaseFuncDevice(struct UsbEcmDevice * ecm)827 static int32_t EcmReleaseFuncDevice(struct UsbEcmDevice *ecm)
828 {
829 int32_t ret = HDF_SUCCESS;
830 if (ecm->fnDev == NULL) {
831 HDF_LOGE("%{public}s: fnDev is null", __func__);
832 return HDF_FAILURE;
833 }
834 (void)UsbFnFreeRequest(ecm->ep0Req);
835 (void)EcmFreeNotifyRequest(ecm);
836 UsbFnCloseInterface(ecm->ctrlIface.handle);
837 (void)UsbFnCloseInterface(ecm->dataIface.handle);
838 (void)UsbFnStopRecvInterfaceEvent(ecm->ctrlIface.fn);
839 return ret;
840 }
841
UsbEcmAlloc(struct UsbEcmDevice * ecm)842 static int32_t UsbEcmAlloc(struct UsbEcmDevice *ecm)
843 {
844 struct UsbEcm *port = NULL;
845
846 port = (struct UsbEcm *)OsalMemCalloc(sizeof(*port));
847 if (port == NULL) {
848 HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__);
849 return HDF_FAILURE;
850 }
851
852 if (OsalMutexInit(&port->lock) != HDF_SUCCESS) {
853 HDF_LOGE("%{public}s: init lock fail!", __func__);
854 OsalMemFree(port);
855 return HDF_FAILURE;
856 }
857
858 if (OsalMutexInit(&port->lockRW) != HDF_SUCCESS) {
859 HDF_LOGE("%{public}s: init lock fail!", __func__);
860 OsalMutexDestroy(&port->lock);
861 OsalMemFree(port);
862 return HDF_FAILURE;
863 }
864
865 if (OsalMutexInit(&port->lockReadFifo) != HDF_SUCCESS) {
866 HDF_LOGE("%{public}s: init lock fail!", __func__);
867 OsalMutexDestroy(&port->lock);
868 OsalMutexDestroy(&port->lockRW);
869 OsalMemFree(port);
870 return HDF_FAILURE;
871 }
872
873 if (OsalMutexInit(&port->lockWriteFifo) != HDF_SUCCESS) {
874 HDF_LOGE("%{public}s: init lock fail!", __func__);
875 OsalMutexDestroy(&port->lock);
876 OsalMutexDestroy(&port->lockRW);
877 OsalMutexDestroy(&port->lockReadFifo);
878 OsalMemFree(port);
879 return HDF_FAILURE;
880 }
881 DListHeadInit(&port->readPool);
882 DListHeadInit(&port->readQueue);
883 DListHeadInit(&port->writePool);
884
885 ecm->port = port;
886 return HDF_SUCCESS;
887 }
888
UsbEcmFree(struct UsbEcmDevice * ecm)889 static void UsbEcmFree(struct UsbEcmDevice *ecm)
890 {
891 if (ecm != NULL && ecm->port != NULL) {
892 OsalMutexDestroy(&ecm->port->lock);
893 OsalMutexDestroy(&ecm->port->lockRW);
894 OsalMutexDestroy(&ecm->port->lockReadFifo);
895 OsalMutexDestroy(&ecm->port->lockWriteFifo);
896 OsalMemFree(ecm->port);
897 ecm->port = NULL;
898 }
899 }
900
901 /* HdfDriverEntry implementations */
EcmDriverBind(struct HdfDeviceObject * device)902 static int32_t EcmDriverBind(struct HdfDeviceObject *device)
903 {
904 struct UsbEcmDevice *ecm = NULL;
905
906 if (device == NULL) {
907 HDF_LOGE("%{public}s: device is null", __func__);
908 return HDF_ERR_INVALID_OBJECT;
909 }
910
911 ecm = (struct UsbEcmDevice *)OsalMemCalloc(sizeof(*ecm));
912 if (ecm == NULL) {
913 HDF_LOGE("%{public}s: Alloc usb ecm device failed", __func__);
914 return HDF_FAILURE;
915 }
916 ecm->ctrlId = 0;
917 ecm->dataId = 1;
918 if (OsalMutexInit(&ecm->lock) != HDF_SUCCESS) {
919 HDF_LOGE("%{public}s: init lock fail!", __func__);
920 OsalMemFree(ecm);
921 return HDF_FAILURE;
922 }
923
924 if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) {
925 HDF_LOGE(" Set Desc fail!");
926 OsalMemFree(ecm);
927 return HDF_FAILURE;
928 }
929
930 ecm->device = device;
931 device->service = &(ecm->service);
932 if (ecm->device->service) {
933 ecm->device->service->Dispatch = EcmDeviceDispatch;
934 }
935 return HDF_SUCCESS;
936 }
937
EcmInit(struct HdfDeviceObject * device)938 static int32_t EcmInit(struct HdfDeviceObject *device)
939 {
940 struct UsbEcmDevice *ecm = NULL;
941 struct DeviceResourceIface *iface = NULL;
942 int32_t ret;
943
944 if (device == NULL) {
945 HDF_LOGE("%{public}s: device is null", __func__);
946 return HDF_ERR_INVALID_OBJECT;
947 }
948
949 ecm = (struct UsbEcmDevice *)device->service;
950 if (ecm == NULL || ecm->initFlag) {
951 HDF_LOGE("%{public}s: ecm is null", __func__);
952 return HDF_FAILURE;
953 }
954
955 iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
956 if (iface == NULL || iface->GetUint32 == NULL) {
957 HDF_LOGE("%{public}s: face is invalid", __func__);
958 return HDF_FAILURE;
959 }
960
961 ret = EcmCreateFuncDevice(ecm, iface);
962 if (ret != HDF_SUCCESS) {
963 HDF_LOGE("%{public}s: EcmCreateFuncDevice failed", __func__);
964 return ret;
965 }
966
967 ret = UsbEcmAlloc(ecm);
968 if (ret != HDF_SUCCESS) {
969 HDF_LOGE("%{public}s: UsbEcmAlloc failed", __func__);
970 return ret;
971 }
972
973 ret = EcmAllocEp0Request(ecm);
974 if (ret != HDF_SUCCESS) {
975 HDF_LOGE("%{public}s: EcmAllocEp0Request failed", __func__);
976 goto ERR;
977 }
978
979 ret = EcmAllocNotifyRequest(ecm);
980 if (ret != HDF_SUCCESS) {
981 HDF_LOGE("%{public}s: EcmAllocNotifyRequest failed", __func__);
982 goto ERR;
983 }
984
985 ret = UsbFnStartRecvInterfaceEvent(ecm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbEcmEventCallback, ecm);
986 if (ret != HDF_SUCCESS) {
987 HDF_LOGE("%{public}s: register event callback failed", __func__);
988 goto ERR;
989 }
990 ecm->initFlag = true;
991 return ret;
992 ERR:
993 UsbEcmFree(ecm);
994 (void)EcmReleaseFuncDevice(ecm);
995 return ret;
996 }
997
EcmRelease(struct HdfDeviceObject * device)998 static int32_t EcmRelease(struct HdfDeviceObject *device)
999 {
1000 struct UsbEcmDevice *ecm = NULL;
1001
1002 if (device == NULL) {
1003 HDF_LOGE("%{public}s: device is NULL", __func__);
1004 return HDF_FAILURE;
1005 }
1006
1007 ecm = (struct UsbEcmDevice *)device->service;
1008 if (ecm == NULL) {
1009 HDF_LOGE("%{public}s: ecm is null", __func__);
1010 return HDF_FAILURE;
1011 }
1012 if (ecm->initFlag == false) {
1013 HDF_LOGE("%{public}s: ecm not init!", __func__);
1014 return HDF_FAILURE;
1015 }
1016 UsbEcmFree(ecm);
1017 (void)EcmReleaseFuncDevice(ecm);
1018 ecm->initFlag = false;
1019 return HDF_SUCCESS;
1020 }
1021
EcmDriverInit(struct HdfDeviceObject * device)1022 static int32_t EcmDriverInit(struct HdfDeviceObject *device)
1023 {
1024 (void)device;
1025 HDF_LOGE("%{public}s: usbfn do nothing...", __func__);
1026 return 0;
1027 }
1028
EcmDriverRelease(struct HdfDeviceObject * device)1029 static void EcmDriverRelease(struct HdfDeviceObject *device)
1030 {
1031 struct UsbEcmDevice *ecm = NULL;
1032 if (device == NULL) {
1033 HDF_LOGE("%{public}s: device is NULL", __func__);
1034 return;
1035 }
1036
1037 ecm = (struct UsbEcmDevice *)device->service;
1038 if (ecm == NULL) {
1039 HDF_LOGE("%{public}s: ecm is null", __func__);
1040 return;
1041 }
1042
1043 (void)OsalMutexDestroy(&ecm->lock);
1044 OsalMemFree(ecm);
1045 device->service = NULL;
1046 }
1047
1048 struct HdfDriverEntry g_ecmDriverEntry = {
1049 .moduleVersion = 1,
1050 .moduleName = "usbfn_cdcecm",
1051 .Bind = EcmDriverBind,
1052 .Init = EcmDriverInit,
1053 .Release = EcmDriverRelease,
1054 };
1055
1056 HDF_INIT(g_ecmDriverEntry);
1057