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