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