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