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