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