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