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