1 /*
2  * Copyright (c) 2021-2023 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 = CPU_TO_LE16(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 = CPU_TO_LE16(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 = CPU_TO_LE16(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 = CPU_TO_LE16(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 = CPU_TO_LE16(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 = CPU_TO_LE16(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 = CPU_TO_LE16(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)", [1].s = "CDC ACM Data", [2].s = "CDC Serial", {} /* end of list */
220 };
221 
222 static struct UsbFnStrings g_acmStringTable = {
223     .language = 0x0409, /* en-us */
224     .strings = g_acmStringDefs,
225 };
226 
227 static struct UsbFnStrings *g_acmStrings[] = {
228     &g_acmStringTable,
229     nullptr,
230 };
231 
232 static struct UsbFnFunction g_acmFunction = {
233     .funcName = "f_generic.a",
234     .strings = g_acmStrings,
235     .fsDescriptors = g_acmFsFunction,
236     .hsDescriptors = g_acmHsFunction,
237     .ssDescriptors = g_acmSsFunction,
238     .sspDescriptors = nullptr,
239 };
240 
241 /** device **/
242 #define BCD_USB           0x0200
243 #define DEVICE_VENDOR_ID  0x12D1
244 #define DEVICE_PRODUCT_ID 0x5000
245 #define DEVICE_VERSION    0x0223
246 
247 #define USB_MAX_PACKET_SIZE 0x40
248 #define POWER               500
249 
250 #define USB_FUNC_CONFIG_IDX USB_FUNC_FIRST_AVAIL_IDX
251 #define DRIVER_DESC         "HDC Device"
252 #define CONFIG_DESC         "hdc"
253 
254 static struct UsbDeviceDescriptor g_cdcUsbFnDeviceDesc = {
255     .bLength = sizeof(g_cdcUsbFnDeviceDesc),
256     .bDescriptorType = USB_DDK_DT_DEVICE,
257     .bcdUSB = CPU_TO_LE16(BCD_USB),
258     .bDeviceClass = 0,
259     .bDeviceSubClass = 0,
260     .bDeviceProtocol = 0,
261     .bMaxPacketSize0 = USB_MAX_PACKET_SIZE,
262     .idVendor = CPU_TO_LE16(DEVICE_VENDOR_ID),
263     .idProduct = CPU_TO_LE16(DEVICE_PRODUCT_ID),
264     .bcdDevice = CPU_TO_LE16(DEVICE_VERSION),
265     .iManufacturer = USB_FUNC_MANUFACTURER_IDX,
266     .iProduct = USB_FUNC_PRODUCT_IDX,
267     .iSerialNumber = USB_FUNC_SERIAL_IDX,
268     .bNumConfigurations = 1,
269 };
270 
271 static struct UsbString g_stringsDev[] = {
272     {USB_FUNC_MANUFACTURER_IDX, "HISILICON"},
273     {USB_FUNC_PRODUCT_IDX, DRIVER_DESC},
274     {USB_FUNC_SERIAL_IDX, "0123456789POPLAR"},
275     {USB_FUNC_CONFIG_IDX, CONFIG_DESC},
276     {       }  /* end of list */
277 };
278 
279 static struct UsbFnStrings g_stringTabDev = {
280     .language = 0x0409, /* en-us */
281     .strings = g_stringsDev,
282 };
283 
284 static struct UsbFnStrings *g_devStrings[] = {
285     &g_stringTabDev,
286     nullptr,
287 };
288 
289 struct UsbFnFunction *g_functions[] = {
290 #ifdef CDC_ECM
291     &g_ecmFunction,
292 #endif
293 #ifdef CDC_ACM
294     &g_acmFunction,
295 #endif
296     nullptr};
297 
298 static struct UsbFnConfiguration g_usbFnConfig = {
299     .configurationValue = 1,
300     .iConfiguration = USB_FUNC_CONFIG_IDX,
301     .attributes = USB_CFG_BUS_POWERED,
302     .maxPower = POWER,
303     .functions = g_functions,
304 };
305 
306 static struct UsbFnConfiguration *g_configs[] = {
307     &g_usbFnConfig,
308     nullptr,
309 };
310 
311 struct UsbFnDeviceDesc g_acmFnDevice = {
312     .deviceDesc = &g_cdcUsbFnDeviceDesc,
313     .deviceStrings = g_devStrings,
314     .configs = g_configs,
315 };
316 
317 enum DevUsbFnCmd {
318     DEV_USBFN_RELEASE = 1,
319 };
320 
SerialAlloc(void)321 static struct Serial *SerialAlloc(void)
322 {
323     struct Serial *port = nullptr;
324     port = static_cast<struct Serial *>(OsalMemCalloc(sizeof(*port)));
325     if (port == nullptr) {
326         return nullptr;
327     }
328     OsalMutexInit(&port->lock);
329     DListHeadInit(&port->readPool);
330     DListHeadInit(&port->readQueue);
331     DListHeadInit(&port->writePool);
332 
333     port->lineCoding.dwDTERate = CPU_TO_LE32(PORT_RATE);
334     port->lineCoding.bCharFormat = USB_CDC_1_STOP_BITS;
335     port->lineCoding.bParityType = USB_CDC_NO_PARITY;
336     port->lineCoding.bDataBits = DATA_BIT;
337     return port;
338 }
339 
ParseInterfaces(struct AcmDevice * const acmDevice)340 static int32_t ParseInterfaces(struct AcmDevice * const acmDevice)
341 {
342     uint32_t i;
343     uint32_t j;
344     struct UsbFnInterface *fnIface = nullptr;
345     UsbFnInterfaceHandle handle = nullptr;
346     int32_t ret;
347     for (i = 0; i < acmDevice->fnDev->numInterfaces; i++) {
348         fnIface = const_cast<UsbFnInterface *>(UsbFnGetInterface(acmDevice->fnDev, i));
349         if (fnIface == nullptr) {
350             return -1;
351         }
352         handle = UsbFnOpenInterface(fnIface);
353         if (handle == nullptr) {
354             return -1;
355         }
356         for (j = 0; j < fnIface->info.numPipes; j++) {
357             struct UsbFnPipeInfo pipeInfo;
358             ret = UsbFnGetInterfacePipeInfo(fnIface, j, &pipeInfo);
359             if (ret != HDF_SUCCESS) {
360                 return -1;
361             }
362             if (pipeInfo.type == USB_PIPE_TYPE_INTERRUPT) {
363                 acmDevice->notifyPipe.id = pipeInfo.id;
364                 acmDevice->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
365                 acmDevice->ctrlIface.fn = fnIface;
366                 acmDevice->ctrlIface.handle = handle;
367                 continue;
368             }
369             if (pipeInfo.type == USB_PIPE_TYPE_BULK && pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
370                 acmDevice->dataInPipe.id = pipeInfo.id;
371                 acmDevice->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
372                 acmDevice->dataIface.fn = fnIface;
373                 acmDevice->dataIface.handle = handle;
374                 continue;
375             }
376             if (pipeInfo.type == USB_PIPE_TYPE_BULK) {
377                 acmDevice->dataOutPipe.id = pipeInfo.id;
378                 acmDevice->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
379                 acmDevice->dataIface.fn = fnIface;
380                 acmDevice->dataIface.handle = handle;
381             }
382         }
383     }
384     return 0;
385 }
386 
CtrlComplete(uint8_t pipe,struct UsbFnRequest * req)387 static void CtrlComplete(uint8_t pipe, struct UsbFnRequest *req)
388 {
389     if (req == nullptr) {
390         HDF_LOGE("%{public}s:%{public}d req is nullptr", __func__, __LINE__);
391         return;
392     }
393 
394     struct CtrlInfo *ctrlInfo = static_cast<struct CtrlInfo *>(req->context);
395     struct AcmDevice *acm = ctrlInfo->acm;
396 
397     if (USB_REQUEST_COMPLETED != req->status) {
398         goto OUT;
399     }
400 
401     if (ctrlInfo->request == USB_DDK_CDC_REQ_SET_LINE_CODING) {
402         struct UsbCdcLineCoding *value = static_cast<struct UsbCdcLineCoding *>(req->buf);
403         if (req->actual == sizeof(*value)) {
404             acm->lineCoding = *value;
405         }
406     }
407 OUT:
408     DListInsertTail(&req->list, &acm->ctrlPool);
409 }
410 
AllocCtrlRequests(struct AcmDevice * acmDevice)411 static int32_t AllocCtrlRequests(struct AcmDevice *acmDevice)
412 {
413     struct DListHead *head = &acmDevice->ctrlPool;
414     struct UsbFnRequest *req = nullptr;
415     struct CtrlInfo *ctrlInfo = nullptr;
416     int32_t i;
417 
418     DListHeadInit(&acmDevice->ctrlPool);
419     acmDevice->ctrlReqNum = 0;
420 
421     for (i = 0; i < 2; i++) {
422         ctrlInfo = static_cast<struct CtrlInfo *>(OsalMemCalloc(sizeof(*ctrlInfo)));
423         if (ctrlInfo == nullptr) {
424             return -1;
425         }
426         ctrlInfo->acm = acmDevice;
427         req = UsbFnAllocCtrlRequest(
428             acmDevice->ctrlIface.handle, sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
429         if (req == nullptr) {
430             return -1;
431         }
432         req->complete = CtrlComplete;
433         req->context = ctrlInfo;
434         DListInsertTail(&req->list, head);
435         acmDevice->ctrlReqNum++;
436     }
437 
438     return 0;
439 }
440 
SendNotifyRequest(struct AcmDevice * acm,uint8_t type,uint16_t value,void * data,uint32_t length)441 static int32_t SendNotifyRequest(struct AcmDevice *acm, uint8_t type, uint16_t value, void *data, uint32_t length)
442 {
443     if (acm == nullptr) {
444         HDF_LOGE("%{public}s:%{public}d req is nullptr", __func__, __LINE__);
445         return -1;
446     }
447 
448     struct UsbFnRequest *req = nullptr;
449     struct UsbCdcNotification *notify = nullptr;
450     int32_t ret;
451 
452     req = acm->notifyReq;
453     if (req == nullptr || req->buf == nullptr) {
454         return -1;
455     }
456     acm->notifyReq = nullptr;
457     acm->pending = false;
458     req->length = sizeof(*notify) + length;
459 
460     notify = static_cast<struct UsbCdcNotification *>(req->buf);
461     notify->bmRequestType = USB_DDK_DIR_IN | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE;
462     notify->bNotificationType = type;
463     notify->wValue = CPU_TO_LE16(value);
464     notify->wIndex = CPU_TO_LE16(acm->ctrlIface.fn->info.index);
465     notify->wLength = CPU_TO_LE16(length);
466     if (memcpy_s(static_cast<void *>(notify + 1), length, data, length) != EOK) {
467         HDF_LOGE("%{public}s:memcpy_s failed", __func__);
468         return -1;
469     }
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 = CPU_TO_LE16(acm->serialState);
483         ret = SendNotifyRequest(acm, USB_DDK_CDC_NOTIFY_SERIAL_STATE, 0, &serialState, sizeof(acm->serialState));
484     } else {
485         acm->pending = true;
486     }
487     OsalMutexUnlock(&acm->lock);
488 
489     return ret;
490 }
491 
NotifyComplete(uint8_t pipe,struct UsbFnRequest * req)492 static void NotifyComplete(uint8_t pipe, struct UsbFnRequest *req)
493 {
494     struct AcmDevice *acm = static_cast<struct AcmDevice *>(req->context);
495     bool pending = false;
496 
497     if (acm == nullptr) {
498         return;
499     }
500     OsalMutexLock(&acm->lock);
501     if (req->status != USB_REQUEST_NO_DEVICE) {
502         pending = acm->pending;
503     }
504     acm->notifyReq = req;
505     OsalMutexUnlock(&acm->lock);
506     if (pending) {
507         NotifySerialState(acm);
508     }
509 }
510 
AllocNotifyRequest(struct AcmDevice * acmDevice)511 static int32_t AllocNotifyRequest(struct AcmDevice *acmDevice)
512 {
513     /* allocate notification request */
514     acmDevice->notifyReq =
515         UsbFnAllocRequest(acmDevice->ctrlIface.handle, acmDevice->notifyPipe.id, sizeof(struct UsbCdcNotification));
516     if (acmDevice->notifyReq == nullptr) {
517         return -1;
518     }
519     acmDevice->notifyReq->complete = NotifyComplete;
520     acmDevice->notifyReq->context = acmDevice;
521 
522     return HDF_SUCCESS;
523 }
524 
Connect(struct AcmDevice * acm)525 static void Connect(struct AcmDevice *acm)
526 {
527     if (acm == nullptr) {
528         return;
529     }
530     acm->serialState |= SERIAL_STATE_DSR | SERIAL_STATE_DCD;
531     NotifySerialState(acm);
532 }
533 
Disconnect(struct AcmDevice * acm)534 static void Disconnect(struct AcmDevice *acm)
535 {
536     if (acm == nullptr) {
537         return;
538     }
539     acm->serialState &= ~(SERIAL_STATE_DSR | SERIAL_STATE_DCD);
540     NotifySerialState(acm);
541 }
542 
SendBreak(struct AcmDevice * acm,int32_t duration)543 static int32_t SendBreak(struct AcmDevice *acm, int32_t duration)
544 {
545     uint16_t state;
546 
547     if (acm == nullptr) {
548         return -1;
549     }
550     state = acm->serialState;
551     state &= ~SERIAL_STATE_BREAK;
552     if (duration)
553         state |= SERIAL_STATE_BREAK;
554 
555     acm->serialState = state;
556     return NotifySerialState(acm);
557 }
558 
559 static struct AcmNotifyMethod g_notifyMethod = {
560     .connect = Connect,
561     .disconnect = Disconnect,
562     .sendBreak = SendBreak,
563 };
564 
Enable(struct AcmDevice * acm)565 static uint32_t Enable(struct AcmDevice *acm)
566 {
567     struct Serial *port = acm->port;
568     OsalMutexLock(&port->lock);
569     port->acm = acm;
570     acm->lineCoding = port->lineCoding;
571     if (port->refCount > 0) {
572         if (acm->notify && acm->notify->Connect) {
573             acm->notify->Connect(acm);
574         }
575     } else {
576         if (acm->notify && acm->notify->Disconnect) {
577             acm->notify->Disconnect(acm);
578         }
579     }
580     OsalMutexUnlock(&port->lock);
581 
582     return HDF_SUCCESS;
583 }
584 
Disable(struct AcmDevice * acm)585 static uint32_t Disable(struct AcmDevice *acm)
586 {
587     (void)acm;
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 = LE16_TO_CPU(setup->value);
607     uint16_t length = LE16_TO_CPU(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)) ? sizeof(struct UsbCdcLineCoding) : length;
622             if (acm->lineCoding.dwDTERate == 0) {
623                 acm->lineCoding = acm->port->lineCoding;
624             }
625             memcpy_s(req->buf, req->length, &acm->lineCoding, ret);
626             break;
627         case USB_DDK_CDC_REQ_SET_CONTROL_LINE_STATE:
628             ret = 0;
629             acm->handshakeBits = value;
630             break;
631         default:
632             break;
633     }
634 
635 OUT:
636     ctrlInfo = static_cast<struct CtrlInfo *>(req->context);
637     ctrlInfo->request = setup->request;
638     req->length = ret;
639     ret = UsbFnSubmitRequestAsync(req);
640 }
641 
Suspend(struct AcmDevice * acm)642 static void Suspend(struct AcmDevice *acm)
643 {
644     struct Serial *port = acm->port;
645 
646     OsalMutexLock(&port->lock);
647     port->suspended = true;
648     OsalMutexUnlock(&port->lock);
649 }
650 
Resume(struct AcmDevice * acm)651 static void Resume(struct AcmDevice *acm)
652 {
653     struct Serial *port = acm->port;
654 
655     OsalMutexLock(&port->lock);
656     port->suspended = false;
657     if (acm->notify && acm->notify->Connect) {
658         acm->notify->Connect(acm);
659     }
660     port->startDelayed = false;
661     OsalMutexUnlock(&port->lock);
662 }
663 
AcmEventCallback(struct UsbFnEvent * const event)664 void AcmEventCallback(struct UsbFnEvent * const event)
665 {
666     struct AcmDevice *acm = nullptr;
667 
668     if (event == nullptr || event->context == nullptr) {
669         return;
670     }
671     acm = static_cast<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 = static_cast<struct AcmDevice *>(OsalMemCalloc(sizeof(*acmDevice)));
707     if (acmDevice == nullptr) {
708         return nullptr;
709     }
710     acmDevice->fnDev = const_cast<struct UsbFnDevice *>(UsbFnCreateDevice("100e0000.hidwc3_0", &descData));
711     if (acmDevice->fnDev == nullptr) {
712         return nullptr;
713     }
714     acmDevice->port = 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 * const acmDevice)757 static int32_t FreeCtrlRequests(struct AcmDevice * const 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