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 HDF_LOGD("%{public}s: enter", __func__);
316 int32_t ret;
317
318 if (port == NULL) {
319 HDF_LOGE("%{public}s: port is null", __func__);
320 return HDF_ERR_INVALID_PARAM;
321 }
322
323 OsalMutexLock(&port->lock);
324 ret = UsbEcmAllocFifo(&port->writeFifo, WRITE_BUF_SIZE);
325 if (ret != HDF_SUCCESS) {
326 HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
327 goto OUT;
328 }
329 ret = UsbEcmAllocFifo(&port->readFifo, READ_BUF_SIZE);
330 if (ret != HDF_SUCCESS) {
331 HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
332 goto OUT;
333 }
334 DataFifoReset(&port->writeFifo);
335 DataFifoReset(&port->readFifo);
336
337 if (port->refCount++) {
338 HDF_LOGE("%{public}s: refCount failed", __func__);
339 goto OUT;
340 }
341
342 /* the ecm is enabled, start the io stream */
343 if (port->ecm) {
344 HDF_LOGD("%{public}s: start usb io", __func__);
345 ret = UsbEcmStartIo(port);
346 if (ret != HDF_SUCCESS) {
347 goto OUT;
348 }
349 }
350
351 OUT:
352 OsalMutexUnlock(&port->lock);
353 HDF_LOGD("%{public}s: exit", __func__);
354 return HDF_SUCCESS;
355 }
356
UsbEcmClose(struct UsbEcm * port)357 static int32_t UsbEcmClose(struct UsbEcm *port)
358 {
359 HDF_LOGD("%{public}s: enter", __func__);
360 if (port == NULL) {
361 HDF_LOGE("%{public}s: port is null", __func__);
362 return HDF_ERR_INVALID_PARAM;
363 }
364
365 OsalMutexLock(&port->lock);
366 if (port->refCount != 1) {
367 --port->refCount;
368 goto OUT;
369 }
370
371 HDF_LOGD("%{public}s: close usb serial", __func__);
372
373 DataFifoReset(&port->writeFifo);
374 DataFifoReset(&port->readFifo);
375 port->refCount = 0;
376
377 OUT:
378 OsalMutexUnlock(&port->lock);
379 HDF_LOGD("%{public}s: exit", __func__);
380 return HDF_SUCCESS;
381 }
382
UsbEcmRead(struct UsbEcm * port,struct HdfSBuf * reply)383 static int32_t UsbEcmRead(struct UsbEcm *port, struct HdfSBuf *reply)
384 {
385 HDF_LOGI("%{public}s: enter", __func__);
386 uint32_t len;
387 int32_t ret = HDF_SUCCESS;
388 uint8_t *buf = NULL;
389 OsalMutexLock(&port->lock);
390 OsalMutexLock(&port->lockReadFifo);
391 if (DataFifoIsEmpty(&port->readFifo)) {
392 OsalMutexUnlock(&port->lockReadFifo);
393 OsalMutexUnlock(&port->lock);
394 HDF_LOGI("%{public}s: data fifl is empty", __func__);
395 return 0;
396 }
397
398 buf = (uint8_t *)OsalMemCalloc(DataFifoLen(&port->readFifo) + sizeof(uint32_t));
399 if (buf == NULL) {
400 HDF_LOGE("%{public}s: OsalMemCalloc error", __func__);
401 OsalMutexUnlock(&port->lockReadFifo);
402 OsalMutexUnlock(&port->lock);
403 return HDF_ERR_MALLOC_FAIL;
404 }
405
406 len = DataFifoRead(&port->readFifo, buf, DataFifoLen(&port->readFifo));
407 if (len == 0) {
408 HDF_LOGE("%{public}s: no data", __func__);
409 ret = HDF_ERR_IO;
410 OsalMutexUnlock(&port->lockReadFifo);
411 goto OUT;
412 }
413 OsalMutexUnlock(&port->lockReadFifo);
414
415 bool bufok = HdfSbufWriteBuffer(reply, (const void *)buf, len);
416 if (!bufok) {
417 HDF_LOGE("UsbEcmRead HdfSbufWriteBuffer error");
418 ret = HDF_ERR_IO;
419 goto OUT;
420 }
421
422 OUT:
423 if (port->ecm) {
424 UsbEcmStartRx(port);
425 }
426 OsalMemFree(buf);
427 OsalMutexUnlock(&port->lock);
428 HDF_LOGD("%{public}s: exit", __func__);
429 return ret;
430 }
431
UsbEcmWrite(struct UsbEcm * port,struct HdfSBuf * data)432 static int32_t UsbEcmWrite(struct UsbEcm *port, struct HdfSBuf *data)
433 {
434 HDF_LOGD("%{public}s: enter", __func__);
435 uint32_t size = 0;
436 uint8_t *buf = NULL;
437
438 if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) {
439 HDF_LOGE("UsbEcmWrite HdfSbufReadBuffer err");
440 return HDF_ERR_IO;
441 }
442
443 OsalMutexLock(&port->lock);
444 if (size > 0 && buf != NULL) {
445 OsalMutexLock(&port->lockWriteFifo);
446 size = DataFifoWrite(&port->writeFifo, buf, size);
447 OsalMutexUnlock(&port->lockWriteFifo);
448 } else {
449 HDF_LOGE("%{public}s: buf is null", __func__);
450 }
451 if (port->ecm) {
452 UsbEcmStartTx(port);
453 }
454 OsalMutexUnlock(&port->lock);
455 HDF_LOGD("%{public}s: exit", __func__);
456 return HDF_SUCCESS;
457 }
458
UsbFnNotifyRequest(struct UsbFnRequest * req,struct UsbEcmDevice * ecm)459 void UsbFnNotifyRequest(struct UsbFnRequest *req, struct UsbEcmDevice *ecm)
460 {
461 int32_t status;
462 ecm->notifyReq = NULL;
463 status = UsbFnSubmitRequestAsync(req);
464 if (status < 0) {
465 ecm->notifyReq = req;
466 HDF_LOGD("notify --> %{public}d", status);
467 }
468 }
469
EcmDoNotify(struct UsbEcmDevice * ecm)470 static void EcmDoNotify(struct UsbEcmDevice *ecm)
471 {
472 struct UsbFnRequest *req = ecm->notifyReq;
473 struct UsbCdcNotification *event = NULL;
474 uint32_t *data = NULL;
475
476 if (!req) {
477 return;
478 }
479 ecm->isOpen = true;
480 event = (struct UsbCdcNotification *)req->buf;
481 if (event == NULL) {
482 return;
483 }
484 switch (ecm->notifyState) {
485 case ECM_NOTIFY_NONE:
486 return;
487
488 case ECM_NOTIFY_CONNECT:
489 event->bNotificationType = USB_DDK_CDC_NOTIFY_NETWORK_CONNECTION;
490 if (ecm->isOpen) {
491 event->wValue = CPU_TO_LE16(1);
492 } else {
493 event->wValue = CPU_TO_LE16(0);
494 }
495 event->wLength = 0;
496 req->length = sizeof(*event);
497
498 HDF_LOGD("notify connect %{public}s", ecm->isOpen ? "true" : "false");
499 ecm->notifyState = ECM_NOTIFY_SPEED;
500 break;
501
502 case ECM_NOTIFY_SPEED:
503 event->bNotificationType = USB_DDK_CDC_NOTIFY_SPEED_CHANGE;
504 event->wValue = CPU_TO_LE16(0);
505 event->wLength = CPU_TO_LE16(0x08);
506 req->length = ECM_STATUS_BYTECOUNT;
507
508 /* SPEED_CHANGE data is up/down speeds in bits/sec */
509 data = (uint32_t *)((char *)req->buf + sizeof(*event));
510 data[0] = CPU_TO_LE32(EcmBitrate());
511 data[1] = data[0];
512
513 HDF_LOGD("notify speed %{public}d", EcmBitrate());
514 ecm->notifyState = ECM_NOTIFY_NONE;
515 break;
516
517 default:
518 break;
519 }
520 event->bmRequestType = 0xA1;
521 event->wIndex = CPU_TO_LE16(ecm->ctrlId);
522 UsbFnNotifyRequest(req, ecm);
523 }
524
EcmNotifyComplete(uint8_t pipe,struct UsbFnRequest * req)525 static void EcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req)
526 {
527 struct UsbEcmDevice *ecm = req->context;
528 struct UsbCdcNotification *event = req->buf;
529 ecm->notifyReq = req;
530 if (req->status == 0) {
531 EcmDoNotify(ecm);
532 } else {
533 HDF_LOGD("event %{public}d --> %{public}d", event->bNotificationType, req->status);
534 }
535 }
536
EcmSetup(const struct UsbEcmDevice * ecm,const struct UsbFnCtrlRequest * ctrl)537 static int32_t EcmSetup(const struct UsbEcmDevice *ecm, const struct UsbFnCtrlRequest *ctrl)
538 {
539 struct UsbFnRequest *req = ecm->ep0Req;
540 int32_t ret = -1;
541 uint16_t index = LE16_TO_CPU(ctrl->index);
542 uint16_t value = LE16_TO_CPU(ctrl->value);
543 uint16_t length = LE16_TO_CPU(ctrl->length);
544
545 switch ((ctrl->reqType << 0x08) | ctrl->request) {
546 case ((USB_DDK_DIR_OUT | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE) << 0x08) |
547 USB_DDK_CDC_SET_ETHERNET_PACKET_FILTER:
548 if (length != 0 || index != ecm->ctrlId) {
549 break;
550 }
551 HDF_LOGD("packet filter %{public}02x", value);
552 ret = 0;
553 break;
554
555 default:
556 HDF_LOGW(
557 "invalid control req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}hu",
558 ctrl->reqType, ctrl->request, value, index, length);
559 }
560
561 if (ret >= 0) {
562 HDF_LOGD("ecm req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}d",
563 ctrl->reqType, ctrl->request, value, index, length);
564 req->length = (uint32_t)ret;
565 ret = UsbFnSubmitRequestSync(req, 0);
566 if (ret < 0) {
567 HDF_LOGD("ecm req %{public}02x.%{public}02x response err %{public}d", ctrl->reqType, ctrl->request, ret);
568 }
569 }
570
571 return value;
572 }
573
EcmDeviceDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)574 static int32_t EcmDeviceDispatch(
575 struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
576 {
577 struct UsbEcmDevice *ecm = NULL;
578 struct UsbEcm *port = NULL;
579 int32_t ret;
580 if (client == NULL || client->device == NULL || client->device->service == NULL) {
581 HDF_LOGE("%{public}s: client is NULL", __func__);
582 return HDF_ERR_INVALID_OBJECT;
583 }
584 if (data == NULL || reply == NULL) {
585 HDF_LOGE("%{public}s: data or reply is NULL", __func__);
586 return HDF_ERR_INVALID_OBJECT;
587 }
588
589 if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) {
590 HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__);
591 return HDF_ERR_INVALID_PARAM;
592 }
593
594 switch (cmd) {
595 case USB_ECM_INIT:
596 return EcmInit(client->device);
597 case USB_ECM_RELEASE:
598 return EcmRelease(client->device);
599 default:
600 break;
601 }
602 ecm = (struct UsbEcmDevice *)client->device->service;
603 port = ecm->port;
604 if (port == NULL) {
605 return HDF_ERR_IO;
606 }
607 OsalMutexLock(&port->lockRW);
608 switch (cmd) {
609 case USB_ECM_OPEN:
610 ret = UsbEcmOpen(port);
611 break;
612 case USB_ECM_CLOSE:
613 ret = UsbEcmClose(port);
614 break;
615 case USB_ECM_READ:
616 ret = UsbEcmRead(port, reply);
617 break;
618 case USB_ECM_WRITE:
619 ret = UsbEcmWrite(port, data);
620 break;
621 default:
622 ret = HDF_ERR_NOT_SUPPORT;
623 break;
624 }
625 OsalMutexUnlock(&port->lockRW);
626 return ret;
627 }
628
EcmEnable(struct UsbEcmDevice * ecm)629 static int32_t EcmEnable(struct UsbEcmDevice *ecm)
630 {
631 (void)ecm;
632 return HDF_SUCCESS;
633 }
634
EcmDisable(const struct UsbEcmDevice * ecm)635 static void EcmDisable(const struct UsbEcmDevice *ecm)
636 {
637 (void)ecm;
638 return;
639 }
640
UsbEcmEventCallback(struct UsbFnEvent * event)641 static void UsbEcmEventCallback(struct UsbFnEvent *event)
642 {
643 struct UsbEcmDevice *ecm = NULL;
644
645 if (event == NULL || event->context == NULL) {
646 HDF_LOGE("%{public}s: event is null", __func__);
647 return;
648 }
649
650 ecm = (struct UsbEcmDevice *)event->context;
651 switch (event->type) {
652 case USBFN_STATE_BIND:
653 HDF_LOGI("%{public}s: receive bind event", __func__);
654 break;
655 case USBFN_STATE_UNBIND:
656 HDF_LOGI("%{public}s: receive unbind event", __func__);
657 break;
658 case USBFN_STATE_ENABLE:
659 HDF_LOGI("%{public}s: receive enable event", __func__);
660 EcmEnable(ecm);
661 break;
662 case USBFN_STATE_DISABLE:
663 HDF_LOGI("%{public}s: receive disable event", __func__);
664 EcmDisable(ecm);
665 break;
666 case USBFN_STATE_SETUP:
667 HDF_LOGI("%{public}s: receive setup event", __func__);
668 if (event->setup != NULL) {
669 EcmSetup(ecm, event->setup);
670 }
671 break;
672 case USBFN_STATE_SUSPEND:
673 HDF_LOGI("%{public}s: receive suspend event", __func__);
674 break;
675 case USBFN_STATE_RESUME:
676 HDF_LOGI("%{public}s: receive resume event", __func__);
677 break;
678 default:
679 break;
680 }
681 }
682
EcmAllocNotifyRequest(struct UsbEcmDevice * ecm)683 static int32_t EcmAllocNotifyRequest(struct UsbEcmDevice *ecm)
684 {
685 /* allocate notification request */
686 ecm->notifyReq =
687 UsbFnAllocRequest(ecm->ctrlIface.handle, ecm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN);
688 if (ecm->notifyReq == NULL) {
689 HDF_LOGE("%{public}s: allocate notify request failed", __func__);
690 return HDF_FAILURE;
691 }
692 ecm->notifyReq->complete = EcmNotifyComplete;
693 ecm->notifyReq->context = ecm;
694
695 return HDF_SUCCESS;
696 }
697
EcmAllocEp0Request(struct UsbEcmDevice * ecm)698 static int32_t EcmAllocEp0Request(struct UsbEcmDevice *ecm)
699 {
700 /* allocate notification request */
701 ecm->ep0Req = UsbFnAllocCtrlRequest(ecm->ctrlIface.handle, ECM_STATUS_BYTECOUNT);
702 if (ecm->ep0Req == NULL) {
703 HDF_LOGE("%{public}s: allocate ep0Req request failed", __func__);
704 return HDF_FAILURE;
705 }
706 return HDF_SUCCESS;
707 }
708
EcmParseEachPipe(struct UsbEcmDevice * ecm,struct UsbEcmInterface * iface)709 static int32_t EcmParseEachPipe(struct UsbEcmDevice *ecm, struct UsbEcmInterface *iface)
710 {
711 struct UsbFnInterface *fnIface = iface->fn;
712 uint32_t repetIdx = 0;
713 for (int32_t i = 0; i < fnIface->info.numPipes; i++) {
714 struct UsbFnPipeInfo pipeInfo;
715 (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo));
716 int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo);
717 if (ret != HDF_SUCCESS) {
718 HDF_LOGE("%{public}s: get pipe info error", __func__);
719 return HDF_FAILURE;
720 }
721
722 switch (pipeInfo.type) {
723 case USB_PIPE_TYPE_INTERRUPT:
724 ecm->notifyPipe.id = pipeInfo.id;
725 ecm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
726 ecm->ctrlIface = *iface;
727 break;
728 case USB_PIPE_TYPE_BULK:
729 if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
730 ecm->dataInPipe.id = pipeInfo.id;
731 ecm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
732 ecm->dataIface = *iface;
733 } else {
734 ecm->dataOutPipe.id = pipeInfo.id;
735 ecm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
736 }
737 break;
738 default:
739 if (repetIdx < WAIT_UDC_MAX_LOOP) {
740 usleep(WAIT_UDC_TIME);
741 i--;
742 }
743 repetIdx++;
744 HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type);
745 break;
746 }
747 }
748
749 return HDF_SUCCESS;
750 }
751
EcmParseEcmIface(struct UsbEcmDevice * ecm,struct UsbFnInterface * fnIface)752 static int32_t EcmParseEcmIface(struct UsbEcmDevice *ecm, struct UsbFnInterface *fnIface)
753 {
754 int32_t ret;
755 struct UsbEcmInterface iface;
756 UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface);
757 if (handle == NULL) {
758 HDF_LOGE("%{public}s: open interface failed", __func__);
759 return HDF_FAILURE;
760 }
761 iface.fn = fnIface;
762 iface.handle = handle;
763
764 ret = EcmParseEachPipe(ecm, &iface);
765 if (ret != HDF_SUCCESS) {
766 return HDF_FAILURE;
767 }
768 return HDF_SUCCESS;
769 }
770
EcmParseEachIface(struct UsbEcmDevice * ecm,struct UsbFnDevice * fnDev)771 static int32_t EcmParseEachIface(struct UsbEcmDevice *ecm, struct UsbFnDevice *fnDev)
772 {
773 struct UsbFnInterface *fnIface = NULL;
774 uint32_t i;
775
776 for (i = 0; i < fnDev->numInterfaces; i++) {
777 fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
778 if (fnIface == NULL) {
779 HDF_LOGE("%{public}s: get interface failed", __func__);
780 return HDF_FAILURE;
781 }
782
783 if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ETHERNET) {
784 (void)EcmParseEcmIface(ecm, fnIface);
785 fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1);
786 if (fnIface == NULL) {
787 HDF_LOGE("%{public}s: get interface failed", __func__);
788 return HDF_FAILURE;
789 }
790 (void)EcmParseEcmIface(ecm, fnIface);
791 return HDF_SUCCESS;
792 }
793 }
794
795 return HDF_FAILURE;
796 }
797
EcmCreateFuncDevice(struct UsbEcmDevice * ecm,struct DeviceResourceIface * iface)798 static int32_t EcmCreateFuncDevice(struct UsbEcmDevice *ecm, struct DeviceResourceIface *iface)
799 {
800 struct UsbFnDevice *fnDev = NULL;
801 int32_t ret;
802
803 if (iface->GetString(ecm->device->property, "udc_name", (const char **)&ecm->udcName, UDC_NAME) != HDF_SUCCESS) {
804 HDF_LOGE("%{public}s: read udc_name failed, use default", __func__);
805 return HDF_FAILURE;
806 }
807
808 fnDev = (struct UsbFnDevice *)UsbFnGetDevice(ecm->udcName);
809 if (fnDev == NULL) {
810 HDF_LOGE("%{public}s: create usb function device failed", __func__);
811 return HDF_FAILURE;
812 }
813
814 ret = EcmParseEachIface(ecm, fnDev);
815 if (ret != HDF_SUCCESS) {
816 HDF_LOGE("%{public}s: get pipes failed", __func__);
817 goto ERR;
818 }
819
820 ecm->fnDev = fnDev;
821 return HDF_SUCCESS;
822
823 ERR:
824 return ret;
825 }
826
EcmFreeNotifyRequest(struct UsbEcmDevice * ecm)827 static void EcmFreeNotifyRequest(struct UsbEcmDevice *ecm)
828 {
829 int32_t ret;
830
831 /* free notification request */
832 ret = UsbFnFreeRequest(ecm->notifyReq);
833 if (ret != HDF_SUCCESS) {
834 HDF_LOGE("%{public}s: free notify request failed", __func__);
835 return;
836 }
837 ecm->notifyReq = NULL;
838 }
839
EcmReleaseFuncDevice(struct UsbEcmDevice * ecm)840 static int32_t EcmReleaseFuncDevice(struct UsbEcmDevice *ecm)
841 {
842 int32_t ret = HDF_SUCCESS;
843 if (ecm->fnDev == NULL) {
844 HDF_LOGE("%{public}s: fnDev is null", __func__);
845 return HDF_FAILURE;
846 }
847 (void)UsbFnFreeRequest(ecm->ep0Req);
848 (void)EcmFreeNotifyRequest(ecm);
849 UsbFnCloseInterface(ecm->ctrlIface.handle);
850 (void)UsbFnCloseInterface(ecm->dataIface.handle);
851 (void)UsbFnStopRecvInterfaceEvent(ecm->ctrlIface.fn);
852 HDF_LOGD("%{public}s: ecn was released heres", __func__);
853 return ret;
854 }
855
UsbEcmAlloc(struct UsbEcmDevice * ecm)856 static int32_t UsbEcmAlloc(struct UsbEcmDevice *ecm)
857 {
858 struct UsbEcm *port = NULL;
859
860 port = (struct UsbEcm *)OsalMemCalloc(sizeof(*port));
861 if (port == NULL) {
862 HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__);
863 return HDF_FAILURE;
864 }
865
866 if (OsalMutexInit(&port->lock) != HDF_SUCCESS) {
867 HDF_LOGE("%{public}s: init lock fail!", __func__);
868 OsalMemFree(port);
869 return HDF_FAILURE;
870 }
871
872 if (OsalMutexInit(&port->lockRW) != HDF_SUCCESS) {
873 HDF_LOGE("%{public}s: init lock fail!", __func__);
874 OsalMutexDestroy(&port->lock);
875 OsalMemFree(port);
876 return HDF_FAILURE;
877 }
878
879 if (OsalMutexInit(&port->lockReadFifo) != HDF_SUCCESS) {
880 HDF_LOGE("%{public}s: init lock fail!", __func__);
881 OsalMutexDestroy(&port->lock);
882 OsalMutexDestroy(&port->lockRW);
883 OsalMemFree(port);
884 return HDF_FAILURE;
885 }
886
887 if (OsalMutexInit(&port->lockWriteFifo) != HDF_SUCCESS) {
888 HDF_LOGE("%{public}s: init lock fail!", __func__);
889 OsalMutexDestroy(&port->lock);
890 OsalMutexDestroy(&port->lockRW);
891 OsalMutexDestroy(&port->lockReadFifo);
892 OsalMemFree(port);
893 return HDF_FAILURE;
894 }
895 DListHeadInit(&port->readPool);
896 DListHeadInit(&port->readQueue);
897 DListHeadInit(&port->writePool);
898
899 ecm->port = port;
900 return HDF_SUCCESS;
901 }
902
UsbEcmFree(struct UsbEcmDevice * ecm)903 static void UsbEcmFree(struct UsbEcmDevice *ecm)
904 {
905 if (ecm != NULL && ecm->port != NULL) {
906 OsalMutexDestroy(&ecm->port->lock);
907 OsalMutexDestroy(&ecm->port->lockRW);
908 OsalMutexDestroy(&ecm->port->lockReadFifo);
909 OsalMutexDestroy(&ecm->port->lockWriteFifo);
910 OsalMemFree(ecm->port);
911 ecm->port = NULL;
912 }
913 }
914
915 /* HdfDriverEntry implementations */
EcmDriverBind(struct HdfDeviceObject * device)916 static int32_t EcmDriverBind(struct HdfDeviceObject *device)
917 {
918 HDF_LOGD("%{public}s: enter", __func__);
919 struct UsbEcmDevice *ecm = NULL;
920
921 if (device == NULL) {
922 HDF_LOGE("%{public}s: device is null", __func__);
923 return HDF_ERR_INVALID_OBJECT;
924 }
925
926 ecm = (struct UsbEcmDevice *)OsalMemCalloc(sizeof(*ecm));
927 if (ecm == NULL) {
928 HDF_LOGE("%{public}s: Alloc usb ecm device failed", __func__);
929 return HDF_FAILURE;
930 }
931 ecm->ctrlId = 0;
932 ecm->dataId = 1;
933 if (OsalMutexInit(&ecm->lock) != HDF_SUCCESS) {
934 HDF_LOGE("%{public}s: init lock fail!", __func__);
935 OsalMemFree(ecm);
936 return HDF_FAILURE;
937 }
938
939 if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) {
940 HDF_LOGE(" Set Desc fail!");
941 OsalMemFree(ecm);
942 return HDF_FAILURE;
943 }
944
945 ecm->device = device;
946 device->service = &(ecm->service);
947 if (ecm->device->service) {
948 ecm->device->service->Dispatch = EcmDeviceDispatch;
949 }
950 HDF_LOGD("%{public}s: exit", __func__);
951 return HDF_SUCCESS;
952 }
953
EcmInit(struct HdfDeviceObject * device)954 static int32_t EcmInit(struct HdfDeviceObject *device)
955 {
956 struct UsbEcmDevice *ecm = NULL;
957 struct DeviceResourceIface *iface = NULL;
958 int32_t ret;
959
960 if (device == NULL) {
961 HDF_LOGE("%{public}s: device is null", __func__);
962 return HDF_ERR_INVALID_OBJECT;
963 }
964
965 ecm = (struct UsbEcmDevice *)device->service;
966 if (ecm == NULL || ecm->initFlag) {
967 HDF_LOGE("%{public}s: ecm is null", __func__);
968 return HDF_FAILURE;
969 }
970
971 iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
972 if (iface == NULL || iface->GetUint32 == NULL) {
973 HDF_LOGE("%{public}s: face is invalid", __func__);
974 return HDF_FAILURE;
975 }
976
977 ret = EcmCreateFuncDevice(ecm, iface);
978 if (ret != HDF_SUCCESS) {
979 HDF_LOGE("%{public}s: EcmCreateFuncDevice failed", __func__);
980 return ret;
981 }
982
983 ret = UsbEcmAlloc(ecm);
984 if (ret != HDF_SUCCESS) {
985 HDF_LOGE("%{public}s: UsbEcmAlloc failed", __func__);
986 return ret;
987 }
988
989 ret = EcmAllocEp0Request(ecm);
990 if (ret != HDF_SUCCESS) {
991 HDF_LOGE("%{public}s: EcmAllocEp0Request failed", __func__);
992 goto ERR;
993 }
994
995 ret = EcmAllocNotifyRequest(ecm);
996 if (ret != HDF_SUCCESS) {
997 HDF_LOGE("%{public}s: EcmAllocNotifyRequest failed", __func__);
998 goto ERR;
999 }
1000
1001 ret = UsbFnStartRecvInterfaceEvent(ecm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbEcmEventCallback, ecm);
1002 if (ret != HDF_SUCCESS) {
1003 HDF_LOGE("%{public}s: register event callback failed", __func__);
1004 goto ERR;
1005 }
1006 ecm->initFlag = true;
1007 return ret;
1008 ERR:
1009 UsbEcmFree(ecm);
1010 (void)EcmReleaseFuncDevice(ecm);
1011 return ret;
1012 }
1013
EcmRelease(struct HdfDeviceObject * device)1014 static int32_t EcmRelease(struct HdfDeviceObject *device)
1015 {
1016 HDF_LOGD("%{public}s: enter", __func__);
1017 struct UsbEcmDevice *ecm = NULL;
1018
1019 if (device == NULL) {
1020 HDF_LOGE("%{public}s: device is NULL", __func__);
1021 return HDF_FAILURE;
1022 }
1023
1024 ecm = (struct UsbEcmDevice *)device->service;
1025 if (ecm == NULL) {
1026 HDF_LOGE("%{public}s: ecm is null", __func__);
1027 return HDF_FAILURE;
1028 }
1029 if (ecm->initFlag == false) {
1030 HDF_LOGE("%{public}s: ecm not init!", __func__);
1031 return HDF_FAILURE;
1032 }
1033 UsbEcmFree(ecm);
1034 (void)EcmReleaseFuncDevice(ecm);
1035 ecm->initFlag = false;
1036 HDF_LOGD("%{public}s: exit", __func__);
1037 return HDF_SUCCESS;
1038 }
1039
EcmDriverInit(struct HdfDeviceObject * device)1040 static int32_t EcmDriverInit(struct HdfDeviceObject *device)
1041 {
1042 (void)device;
1043 HDF_LOGE("%{public}s: usbfn do nothing...", __func__);
1044 return 0;
1045 }
1046
EcmDriverRelease(struct HdfDeviceObject * device)1047 static void EcmDriverRelease(struct HdfDeviceObject *device)
1048 {
1049 struct UsbEcmDevice *ecm = NULL;
1050 if (device == NULL) {
1051 HDF_LOGE("%{public}s: device is NULL", __func__);
1052 return;
1053 }
1054
1055 ecm = (struct UsbEcmDevice *)device->service;
1056 if (ecm == NULL) {
1057 HDF_LOGE("%{public}s: ecm is null", __func__);
1058 return;
1059 }
1060
1061 (void)OsalMutexDestroy(&ecm->lock);
1062 OsalMemFree(ecm);
1063 device->service = NULL;
1064 }
1065
1066 struct HdfDriverEntry g_ecmDriverEntry = {
1067 .moduleVersion = 1,
1068 .moduleName = "usbfn_cdcecm",
1069 .Bind = EcmDriverBind,
1070 .Init = EcmDriverInit,
1071 .Release = EcmDriverRelease,
1072 };
1073
1074 HDF_INIT(g_ecmDriverEntry);
1075