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