• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "usb_device_lite_cdcacm_test.h"
10 #include "adapter_if.h"
11 #include "usbfn_cfg_mgr.h"
12 #include "usbfn_dev_mgr.h"
13 
14 static struct UsbInterfaceAssocDescriptor g_acmIadDescriptor = {
15     .bLength = sizeof(g_acmIadDescriptor),
16     .bDescriptorType = USB_DDK_DT_INTERFACE_ASSOCIATION,
17 #ifdef CDC_ECM
18     .bFirstInterface = 0x02,
19 #else
20     .bFirstInterface = 0,
21 #endif
22     .bInterfaceCount = INTF_COUNT,
23     .bFunctionClass = USB_DDK_CLASS_COMM,
24     .bFunctionSubClass = USB_DDK_CDC_SUBCLASS_ACM,
25     .bFunctionProtocol = USB_DDK_CDC_ACM_PROTO_AT_V25TER,
26     .iFunction = ACM_IAD_IDX,
27 };
28 
29 static struct UsbInterfaceDescriptor g_acmControlInterfaceDesc = {
30     .bLength = USB_DDK_DT_INTERFACE_SIZE,
31     .bDescriptorType = USB_DDK_DT_INTERFACE,
32 #ifdef CDC_ECM
33     .bInterfaceNumber = 0x02,
34 #else
35     .bInterfaceNumber = 0,
36 #endif
37     .bAlternateSetting = 0,
38     .bNumEndpoints = NOTIFY_EP_NUM,
39     .bInterfaceClass = USB_DDK_CLASS_COMM,
40     .bInterfaceSubClass = USB_DDK_CDC_SUBCLASS_ACM,
41     .bInterfaceProtocol = USB_DDK_CDC_ACM_PROTO_AT_V25TER,
42     .iInterface = ACM_CTRL_IDX,
43 };
44 
45 static struct UsbInterfaceDescriptor g_acmDataInterfaceDesc = {
46     .bLength = USB_DDK_DT_INTERFACE_SIZE,
47     .bDescriptorType = USB_DDK_DT_INTERFACE,
48 #ifdef CDC_ECM
49     .bInterfaceNumber = 0x03,
50 #else
51     .bInterfaceNumber = 1,
52 #endif
53     .bAlternateSetting = 0,
54     .bNumEndpoints = DATA_EP_NUM,
55     .bInterfaceClass = USB_DDK_CLASS_CDC_DATA,
56     .bInterfaceSubClass = 0,
57     .bInterfaceProtocol = 0x2,
58     .iInterface = ACM_DATA_IDX,
59 };
60 
61 static struct UsbCdcHeaderDesc g_acmHeaderDesc = {
62     .bLength = sizeof(g_acmHeaderDesc),
63     .bDescriptorType = USB_DDK_DT_CS_INTERFACE,
64     .bDescriptorSubType = USB_DDK_CDC_HEADER_TYPE,
65     .bcdCDC = CPU_TO_LE16(0x0110),
66 };
67 
68 static struct UsbCdcCallMgmtDescriptor g_acmCallMgmtDescriptor = {
69     .bLength = sizeof(g_acmCallMgmtDescriptor),
70     .bDescriptorType = USB_DDK_DT_CS_INTERFACE,
71     .bDescriptorSubType = USB_DDK_CDC_CALL_MANAGEMENT_TYPE,
72     .bmCapabilities = 0,
73     .bDataInterface = 1,
74 };
75 
76 static struct UsbCdcAcmDescriptor g_acmDescriptor = {
77     .bLength = sizeof(g_acmDescriptor),
78     .bDescriptorType = USB_DDK_DT_CS_INTERFACE,
79     .bDescriptorSubType = USB_DDK_CDC_ACM_TYPE,
80     .bmCapabilities = USB_DDK_CDC_CAP_LINE,
81 };
82 
83 static struct UsbCdcUnionDesc g_acmUnionDesc = {
84     .bLength = sizeof(g_acmUnionDesc),
85     .bDescriptorType = USB_DDK_DT_CS_INTERFACE,
86     .bDescriptorSubType = USB_DDK_CDC_UNION_TYPE,
87 #ifdef CDC_ECM
88     .bMasterInterface0 = 0x02,
89     .bSlaveInterface0 = 0x03,
90 #else
91     .bMasterInterface0 = 0,
92     .bSlaveInterface0 = 1,
93 #endif
94 };
95 
96 static struct UsbEndpointDescriptor g_acmFsNotifyDesc = {
97     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
98     .bDescriptorType = USB_DDK_DT_ENDPOINT,
99     .bEndpointAddress = EP_ADD_NOTIFY | USB_DDK_DIR_IN,
100     .bmAttributes = USB_DDK_ENDPOINT_XFER_INT,
101     .wMaxPacketSize = CPU_TO_LE16(ACM_NOTIFY_MAXPACKET),
102     .bInterval = ACM_NOTIFY_INTERVAL,
103 };
104 
105 static struct UsbEndpointDescriptor g_acmFsInDesc = {
106     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
107     .bDescriptorType = USB_DDK_DT_ENDPOINT,
108     .bEndpointAddress = EP_ADD_DATA_IN | USB_DDK_DIR_IN,
109     .bmAttributes = USB_DDK_ENDPOINT_XFER_BULK,
110 };
111 
112 static struct UsbEndpointDescriptor g_acmFsOutDesc = {
113     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
114     .bDescriptorType = USB_DDK_DT_ENDPOINT,
115     .bEndpointAddress = EP_ADD_DATA_OUT | USB_DDK_DIR_OUT,
116     .bmAttributes = USB_DDK_ENDPOINT_XFER_BULK,
117 };
118 
119 static struct UsbDescriptorHeader *g_acmFsFunction[] = {
120     (struct UsbDescriptorHeader *)&g_acmIadDescriptor,
121     (struct UsbDescriptorHeader *)&g_acmControlInterfaceDesc,
122     (struct UsbDescriptorHeader *)&g_acmHeaderDesc,
123     (struct UsbDescriptorHeader *)&g_acmCallMgmtDescriptor,
124     (struct UsbDescriptorHeader *)&g_acmDescriptor,
125     (struct UsbDescriptorHeader *)&g_acmUnionDesc,
126     (struct UsbDescriptorHeader *)&g_acmFsNotifyDesc,
127     (struct UsbDescriptorHeader *)&g_acmDataInterfaceDesc,
128     (struct UsbDescriptorHeader *)&g_acmFsInDesc,
129     (struct UsbDescriptorHeader *)&g_acmFsOutDesc,
130     NULL,
131 };
132 
133 static struct UsbEndpointDescriptor g_acmHsNotifyDesc = {
134     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
135     .bDescriptorType = USB_DDK_DT_ENDPOINT,
136     .bEndpointAddress = EP_ADD_NOTIFY | USB_DDK_DIR_IN,
137     .bmAttributes = USB_DDK_ENDPOINT_XFER_INT,
138     .wMaxPacketSize = CPU_TO_LE16(ACM_NOTIFY_MAXPACKET),
139     .bInterval = ACM_HS_NOTIFY_INTERVAL,
140 };
141 
142 static struct UsbEndpointDescriptor g_acmHsInDesc = {
143     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
144     .bDescriptorType = USB_DDK_DT_ENDPOINT,
145     .bEndpointAddress = EP_ADD_DATA_IN | USB_DDK_DIR_IN,
146     .bmAttributes = USB_DDK_ENDPOINT_XFER_BULK,
147     .wMaxPacketSize = CPU_TO_LE16(MAX_PACKET_SIZE),
148 };
149 
150 static struct UsbEndpointDescriptor g_acmHsOutDesc = {
151     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
152     .bDescriptorType = USB_DDK_DT_ENDPOINT,
153     .bEndpointAddress = EP_ADD_DATA_OUT | USB_DDK_DIR_OUT,
154     .bmAttributes = USB_DDK_ENDPOINT_XFER_BULK,
155     .wMaxPacketSize = CPU_TO_LE16(MAX_PACKET_SIZE),
156 };
157 
158 static struct UsbDescriptorHeader *g_acmHsFunction[] = {
159     (struct UsbDescriptorHeader *)&g_acmIadDescriptor,
160     (struct UsbDescriptorHeader *)&g_acmControlInterfaceDesc,
161     (struct UsbDescriptorHeader *)&g_acmHeaderDesc,
162     (struct UsbDescriptorHeader *)&g_acmCallMgmtDescriptor,
163     (struct UsbDescriptorHeader *)&g_acmDescriptor,
164     (struct UsbDescriptorHeader *)&g_acmUnionDesc,
165     (struct UsbDescriptorHeader *)&g_acmHsNotifyDesc,
166     (struct UsbDescriptorHeader *)&g_acmDataInterfaceDesc,
167     (struct UsbDescriptorHeader *)&g_acmHsInDesc,
168     (struct UsbDescriptorHeader *)&g_acmHsOutDesc,
169     NULL,
170 };
171 
172 static struct UsbEndpointDescriptor g_acmSsInDesc = {
173     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
174     .bDescriptorType = USB_DDK_DT_ENDPOINT,
175     .bEndpointAddress = EP_ADD_DATA_IN | USB_DDK_DIR_IN,
176     .bmAttributes = USB_DDK_ENDPOINT_XFER_BULK,
177     .wMaxPacketSize = CPU_TO_LE16(SS_MAX_PACKET_SIZE),
178 };
179 
180 static struct UsbEndpointDescriptor g_acmSsOutDesc = {
181     .bLength = USB_DDK_DT_ENDPOINT_SIZE,
182     .bDescriptorType = USB_DDK_DT_ENDPOINT,
183     .bEndpointAddress = EP_ADD_DATA_OUT | USB_DDK_DIR_OUT,
184     .bmAttributes = USB_DDK_ENDPOINT_XFER_BULK,
185     .wMaxPacketSize = CPU_TO_LE16(SS_MAX_PACKET_SIZE),
186 };
187 
188 static struct UsbSsEpCompDescriptor g_acmSsBulkCompDesc = {
189     .bLength = sizeof(g_acmSsBulkCompDesc),
190     .bDescriptorType = USB_DDK_DT_SS_ENDPOINT_COMP,
191 };
192 
193 static struct UsbDescriptorHeader *g_acmSsFunction[] = {
194     (struct UsbDescriptorHeader *)&g_acmIadDescriptor,
195     (struct UsbDescriptorHeader *)&g_acmControlInterfaceDesc,
196     (struct UsbDescriptorHeader *)&g_acmHeaderDesc,
197     (struct UsbDescriptorHeader *)&g_acmCallMgmtDescriptor,
198     (struct UsbDescriptorHeader *)&g_acmDescriptor,
199     (struct UsbDescriptorHeader *)&g_acmUnionDesc,
200     (struct UsbDescriptorHeader *)&g_acmHsNotifyDesc,
201     (struct UsbDescriptorHeader *)&g_acmSsBulkCompDesc,
202     (struct UsbDescriptorHeader *)&g_acmDataInterfaceDesc,
203     (struct UsbDescriptorHeader *)&g_acmSsInDesc,
204     (struct UsbDescriptorHeader *)&g_acmSsBulkCompDesc,
205     (struct UsbDescriptorHeader *)&g_acmSsOutDesc,
206     (struct UsbDescriptorHeader *)&g_acmSsBulkCompDesc,
207     NULL,
208 };
209 
210 static struct UsbString g_acmStringDefs[] = {
211     [0].s = "CDC Abstract Control Model (ACM)", [1].s = "CDC ACM Data", [2].s = "CDC Serial", {} /* end of list */
212 };
213 
214 static struct UsbFnStrings g_acmStringTable = {
215     .language = 0x0409, /* en-us */
216     .strings = g_acmStringDefs,
217 };
218 
219 static struct UsbFnStrings *g_acmStrings[] = {
220     &g_acmStringTable,
221     NULL,
222 };
223 
224 static struct UsbFnFunction g_acmFunction = {
225     .funcName = "f_generic.0",
226     .strings = g_acmStrings,
227     .fsDescriptors = g_acmFsFunction,
228     .hsDescriptors = g_acmHsFunction,
229     .ssDescriptors = g_acmSsFunction,
230     .sspDescriptors = NULL,
231 };
232 
233 /** device **/
234 #define BCD_USB           0x0200
235 #define DEVICE_VENDOR_ID  0x12D1
236 #define DEVICE_PRODUCT_ID 0x5000
237 #define DEVICE_VERSION    0x0223
238 
239 #define USB_MAX_PACKET_SIZE 0x40
240 #define POWER               500
241 
242 #define USB_FUNC_CONFIG_IDX USB_FUNC_FIRST_AVAIL_IDX
243 #define DRIVER_DESC         "HDC Device"
244 #define CONFIG_DESC         "hdc"
245 
246 static struct UsbDeviceDescriptor g_cdcUsbFnDeviceDesc = {
247     .bLength = sizeof(g_cdcUsbFnDeviceDesc),
248     .bDescriptorType = USB_DDK_DT_DEVICE,
249     .bcdUSB = CPU_TO_LE16(BCD_USB),
250     .bDeviceClass = 0,
251     .bDeviceSubClass = 0,
252     .bDeviceProtocol = 0,
253     .bMaxPacketSize0 = USB_MAX_PACKET_SIZE,
254     .idVendor = CPU_TO_LE16(DEVICE_VENDOR_ID),
255     .idProduct = CPU_TO_LE16(DEVICE_PRODUCT_ID),
256     .bcdDevice = CPU_TO_LE16(DEVICE_VERSION),
257     .iManufacturer = USB_FUNC_MANUFACTURER_IDX,
258     .iProduct = USB_FUNC_PRODUCT_IDX,
259     .iSerialNumber = USB_FUNC_SERIAL_IDX,
260     .bNumConfigurations = 1,
261 };
262 
263 static struct UsbString g_stringsDev[] = {
264     {USB_FUNC_MANUFACTURER_IDX, "HISILICON"},
265     {USB_FUNC_PRODUCT_IDX, DRIVER_DESC},
266     {USB_FUNC_SERIAL_IDX, "0123456789POPLAR"},
267     {USB_FUNC_CONFIG_IDX, CONFIG_DESC},
268     {} /* end of list */
269 };
270 
271 static struct UsbFnStrings g_stringTabDev = {
272     .language = 0x0409, /* en-us */
273     .strings = g_stringsDev,
274 };
275 
276 static struct UsbFnStrings *g_devStrings[] = {
277     &g_stringTabDev,
278     NULL,
279 };
280 
281 static struct UsbFnFunction *g_functions[] = {
282 #ifdef CDC_ECM
283     &g_ecmFunction,
284 #endif
285 #ifdef CDC_ACM
286     &g_acmFunction,
287 #endif
288     NULL};
289 
290 static struct UsbFnConfiguration g_usbFnConfig = {
291     .configurationValue = 1,
292     .iConfiguration = USB_FUNC_CONFIG_IDX,
293     .attributes = USB_CFG_BUS_POWERED,
294     .maxPower = POWER,
295     .functions = g_functions,
296 };
297 
298 static struct UsbFnConfiguration *g_configs[] = {
299     &g_usbFnConfig,
300     NULL,
301 };
302 
303 struct UsbFnDeviceDesc g_acmFnDevice = {
304     .deviceDesc = &g_cdcUsbFnDeviceDesc,
305     .deviceStrings = g_devStrings,
306     .configs = g_configs,
307 };
308 
SerialAlloc(void)309 static struct Serial *SerialAlloc(void)
310 {
311     struct Serial *port = NULL;
312     port = (struct Serial *)OsalMemCalloc(sizeof(*port));
313     if (port == NULL) {
314         return NULL;
315     }
316     OsalMutexInit(&port->lock);
317     DListHeadInit(&port->readPool);
318     DListHeadInit(&port->readQueue);
319     DListHeadInit(&port->writePool);
320 
321     port->lineCoding.dwDTERate = CPU_TO_LE32(PORT_RATE);
322     port->lineCoding.bCharFormat = USB_CDC_1_STOP_BITS;
323     port->lineCoding.bParityType = USB_CDC_NO_PARITY;
324     port->lineCoding.bDataBits = DATA_BIT;
325     return port;
326 }
327 
ParsePipes(struct AcmDevice * acmDevice,const struct UsbFnInterface * fnIface,UsbFnInterfaceHandle handle)328 static void ParsePipes(struct AcmDevice *acmDevice, const struct UsbFnInterface *fnIface, UsbFnInterfaceHandle handle)
329 {
330     struct UsbFnPipeInfo pipeInfo = {0};
331     for (uint32_t j = 0; j < fnIface->info.numPipes; j++) {
332         int32_t ret = UsbFnGetInterfacePipeInfo((struct UsbFnInterface *)fnIface, j, &pipeInfo);
333         if (ret != HDF_SUCCESS) {
334             return;
335         }
336         if (pipeInfo.type == USB_PIPE_TYPE_INTERRUPT) {
337             acmDevice->notifyPipe.id = pipeInfo.id;
338             acmDevice->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
339             acmDevice->ctrlIface.fn = (struct UsbFnInterface *)fnIface;
340             acmDevice->ctrlIface.handle = handle;
341         } else if (pipeInfo.type == USB_PIPE_TYPE_BULK) {
342             if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
343                 acmDevice->dataInPipe.id = pipeInfo.id;
344                 acmDevice->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
345                 acmDevice->dataIface.fn = (struct UsbFnInterface *)fnIface;
346                 acmDevice->dataIface.handle = handle;
347             } else {
348                 acmDevice->dataOutPipe.id = pipeInfo.id;
349                 acmDevice->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
350                 acmDevice->dataIface.fn = (struct UsbFnInterface *)fnIface;
351                 acmDevice->dataIface.handle = handle;
352             }
353         }
354     }
355 }
356 
ParseInterfaces(struct AcmDevice * acmDevice)357 static int32_t ParseInterfaces(struct AcmDevice *acmDevice)
358 {
359     uint32_t i;
360     struct UsbFnInterface *fnIface = NULL;
361     UsbFnInterfaceHandle handle;
362 
363     for (i = 0; i < acmDevice->fnDev->numInterfaces; i++) {
364         fnIface = (struct UsbFnInterface *)UsbFnGetInterface(acmDevice->fnDev, i);
365         if (fnIface == NULL) {
366             return -1;
367         }
368         handle = UsbFnOpenInterface(fnIface);
369         if (handle == NULL) {
370             return -1;
371         }
372         ParsePipes(acmDevice, fnIface, handle);
373     }
374     return 0;
375 }
376 
CtrlComplete(uint8_t pipe,struct UsbFnRequest * req)377 static void CtrlComplete(uint8_t pipe, struct UsbFnRequest *req)
378 {
379     if (req == NULL) {
380         return;
381     }
382     struct CtrlInfo *ctrlInfo = (struct CtrlInfo *)req->context;
383     struct AcmDevice *acm = ctrlInfo->acm;
384     if (USB_REQUEST_COMPLETED != req->status) {
385         goto OUT;
386     }
387 
388     if (ctrlInfo->request == USB_DDK_CDC_REQ_SET_LINE_CODING) {
389         struct UsbCdcLineCoding *value = (struct UsbCdcLineCoding *)req->buf;
390         if (req->actual == sizeof(*value)) {
391             acm->lineCoding = *value;
392         }
393         acm->connect = true;
394     }
395 OUT:
396     DListInsertTail(&req->list, &acm->ctrlPool);
397 }
398 
AllocCtrlRequests(struct AcmDevice * acmDevice)399 static int32_t AllocCtrlRequests(struct AcmDevice *acmDevice)
400 {
401     struct DListHead *head = &acmDevice->ctrlPool;
402     struct UsbFnRequest *req = NULL;
403     struct CtrlInfo *ctrlInfo = NULL;
404     int32_t i;
405     int32_t count = 2;
406 
407     DListHeadInit(&acmDevice->ctrlPool);
408     acmDevice->ctrlReqNum = 0;
409 
410     for (i = 0; i < count; i++) {
411         ctrlInfo = (struct CtrlInfo *)OsalMemCalloc(sizeof(*ctrlInfo));
412         if (ctrlInfo == NULL) {
413             return -1;
414         }
415         ctrlInfo->acm = acmDevice;
416         req = UsbFnAllocCtrlRequest(
417             acmDevice->ctrlIface.handle, sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
418         if (req == NULL) {
419             return -1;
420         }
421         req->complete = CtrlComplete;
422         req->context = ctrlInfo;
423         DListInsertTail(&req->list, head);
424         acmDevice->ctrlReqNum++;
425     }
426 
427     return 0;
428 }
429 
SendNotifyRequest(struct AcmDevice * acm,uint8_t type,uint16_t value,const uint16_t * data,uint32_t length)430 static int32_t SendNotifyRequest(
431     struct AcmDevice *acm, uint8_t type, uint16_t value, const uint16_t *data, uint32_t length)
432 {
433     struct UsbFnRequest *req = NULL;
434     struct UsbCdcNotification *notify = NULL;
435     int32_t ret;
436     if ((data == NULL) || (acm == NULL) || (acm->ctrlIface.fn == NULL)) {
437         return -1;
438     }
439     req = acm->notifyReq;
440     if ((req == NULL) || (req->buf == NULL)) {
441         return -1;
442     }
443     acm->notifyReq = NULL;
444     acm->pending = false;
445     req->length = sizeof(*notify) + length;
446 
447     notify = (struct UsbCdcNotification *)req->buf;
448     notify->bmRequestType = USB_DDK_DIR_IN | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE;
449     notify->bNotificationType = type;
450     notify->wValue = CPU_TO_LE16(value);
451     notify->wIndex = CPU_TO_LE16(acm->ctrlIface.fn->info.index);
452     notify->wLength = CPU_TO_LE16(length);
453     if (((void *)(notify + 1) == NULL) || (length == 0)) {
454         return HDF_FAILURE;
455     }
456     ret = memcpy_s((void *)(notify + 1), length, data, length);
457     if (ret != EOK) {
458         HDF_LOGE("%s: memcpy_s fail, ret=%d", __func__, ret);
459     }
460 
461     ret = UsbFnSubmitRequestAsync(req);
462     return ret;
463 }
464 
NotifySerialState(struct AcmDevice * acm)465 static int32_t NotifySerialState(struct AcmDevice *acm)
466 {
467     int32_t ret = 0;
468     uint16_t serialState;
469 
470     OsalMutexLock(&acm->lock);
471     if (acm->notifyReq) {
472         serialState = CPU_TO_LE16(acm->serialState);
473         ret = SendNotifyRequest(acm, USB_DDK_CDC_NOTIFY_SERIAL_STATE, 0, &serialState, sizeof(acm->serialState));
474     } else {
475         acm->pending = true;
476     }
477     OsalMutexUnlock(&acm->lock);
478 
479     return ret;
480 }
481 
NotifyComplete(uint8_t pipe,struct UsbFnRequest * req)482 static void NotifyComplete(uint8_t pipe, struct UsbFnRequest *req)
483 {
484     struct AcmDevice *acm = (struct AcmDevice *)req->context;
485     bool pending = false;
486 
487     if (acm == NULL) {
488         return;
489     }
490     OsalMutexLock(&acm->lock);
491     if (req->status != USB_REQUEST_NO_DEVICE) {
492         pending = acm->pending;
493     }
494     acm->notifyReq = req;
495     OsalMutexUnlock(&acm->lock);
496     if (pending) {
497         NotifySerialState(acm);
498     }
499 }
500 
AllocNotifyRequest(struct AcmDevice * acmDevice)501 static int32_t AllocNotifyRequest(struct AcmDevice *acmDevice)
502 {
503     /* allocate notification request */
504     acmDevice->notifyReq =
505         UsbFnAllocRequest(acmDevice->ctrlIface.handle, acmDevice->notifyPipe.id, sizeof(struct UsbCdcNotification));
506     if (acmDevice->notifyReq == NULL) {
507         return -1;
508     }
509     acmDevice->notifyReq->complete = NotifyComplete;
510     acmDevice->notifyReq->context = acmDevice;
511 
512     return HDF_SUCCESS;
513 }
514 
Connect(struct AcmDevice * acm)515 static void Connect(struct AcmDevice *acm)
516 {
517     if (acm == NULL) {
518         return;
519     }
520     acm->serialState |= SERIAL_STATE_DSR | SERIAL_STATE_DCD;
521     NotifySerialState(acm);
522 }
523 
Disconnect(struct AcmDevice * acm)524 static void Disconnect(struct AcmDevice *acm)
525 {
526     if (acm == NULL) {
527         return;
528     }
529     acm->serialState &= ~(SERIAL_STATE_DSR | SERIAL_STATE_DCD);
530     NotifySerialState(acm);
531 }
532 
SendBreak(struct AcmDevice * acm,int32_t duration)533 static int32_t SendBreak(struct AcmDevice *acm, int32_t duration)
534 {
535     uint16_t state;
536 
537     if (acm == NULL) {
538         return -1;
539     }
540     state = acm->serialState;
541     state &= ~SERIAL_STATE_BREAK;
542     if (duration)
543         state |= SERIAL_STATE_BREAK;
544 
545     acm->serialState = state;
546     return NotifySerialState(acm);
547 }
548 
549 static struct AcmNotifyMethod g_notifyMethod = {
550     .Connect = Connect,
551     .Disconnect = Disconnect,
552     .SendBreak = SendBreak,
553 };
554 
Enable(struct AcmDevice * acm)555 static uint32_t Enable(struct AcmDevice *acm)
556 {
557     struct Serial *port = acm->port;
558     OsalMutexLock(&port->lock);
559     port->acm = acm;
560     acm->lineCoding = port->lineCoding;
561     if (port->refCount) {
562         if (acm->notify && acm->notify->Connect) {
563             acm->notify->Connect(acm);
564         }
565     } else {
566         if (acm->notify && acm->notify->Disconnect) {
567             acm->notify->Disconnect(acm);
568         }
569     }
570     OsalMutexUnlock(&port->lock);
571 
572     return HDF_SUCCESS;
573 }
574 
Disable(struct AcmDevice * acm)575 static uint32_t Disable(struct AcmDevice *acm)
576 {
577     (void)acm;
578     return HDF_SUCCESS;
579 }
580 
GetCtrlReq(struct AcmDevice * acm)581 static struct UsbFnRequest *GetCtrlReq(struct AcmDevice *acm)
582 {
583     struct UsbFnRequest *req = NULL;
584     struct DListHead *pool = &acm->ctrlPool;
585     if (!DListIsEmpty(pool)) {
586         req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list);
587         DListRemove(&req->list);
588     }
589     return req;
590 }
591 
Setup(struct AcmDevice * acm,const struct UsbFnCtrlRequest * setup)592 static int32_t Setup(struct AcmDevice *acm, const struct UsbFnCtrlRequest *setup)
593 {
594     struct UsbFnRequest *req = NULL;
595     struct CtrlInfo *ctrlInfo = NULL;
596     uint16_t value = LE16_TO_CPU(setup->value);
597     uint16_t length = LE16_TO_CPU(setup->length);
598     int32_t ret = 0;
599     req = GetCtrlReq(acm);
600     if (req == NULL) {
601         return ret;
602     }
603     switch (setup->request) {
604         case USB_DDK_CDC_REQ_SET_LINE_CODING:
605             if (length != sizeof(struct UsbCdcLineCoding)) {
606                 goto OUT;
607             }
608             ret = (int)length;
609             break;
610         case USB_DDK_CDC_REQ_GET_LINE_CODING:
611             ret = (length > sizeof(struct UsbCdcLineCoding)) ? sizeof(struct UsbCdcLineCoding) : length;
612             if (acm->lineCoding.dwDTERate == 0) {
613                 acm->lineCoding = acm->port->lineCoding;
614             }
615             if (memcpy_s(req->buf, req->length, &acm->lineCoding, ret) != EOK) {
616                 HDF_LOGE("%s:%d memcpy_s fail", __func__, __LINE__);
617             }
618             break;
619         case USB_DDK_CDC_REQ_SET_CONTROL_LINE_STATE:
620             ret = 0;
621             acm->handshakeBits = value;
622             break;
623         default:
624             break;
625     }
626 
627 OUT:
628     ctrlInfo = (struct CtrlInfo *)req->context;
629     ctrlInfo->request = setup->request;
630     req->length = (uint32_t)ret;
631     ret = UsbFnSubmitRequestAsync(req);
632     return ret;
633 }
634 
Suspend(struct AcmDevice * acm)635 static void Suspend(struct AcmDevice *acm)
636 {
637     struct Serial *port = acm->port;
638 
639     OsalMutexLock(&port->lock);
640     port->suspended = true;
641     OsalMutexUnlock(&port->lock);
642 }
643 
Resume(struct AcmDevice * acm)644 static void Resume(struct AcmDevice *acm)
645 {
646     struct Serial *port = acm->port;
647 
648     OsalMutexLock(&port->lock);
649     port->suspended = false;
650     if (acm->notify && acm->notify->Connect) {
651         acm->notify->Connect(acm);
652     }
653     port->startDelayed = false;
654     OsalMutexUnlock(&port->lock);
655 }
656 
AcmEventCallback(struct UsbFnEvent * event)657 void AcmEventCallback(struct UsbFnEvent *event)
658 {
659     struct AcmDevice *acm = NULL;
660 
661     if (event == NULL || event->context == NULL) {
662         return;
663     }
664     acm = (struct AcmDevice *)event->context;
665     switch (event->type) {
666         case USBFN_STATE_BIND:
667             break;
668         case USBFN_STATE_UNBIND:
669             break;
670         case USBFN_STATE_ENABLE:
671             Enable(acm);
672             break;
673         case USBFN_STATE_DISABLE:
674             Disable(acm);
675             acm->enableEvtCnt = 0;
676             break;
677         case USBFN_STATE_SETUP:
678             Setup(acm, event->setup);
679             break;
680         case USBFN_STATE_SUSPEND:
681             Suspend(acm);
682             break;
683         case USBFN_STATE_RESUME:
684             Resume(acm);
685             break;
686         default:
687             break;
688     }
689 }
690 
SetUpAcmDevice(void)691 struct AcmDevice *SetUpAcmDevice(void)
692 {
693     int32_t ret;
694 
695     struct AcmDevice *acmDevice = NULL;
696     struct UsbFnDescriptorData descData;
697     descData.type = USBFN_DESC_DATA_TYPE_DESC;
698     descData.descriptor = &g_acmFnDevice;
699     acmDevice = (struct AcmDevice *)OsalMemCalloc(sizeof(*acmDevice));
700     if (acmDevice == NULL) {
701         return NULL;
702     }
703     acmDevice->fnDev = (struct UsbFnDevice *)UsbFnCreateDevice("100e0000.hidwc3_0", &descData);
704     if (acmDevice->fnDev == NULL) {
705         return NULL;
706     }
707     acmDevice->port = (struct Serial *)SerialAlloc();
708     if (acmDevice->port == NULL) {
709         return NULL;
710     }
711     ret = ParseInterfaces(acmDevice);
712     if (ret != 0) {
713         return NULL;
714     }
715     ret = AllocCtrlRequests(acmDevice);
716     if (ret != 0) {
717         return NULL;
718     }
719     ret = AllocNotifyRequest(acmDevice);
720     if (ret != 0) {
721         return NULL;
722     }
723     ret = UsbFnStartRecvInterfaceEvent(acmDevice->ctrlIface.fn, 0xff, AcmEventCallback, acmDevice);
724     if (ret != 0) {
725         return NULL;
726     }
727     acmDevice->notify = &g_notifyMethod;
728     return acmDevice;
729 }
730 
FreeNotifyRequest(struct AcmDevice * acmDevice)731 static int32_t FreeNotifyRequest(struct AcmDevice *acmDevice)
732 {
733     int32_t ret;
734 
735     /* allocate notification request */
736     if (acmDevice->notifyReq == NULL) {
737         HDF_LOGE("%s: notifyReq is NULL", __func__);
738         return -1;
739     }
740     acmDevice->notifyReq->complete = NULL;
741     acmDevice->notifyReq->context = NULL;
742     ret = UsbFnFreeRequest(acmDevice->notifyReq);
743     if (ret != HDF_SUCCESS) {
744         HDF_LOGE("%s: free notifyReq failed", __func__);
745         return -1;
746     }
747     return HDF_SUCCESS;
748 }
749 
FreeCtrlRequests(struct AcmDevice * acmDevice)750 static int32_t FreeCtrlRequests(struct AcmDevice *acmDevice)
751 {
752     struct DListHead *head = &acmDevice->ctrlPool;
753     struct UsbFnRequest *req = NULL;
754 
755     while (!DListIsEmpty(head)) {
756         req = DLIST_FIRST_ENTRY(head, struct UsbFnRequest, list);
757         DListRemove(&req->list);
758         OsalMemFree(req->context);
759         (void)UsbFnFreeRequest(req);
760         acmDevice->ctrlReqNum--;
761     }
762     return 0;
763 }
764 
ReleaseAcmDevice(struct AcmDevice * acm)765 void ReleaseAcmDevice(struct AcmDevice *acm)
766 {
767     if (acm == NULL) {
768         HDF_LOGE("%s: acm is NULL", __func__);
769         return;
770     }
771     (void)FreeNotifyRequest(acm);
772     (void)FreeCtrlRequests(acm);
773     (void)UsbFnCloseInterface(acm->ctrlIface.handle);
774     (void)UsbFnCloseInterface(acm->dataIface.handle);
775     (void)UsbFnStopRecvInterfaceEvent(acm->ctrlIface.fn);
776     OsalMemFree(acm->port);
777 }
778 
RemoveUsbDevice(void)779 int32_t RemoveUsbDevice(void)
780 {
781     struct UsbFnDevice *device = NULL;
782     struct UsbFnDeviceMgr *devMgr = NULL;
783     struct UsbFnInterfaceMgr *intfMgr = NULL;
784     const char *udcName = "100e0000.hidwc3_0";
785     uint8_t i = 0;
786     int32_t ret;
787 
788     device = (struct UsbFnDevice *)UsbFnGetDevice(udcName);
789     if (device == NULL) {
790         HDF_LOGE("%s: get device failed", __func__);
791         return HDF_FAILURE;
792     }
793     devMgr = (struct UsbFnDeviceMgr *)device;
794     devMgr->running = false;
795     while (devMgr->running != true) {
796         i++;
797         OsalMSleep(WAIT_100MS);
798         if (i > WAIT_TIMES) {
799             HDF_LOGE("%s: wait thread exit timeout", __func__);
800             break;
801         }
802     }
803 
804     for (i = 0; i < device->numInterfaces; i++) {
805         intfMgr = devMgr->interfaceMgr + i;
806         if (intfMgr) {
807             UsbFnCloseInterface((UsbFnInterfaceHandle)intfMgr->handle);
808         }
809     }
810     for (i = 0; i < devMgr->numFunc; i++) {
811         if (intfMgr && intfMgr->isOpen) {
812             UsbFnStopRecvInterfaceEvent(&intfMgr->interface);
813         }
814     }
815     struct UsbFnAdapterOps *fnOps = UsbFnAdapterGetOps();
816     ret = OsalThreadDestroy(&devMgr->thread);
817     if (HDF_SUCCESS != ret) {
818         HDF_LOGE("%s:%d OsalThreadDestroy failed, ret = %d", __func__, __LINE__, ret);
819         return ret;
820     }
821     ret = fnOps->delDevice(devMgr->name, devMgr->udcName, devMgr->des);
822     if (ret) {
823         HDF_LOGE("%s:%d UsbFnMgrDeviceRemove failed", __func__, __LINE__);
824         return ret;
825     }
826     DListRemove(&device->object.entry);
827     UsbFnCfgMgrUnRegisterAllProp();
828 
829     return 0;
830 }
831