1beacf11bSopenharmony_ci/****************************************************************************
2beacf11bSopenharmony_ci * drivers/usbdev/cdcacm.c
3beacf11bSopenharmony_ci *
4beacf11bSopenharmony_ci *   Copyright (C) 2011-2013, 2016-2017 Gregory Nutt. All rights reserved.
5beacf11bSopenharmony_ci *   Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
6beacf11bSopenharmony_ci *   Author: Gregory Nutt <gnutt@nuttx.org>
7beacf11bSopenharmony_ci *
8beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without
9beacf11bSopenharmony_ci * modification, are permitted provided that the following conditions
10beacf11bSopenharmony_ci * are met:
11beacf11bSopenharmony_ci *
12beacf11bSopenharmony_ci * 1. Redistributions of source code must retain the above copyright
13beacf11bSopenharmony_ci *    notice, this list of conditions and the following disclaimer.
14beacf11bSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
15beacf11bSopenharmony_ci *    notice, this list of conditions and the following disclaimer in
16beacf11bSopenharmony_ci *    the documentation and/or other materials provided with the
17beacf11bSopenharmony_ci *    distribution.
18beacf11bSopenharmony_ci * 3. Neither the name NuttX nor the names of its contributors may be
19beacf11bSopenharmony_ci *    used to endorse or promote products derived from this software
20beacf11bSopenharmony_ci *    without specific prior written permission.
21beacf11bSopenharmony_ci *
22beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23beacf11bSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24beacf11bSopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25beacf11bSopenharmony_ci * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26beacf11bSopenharmony_ci * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27beacf11bSopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28beacf11bSopenharmony_ci * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29beacf11bSopenharmony_ci * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30beacf11bSopenharmony_ci * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31beacf11bSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32beacf11bSopenharmony_ci * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33beacf11bSopenharmony_ci * POSSIBILITY OF SUCH DAMAGE.
34beacf11bSopenharmony_ci *
35beacf11bSopenharmony_ci ****************************************************************************/
36beacf11bSopenharmony_ci/****************************************************************************
37beacf11bSopenharmony_ci * Notice of Export Control Law
38beacf11bSopenharmony_ci * ===============================================
39beacf11bSopenharmony_ci * Huawei LiteOS may be subject to applicable export control laws and regulations,
40beacf11bSopenharmony_ci * which might include those applicable to Huawei LiteOS of U.S. and the country in
41beacf11bSopenharmony_ci * which you are located.
42beacf11bSopenharmony_ci * Import, export and usage of Huawei LiteOS in any manner by you shall be in
43beacf11bSopenharmony_ci * compliance with such applicable export control laws and regulations.
44beacf11bSopenharmony_ci ****************************************************************************/
45beacf11bSopenharmony_ci
46beacf11bSopenharmony_ci/****************************************************************************
47beacf11bSopenharmony_ci * Included Files
48beacf11bSopenharmony_ci ****************************************************************************/
49beacf11bSopenharmony_ci
50beacf11bSopenharmony_ci#include <los_event.h>
51beacf11bSopenharmony_ci#include <fs/fs.h>
52beacf11bSopenharmony_ci#include <los_magickey.h>
53beacf11bSopenharmony_ci#include <console.h>
54beacf11bSopenharmony_ci#include <los_hwi.h>
55beacf11bSopenharmony_ci#include <linux/spinlock.h>
56beacf11bSopenharmony_ci#include "cdcacm.h"
57beacf11bSopenharmony_ci#include "gadget/usbdev.h"
58beacf11bSopenharmony_ci
59beacf11bSopenharmony_ci#ifdef CDCACM_DEBUG
60beacf11bSopenharmony_ci#define FALOG(x...)   dprintf(x)
61beacf11bSopenharmony_ci#else
62beacf11bSopenharmony_ci#define FALOG(x...)   do{}while(0)
63beacf11bSopenharmony_ci#endif
64beacf11bSopenharmony_ci
65beacf11bSopenharmony_ci/****************************************************************************
66beacf11bSopenharmony_ci * Pre-processor Definitions
67beacf11bSopenharmony_ci ****************************************************************************/
68beacf11bSopenharmony_ci
69beacf11bSopenharmony_civolatile unsigned int g_usbSerialMask;
70beacf11bSopenharmony_ci
71beacf11bSopenharmony_ci/****************************************************************************
72beacf11bSopenharmony_ci * Private Types
73beacf11bSopenharmony_ci ****************************************************************************/
74beacf11bSopenharmony_ci
75beacf11bSopenharmony_ci/* Container to support a list of requests */
76beacf11bSopenharmony_ci
77beacf11bSopenharmony_cistruct cdcacm_wrreq_s
78beacf11bSopenharmony_ci{
79beacf11bSopenharmony_ci  struct usbdev_req_s *req;               /* The contained request */
80beacf11bSopenharmony_ci  char *data_buffer;                      /* Ringbuffer starting address ,this is data buffer yet */
81beacf11bSopenharmony_ci  char *receive_buffer;                   /* Record the offset of the received data */
82beacf11bSopenharmony_ci  char *send_buffer;                      /* Record the offset of the sent data */
83beacf11bSopenharmony_ci};
84beacf11bSopenharmony_ci
85beacf11bSopenharmony_cistruct cdcacm_rdreq_s
86beacf11bSopenharmony_ci{
87beacf11bSopenharmony_ci  struct usbdev_req_s *req;               /* The contained request */
88beacf11bSopenharmony_ci  void *buf;                              /* The read event buffer */
89beacf11bSopenharmony_ci  size_t buflen;                          /* Offset to valid data in the RX request */
90beacf11bSopenharmony_ci};
91beacf11bSopenharmony_ci
92beacf11bSopenharmony_ci/* This structure describes the internal state of the driver */
93beacf11bSopenharmony_ci
94beacf11bSopenharmony_cistruct cdcacm_dev_s
95beacf11bSopenharmony_ci{
96beacf11bSopenharmony_ci  struct usbdev_s *usbdev;                /* Usb device pointer */
97beacf11bSopenharmony_ci  uint8_t config;                         /* Configuration number */
98beacf11bSopenharmony_ci  uint16_t serialstate;                   /* State of the DSR/DCD */
99beacf11bSopenharmony_ci  bool bdisconnect;                       /* Flags of device action */
100beacf11bSopenharmony_ci  bool wating;                            /* if notify request is NULL, try submit(notify, req) again */
101beacf11bSopenharmony_ci  bool received_char;                     /* Flags of write event */
102beacf11bSopenharmony_ci  atomic_t shutdown;                      /* Device shutdown when transfer data */
103beacf11bSopenharmony_ci  atomic_t send_char;                     /* Flag of read event */
104beacf11bSopenharmony_ci
105beacf11bSopenharmony_ci  struct usb_cdc_line_state  linecoding;  /* Buffered line status */
106beacf11bSopenharmony_ci  struct usbdev_ep_s *epintin;            /* Interrupt IN endpoint structure */
107beacf11bSopenharmony_ci  struct usbdev_ep_s *epbulkin;           /* Bulk IN endpoint structure */
108beacf11bSopenharmony_ci  struct usbdev_ep_s *epbulkout;          /* Bulk OUT endpoint structure */
109beacf11bSopenharmony_ci  bool epintin_enabled;                   /* Interrupt IN endpoint enable flag */
110beacf11bSopenharmony_ci  bool epbulkin_enabled;                  /* Bulk IN endpoint enable flag */
111beacf11bSopenharmony_ci  bool epbulkout_enabled;                 /* Bulk OUT endpoint enable flag */
112beacf11bSopenharmony_ci  struct usbdev_req_s *ctrlreq;           /* Allocated control request */
113beacf11bSopenharmony_ci  struct usbdev_devinfo_s devinfo;
114beacf11bSopenharmony_ci
115beacf11bSopenharmony_ci  /* Pre-allocated write request containers.  The write requests will
116beacf11bSopenharmony_ci   * be save here, and used to send requests to EPBULKIN ; Read requests
117beacf11bSopenharmony_ci   * will be save in the EBULKOUT.
118beacf11bSopenharmony_ci   */
119beacf11bSopenharmony_ci
120beacf11bSopenharmony_ci  struct cdcacm_wrreq_s wrreqs;           /* Serial write buffer */
121beacf11bSopenharmony_ci  struct cdcacm_rdreq_s rdreqs;           /* Serial read buffer */
122beacf11bSopenharmony_ci  EVENT_CB_S read_event;                  /* Read event */
123beacf11bSopenharmony_ci  uint8_t ctrl_id;                        /* Control id of Interface-IDs */
124beacf11bSopenharmony_ci  uint8_t data_id;                        /* Data id of Interface-IDs */
125beacf11bSopenharmony_ci  spinlock_t acm_lock;                    /* Spinlock */
126beacf11bSopenharmony_ci  uint32_t read_offset;                   /* Quick command offset */
127beacf11bSopenharmony_ci};
128beacf11bSopenharmony_ci
129beacf11bSopenharmony_ci/* The internal version of the class driver */
130beacf11bSopenharmony_ci
131beacf11bSopenharmony_cistruct cdcacm_driver_s
132beacf11bSopenharmony_ci{
133beacf11bSopenharmony_ci  struct usbdevclass_driver_s drvr;
134beacf11bSopenharmony_ci  struct cdcacm_dev_s     *dev;
135beacf11bSopenharmony_ci};
136beacf11bSopenharmony_ci
137beacf11bSopenharmony_ci/* This is what is allocated */
138beacf11bSopenharmony_ci
139beacf11bSopenharmony_cistruct cdcacm_alloc_s
140beacf11bSopenharmony_ci{
141beacf11bSopenharmony_ci  struct cdcacm_dev_s    dev;
142beacf11bSopenharmony_ci  struct cdcacm_driver_s drvr;
143beacf11bSopenharmony_ci};
144beacf11bSopenharmony_ci
145beacf11bSopenharmony_ciint usbdev_cdcacm_initialize (FAR struct module *mod, int n, FAR void *arg);
146beacf11bSopenharmony_ci
147beacf11bSopenharmony_ci/* Device driver structure definition */
148beacf11bSopenharmony_ci
149beacf11bSopenharmony_cistatic driver_t g_fcdcacm_driver_t =
150beacf11bSopenharmony_ci{
151beacf11bSopenharmony_ci  .name     = "fcdcacm",
152beacf11bSopenharmony_ci  .methods  = NULL,
153beacf11bSopenharmony_ci  .size     = sizeof(struct cdcacm_alloc_s)
154beacf11bSopenharmony_ci};
155beacf11bSopenharmony_ci
156beacf11bSopenharmony_ci/* Private device class information */
157beacf11bSopenharmony_ci
158beacf11bSopenharmony_cistatic devclass_t g_fcdcacm_devclass;
159beacf11bSopenharmony_ciDRIVER_MODULE(fcdcacm, simple, g_fcdcacm_driver_t, g_fcdcacm_devclass, usbdev_cdcacm_initialize, 0);
160beacf11bSopenharmony_ci
161beacf11bSopenharmony_ciatomic_t g_magickey = 0;
162beacf11bSopenharmony_cibool g_readpend = false;
163beacf11bSopenharmony_ci
164beacf11bSopenharmony_ci/****************************************************************************
165beacf11bSopenharmony_ci * Private Function Prototypes
166beacf11bSopenharmony_ci ****************************************************************************/
167beacf11bSopenharmony_ci
168beacf11bSopenharmony_ci/* Transfer helpers *********************************************************/
169beacf11bSopenharmony_ci
170beacf11bSopenharmony_cistatic int      cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv,
171beacf11bSopenharmony_ci                  FAR struct cdcacm_wrreq_s *wrcontainer);
172beacf11bSopenharmony_cistatic int      cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
173beacf11bSopenharmony_ci                  FAR struct cdcacm_rdreq_s *rdcontainer);
174beacf11bSopenharmony_cistatic int      cdcacm_requeue_rdrequest(FAR struct cdcacm_dev_s *priv,
175beacf11bSopenharmony_ci                  FAR struct cdcacm_rdreq_s *rdcontainer);
176beacf11bSopenharmony_cistatic ssize_t  cdcacm_release_rxpending(FAR struct file *filep,
177beacf11bSopenharmony_ci                  FAR char *buffer, size_t buflen);
178beacf11bSopenharmony_ci
179beacf11bSopenharmony_ci/* Request helpers *********************************************************/
180beacf11bSopenharmony_ci
181beacf11bSopenharmony_cistatic struct usbdev_req_s *cdcacm_allocreq(FAR struct usbdev_ep_s *ep,
182beacf11bSopenharmony_ci                              uint16_t len);
183beacf11bSopenharmony_cistatic void                 cdcacm_freereq(FAR struct usbdev_ep_s *ep,
184beacf11bSopenharmony_ci                              FAR struct usbdev_req_s *req);
185beacf11bSopenharmony_ci
186beacf11bSopenharmony_ci/* Configuration ***********************************************************/
187beacf11bSopenharmony_ci
188beacf11bSopenharmony_cistatic void    cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv);
189beacf11bSopenharmony_ci
190beacf11bSopenharmony_cistatic int     cdcacm_epconfigure(FAR struct usbdev_ep_s *ep,
191beacf11bSopenharmony_ci                 enum cdcacm_epdesc_e epid,
192beacf11bSopenharmony_ci                 FAR const usb_endpoint_descriptor_t *ep_desc,
193beacf11bSopenharmony_ci                 FAR struct usbdev_s *dev,
194beacf11bSopenharmony_ci                 bool last);
195beacf11bSopenharmony_ci
196beacf11bSopenharmony_cistatic int     cdcacm_setconfig(FAR struct cdcacm_dev_s *priv,
197beacf11bSopenharmony_ci                 FAR struct usbdev_s *dev);
198beacf11bSopenharmony_ci
199beacf11bSopenharmony_ci/* Completion event handlers ***********************************************/
200beacf11bSopenharmony_ci
201beacf11bSopenharmony_cistatic void    cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
202beacf11bSopenharmony_ci                 FAR struct usbdev_req_s *req);
203beacf11bSopenharmony_cistatic void    cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
204beacf11bSopenharmony_ci                 FAR struct usbdev_req_s *req);
205beacf11bSopenharmony_ci
206beacf11bSopenharmony_ci/* USB class device ********************************************************/
207beacf11bSopenharmony_ci
208beacf11bSopenharmony_cistatic int     cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
209beacf11bSopenharmony_ci                 FAR struct usbdev_s *dev);
210beacf11bSopenharmony_cistatic int     cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
211beacf11bSopenharmony_ci                 FAR struct usbdev_s *dev);
212beacf11bSopenharmony_cistatic int     cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
213beacf11bSopenharmony_ci                 FAR struct usbdev_s *dev,
214beacf11bSopenharmony_ci                 FAR const struct usb_device_request *ctrl, uint8_t *dataout,
215beacf11bSopenharmony_ci                 size_t outlen);
216beacf11bSopenharmony_cistatic int     cdcacm_serial_connect(FAR struct cdcacm_dev_s *priv);
217beacf11bSopenharmony_cistatic int     cdcacm_serial_disconnect(FAR struct cdcacm_dev_s *priv);
218beacf11bSopenharmony_cistatic void    cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
219beacf11bSopenharmony_ci                 FAR struct usbdev_s *dev);
220beacf11bSopenharmony_cistatic ssize_t cdcuart_write(FAR struct file *filep,
221beacf11bSopenharmony_ci                 FAR const char *buffer, size_t buflen);
222beacf11bSopenharmony_cistatic int     cdcuart_open(FAR struct file *filep);
223beacf11bSopenharmony_cistatic int     cdcuart_ioctl(FAR struct file *filep,
224beacf11bSopenharmony_ci                 int cmd, unsigned long arg);
225beacf11bSopenharmony_ci
226beacf11bSopenharmony_ci/****************************************************************************
227beacf11bSopenharmony_ci * Private Data
228beacf11bSopenharmony_ci ****************************************************************************/
229beacf11bSopenharmony_ci
230beacf11bSopenharmony_cistatic const struct file_operations_vfs g_vfs_ops =
231beacf11bSopenharmony_ci{
232beacf11bSopenharmony_ci  .open   = cdcuart_open,
233beacf11bSopenharmony_ci  .close  = NULL,
234beacf11bSopenharmony_ci  .read   = cdcacm_release_rxpending,
235beacf11bSopenharmony_ci  .write  = cdcuart_write,
236beacf11bSopenharmony_ci  .seek   = NULL,
237beacf11bSopenharmony_ci  .ioctl  = cdcuart_ioctl,
238beacf11bSopenharmony_ci  .mmap   = NULL,
239beacf11bSopenharmony_ci#ifndef CONFIG_DISABLE_POLL
240beacf11bSopenharmony_ci  .poll   = NULL,
241beacf11bSopenharmony_ci#endif
242beacf11bSopenharmony_ci  .unlink = NULL,
243beacf11bSopenharmony_ci};
244beacf11bSopenharmony_ci
245beacf11bSopenharmony_ci/* USB class device *********************************************************/
246beacf11bSopenharmony_ci
247beacf11bSopenharmony_cistatic struct usbdevclass_driverops_s g_driver_ops =
248beacf11bSopenharmony_ci{
249beacf11bSopenharmony_ci  cdcacm_bind,           /* bind */
250beacf11bSopenharmony_ci  cdcacm_unbind,         /* unbind */
251beacf11bSopenharmony_ci  cdcacm_setup,          /* setup */
252beacf11bSopenharmony_ci  cdcacm_disconnect,     /* disconnect */
253beacf11bSopenharmony_ci  NULL,                  /* suspend */
254beacf11bSopenharmony_ci  NULL,                  /* resume */
255beacf11bSopenharmony_ci};
256beacf11bSopenharmony_ci
257beacf11bSopenharmony_cistatic void cdcacm_receive_buf(struct cdcacm_wrreq_s *wrcontainer,
258beacf11bSopenharmony_ci                               FAR const char *buffer,
259beacf11bSopenharmony_ci                               size_t buflen)
260beacf11bSopenharmony_ci{
261beacf11bSopenharmony_ci  int ret;
262beacf11bSopenharmony_ci
263beacf11bSopenharmony_ci  /* Determine if the receive_buffer pointer is offset at the end of the ringbuffer */
264beacf11bSopenharmony_ci
265beacf11bSopenharmony_ci  const size_t length = RING_BUFFER_SIZE - (wrcontainer->receive_buffer - wrcontainer->data_buffer);
266beacf11bSopenharmony_ci  if (length > buflen)
267beacf11bSopenharmony_ci    {
268beacf11bSopenharmony_ci      ret = usbd_copy_from_user(wrcontainer->receive_buffer, length,
269beacf11bSopenharmony_ci                                buffer, buflen);
270beacf11bSopenharmony_ci      if (ret != EOK)
271beacf11bSopenharmony_ci        {
272beacf11bSopenharmony_ci          usb_err("Copy from user failed!\r\n");
273beacf11bSopenharmony_ci          return;
274beacf11bSopenharmony_ci        }
275beacf11bSopenharmony_ci      wrcontainer->receive_buffer += buflen;
276beacf11bSopenharmony_ci    }
277beacf11bSopenharmony_ci  else
278beacf11bSopenharmony_ci    {
279beacf11bSopenharmony_ci      /* The length of console data is bigger than receive_buffer length.
280beacf11bSopenharmony_ci       * The second parameter "length" is the currently available remaining length of the ringbuffer.
281beacf11bSopenharmony_ci       */
282beacf11bSopenharmony_ci
283beacf11bSopenharmony_ci      ret = usbd_copy_from_user(wrcontainer->receive_buffer, length,
284beacf11bSopenharmony_ci                                buffer, length);
285beacf11bSopenharmony_ci      if (ret)
286beacf11bSopenharmony_ci        {
287beacf11bSopenharmony_ci          usb_err("Copy from user failed!\r\n");
288beacf11bSopenharmony_ci          return;
289beacf11bSopenharmony_ci        }
290beacf11bSopenharmony_ci      buffer += length;
291beacf11bSopenharmony_ci      ret = usbd_copy_from_user(wrcontainer->data_buffer, RING_BUFFER_SIZE,
292beacf11bSopenharmony_ci                                buffer, buflen - length);
293beacf11bSopenharmony_ci      if (ret != EOK)
294beacf11bSopenharmony_ci        {
295beacf11bSopenharmony_ci          usb_err("Copy from user failed!\r\n");
296beacf11bSopenharmony_ci          return;
297beacf11bSopenharmony_ci        }
298beacf11bSopenharmony_ci      wrcontainer->receive_buffer = wrcontainer->data_buffer + buflen - length;
299beacf11bSopenharmony_ci    }
300beacf11bSopenharmony_ci}
301beacf11bSopenharmony_ci
302beacf11bSopenharmony_cistatic ssize_t cdcuart_write(FAR struct file *filep,
303beacf11bSopenharmony_ci                             FAR const char *buffer,
304beacf11bSopenharmony_ci                             size_t buflen)
305beacf11bSopenharmony_ci{
306beacf11bSopenharmony_ci  struct cdcacm_dev_s *priv;
307beacf11bSopenharmony_ci  struct cdcacm_wrreq_s *wrcontainer;
308beacf11bSopenharmony_ci  int ret;
309beacf11bSopenharmony_ci  uint32_t flags;
310beacf11bSopenharmony_ci
311beacf11bSopenharmony_ci  struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
312beacf11bSopenharmony_ci  priv = (struct cdcacm_dev_s *)drv->priv;
313beacf11bSopenharmony_ci  if (priv == NULL)
314beacf11bSopenharmony_ci    {
315beacf11bSopenharmony_ci      usb_err("file write failed!\r\n");
316beacf11bSopenharmony_ci      return -ENODEV;
317beacf11bSopenharmony_ci    }
318beacf11bSopenharmony_ci
319beacf11bSopenharmony_ci  wrcontainer = &priv->wrreqs;
320beacf11bSopenharmony_ci  if (buflen)
321beacf11bSopenharmony_ci    {
322beacf11bSopenharmony_ci      cdcacm_receive_buf(wrcontainer, buffer, buflen);
323beacf11bSopenharmony_ci    }
324beacf11bSopenharmony_ci  spin_lock_irqsave(&priv->acm_lock, flags);
325beacf11bSopenharmony_ci  ret = cdcacm_sndpacket(priv, wrcontainer);
326beacf11bSopenharmony_ci  spin_unlock_irqrestore(&priv->acm_lock, flags);
327beacf11bSopenharmony_ci  if (ret < 0)
328beacf11bSopenharmony_ci    {
329beacf11bSopenharmony_ci      usb_err("file write failed!\r\n");
330beacf11bSopenharmony_ci    }
331beacf11bSopenharmony_ci
332beacf11bSopenharmony_ci  return ret;
333beacf11bSopenharmony_ci}
334beacf11bSopenharmony_ci
335beacf11bSopenharmony_ci/****************************************************************************
336beacf11bSopenharmony_ci * Name: cdcacm_sndpacket
337beacf11bSopenharmony_ci *
338beacf11bSopenharmony_ci * Description:
339beacf11bSopenharmony_ci *   This function obtains write requests, transfers the TX data into the
340beacf11bSopenharmony_ci *   request, and submits the requests to the USB controller.  This
341beacf11bSopenharmony_ci *   continues until either (1) there are no further packets available, or
342beacf11bSopenharmony_ci *   (2) there is no further data to send.
343beacf11bSopenharmony_ci *
344beacf11bSopenharmony_ci ****************************************************************************/
345beacf11bSopenharmony_ci
346beacf11bSopenharmony_cistatic int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv,
347beacf11bSopenharmony_ci                            FAR struct cdcacm_wrreq_s *wrcontainer)
348beacf11bSopenharmony_ci{
349beacf11bSopenharmony_ci  FAR struct usbdev_ep_s *ep;
350beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
351beacf11bSopenharmony_ci  size_t data_size;
352beacf11bSopenharmony_ci  size_t reqlen;
353beacf11bSopenharmony_ci  int ret = 0;
354beacf11bSopenharmony_ci  uint32_t length;
355beacf11bSopenharmony_ci
356beacf11bSopenharmony_ci  if (priv == NULL)
357beacf11bSopenharmony_ci    {
358beacf11bSopenharmony_ci      return -EINVAL;
359beacf11bSopenharmony_ci    }
360beacf11bSopenharmony_ci
361beacf11bSopenharmony_ci  ep  = priv->epbulkin;
362beacf11bSopenharmony_ci  req = wrcontainer->req;
363beacf11bSopenharmony_ci
364beacf11bSopenharmony_ci#ifdef DWC3_USB_SERIAL
365beacf11bSopenharmony_ci  reqlen = CONFIG_CDCACM_EPBULKIN_HSSIZE;
366beacf11bSopenharmony_ci#else
367beacf11bSopenharmony_ci  reqlen = CONFIG_CDCACM_EPBULKIN_FSSIZE;
368beacf11bSopenharmony_ci#endif
369beacf11bSopenharmony_ci
370beacf11bSopenharmony_ci  while (priv->received_char == false)
371beacf11bSopenharmony_ci    {
372beacf11bSopenharmony_ci      /* The data need to submit to host */
373beacf11bSopenharmony_ci
374beacf11bSopenharmony_ci      data_size = (RING_BUFFER_SIZE + (wrcontainer->receive_buffer - wrcontainer->send_buffer)) % RING_BUFFER_SIZE;
375beacf11bSopenharmony_ci
376beacf11bSopenharmony_ci      /* Stitching the beginning and end of the ringbuffer */
377beacf11bSopenharmony_ci
378beacf11bSopenharmony_ci      length = RING_BUFFER_SIZE - (wrcontainer->send_buffer - wrcontainer->data_buffer);
379beacf11bSopenharmony_ci      if (data_size == 0)
380beacf11bSopenharmony_ci        {
381beacf11bSopenharmony_ci          break;
382beacf11bSopenharmony_ci        }
383beacf11bSopenharmony_ci      if (data_size > MAX_PACKET_SIZE)
384beacf11bSopenharmony_ci        {
385beacf11bSopenharmony_ci          data_size = MAX_PACKET_SIZE;
386beacf11bSopenharmony_ci        }
387beacf11bSopenharmony_ci      if (length < data_size)
388beacf11bSopenharmony_ci        {
389beacf11bSopenharmony_ci          ret = memcpy_s(req->buf, reqlen, wrcontainer->send_buffer, length);
390beacf11bSopenharmony_ci          if (ret != EOK)
391beacf11bSopenharmony_ci            {
392beacf11bSopenharmony_ci              usb_err("Memcpy failed!\r\n");
393beacf11bSopenharmony_ci              return ret;
394beacf11bSopenharmony_ci            }
395beacf11bSopenharmony_ci          ret = memcpy_s(req->buf + length, reqlen, wrcontainer->data_buffer, data_size - length);
396beacf11bSopenharmony_ci          if (ret != EOK)
397beacf11bSopenharmony_ci            {
398beacf11bSopenharmony_ci              usb_err("Memcpy failed!\r\n");
399beacf11bSopenharmony_ci              return ret;
400beacf11bSopenharmony_ci            }
401beacf11bSopenharmony_ci          wrcontainer->send_buffer = wrcontainer->data_buffer + data_size - length;
402beacf11bSopenharmony_ci        }
403beacf11bSopenharmony_ci      else
404beacf11bSopenharmony_ci        {
405beacf11bSopenharmony_ci          ret = memcpy_s(req->buf, data_size, wrcontainer->send_buffer, data_size);
406beacf11bSopenharmony_ci          if (ret != EOK)
407beacf11bSopenharmony_ci            {
408beacf11bSopenharmony_ci              usb_err("memcpy_s failed!\r\n");
409beacf11bSopenharmony_ci              return ret;
410beacf11bSopenharmony_ci            }
411beacf11bSopenharmony_ci          wrcontainer->send_buffer += data_size;
412beacf11bSopenharmony_ci        }
413beacf11bSopenharmony_ci
414beacf11bSopenharmony_ci      priv->received_char = true;
415beacf11bSopenharmony_ci
416beacf11bSopenharmony_ci      /* Fill the request with serial TX data.
417beacf11bSopenharmony_ci       * Then submit the request to the endpoint.
418beacf11bSopenharmony_ci       */
419beacf11bSopenharmony_ci
420beacf11bSopenharmony_ci      req->len  = data_size;
421beacf11bSopenharmony_ci      req->priv = wrcontainer;
422beacf11bSopenharmony_ci      ret       = EP_SUBMIT(ep, req);
423beacf11bSopenharmony_ci      if (ret != OK)
424beacf11bSopenharmony_ci        {
425beacf11bSopenharmony_ci          usb_err("submit filed!\r\n");
426beacf11bSopenharmony_ci          priv->received_char = false;
427beacf11bSopenharmony_ci        }
428beacf11bSopenharmony_ci    }
429beacf11bSopenharmony_ci  return ret;
430beacf11bSopenharmony_ci}
431beacf11bSopenharmony_ci
432beacf11bSopenharmony_cistatic int cdcacm_fill_rdrequest(struct cdcacm_dev_s *priv,
433beacf11bSopenharmony_ci                                 struct cdcacm_rdreq_s *rdcontainer,
434beacf11bSopenharmony_ci                                 size_t buflen)
435beacf11bSopenharmony_ci{
436beacf11bSopenharmony_ci  struct usbdev_req_s *req;
437beacf11bSopenharmony_ci  char *req_buf;
438beacf11bSopenharmony_ci  char *read_buf;
439beacf11bSopenharmony_ci  int nbytes;
440beacf11bSopenharmony_ci  int ret;
441beacf11bSopenharmony_ci
442beacf11bSopenharmony_ci  req = rdcontainer->req;
443beacf11bSopenharmony_ci  read_buf = rdcontainer->buf;
444beacf11bSopenharmony_ci  req_buf  = (char *)req->buf;
445beacf11bSopenharmony_ci
446beacf11bSopenharmony_ci  /* Copy character into read buffer and retrun the nbytes */
447beacf11bSopenharmony_ci
448beacf11bSopenharmony_ci  ret = usbd_copy_to_user(read_buf, req->len, (req_buf + priv->read_offset), buflen);
449beacf11bSopenharmony_ci  if (ret != EOK)
450beacf11bSopenharmony_ci    {
451beacf11bSopenharmony_ci      usb_err("memcpy_s failed, %d\n", ret);
452beacf11bSopenharmony_ci      return -1;
453beacf11bSopenharmony_ci    }
454beacf11bSopenharmony_ci
455beacf11bSopenharmony_ci  nbytes = (int)buflen;
456beacf11bSopenharmony_ci  priv->read_offset += buflen;
457beacf11bSopenharmony_ci
458beacf11bSopenharmony_ci  if (priv->read_offset < req->xfrd)
459beacf11bSopenharmony_ci    {
460beacf11bSopenharmony_ci      ret = (int)LOS_EventWrite(&priv->read_event, USB_SERIAL_READ_EVENT);
461beacf11bSopenharmony_ci      if (ret != OK)
462beacf11bSopenharmony_ci        {
463beacf11bSopenharmony_ci          usb_err("write event failed!\n");
464beacf11bSopenharmony_ci          return -1;
465beacf11bSopenharmony_ci        }
466beacf11bSopenharmony_ci      return nbytes;
467beacf11bSopenharmony_ci    }
468beacf11bSopenharmony_ci  atomic_set(&priv->send_char, 0);
469beacf11bSopenharmony_ci  priv->read_offset = 0;
470beacf11bSopenharmony_ci  return nbytes;
471beacf11bSopenharmony_ci}
472beacf11bSopenharmony_ci
473beacf11bSopenharmony_ci/****************************************************************************
474beacf11bSopenharmony_ci * Name: cdcacm_recvpacket
475beacf11bSopenharmony_ci *
476beacf11bSopenharmony_ci * Description:
477beacf11bSopenharmony_ci *   A normal completion event was received by the read completion handler
478beacf11bSopenharmony_ci *   at the interrupt level (with interrupts disabled).  This function handles
479beacf11bSopenharmony_ci *   the USB packet and provides the received data to the uart RX buffer.
480beacf11bSopenharmony_ci *
481beacf11bSopenharmony_ci * Assumptions:
482beacf11bSopenharmony_ci *   Called from the USB interrupt handler with interrupts disabled.
483beacf11bSopenharmony_ci *
484beacf11bSopenharmony_ci ****************************************************************************/
485beacf11bSopenharmony_ci
486beacf11bSopenharmony_cistatic int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
487beacf11bSopenharmony_ci                             FAR struct cdcacm_rdreq_s *rdcontainer)
488beacf11bSopenharmony_ci{
489beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
490beacf11bSopenharmony_ci  size_t buflen;
491beacf11bSopenharmony_ci  int nbytes = 0;
492beacf11bSopenharmony_ci
493beacf11bSopenharmony_ci  if (priv == NULL || rdcontainer == NULL)
494beacf11bSopenharmony_ci    {
495beacf11bSopenharmony_ci      usb_err("device unavailable!\r\n");
496beacf11bSopenharmony_ci      return -ENODEV;
497beacf11bSopenharmony_ci    }
498beacf11bSopenharmony_ci
499beacf11bSopenharmony_ci  if (atomic_read(&g_magickey) == 1)
500beacf11bSopenharmony_ci    {
501beacf11bSopenharmony_ci      buflen = 1;
502beacf11bSopenharmony_ci    }
503beacf11bSopenharmony_ci  else
504beacf11bSopenharmony_ci    {
505beacf11bSopenharmony_ci      buflen = rdcontainer->buflen;
506beacf11bSopenharmony_ci    }
507beacf11bSopenharmony_ci
508beacf11bSopenharmony_ci  if (g_readpend == true && atomic_read(&g_magickey) == 0)
509beacf11bSopenharmony_ci    {
510beacf11bSopenharmony_ci      (void)LOS_EventRead(&priv->read_event, USB_SERIAL_READ_EVENT,
511beacf11bSopenharmony_ci                          LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER);
512beacf11bSopenharmony_ci    }
513beacf11bSopenharmony_ci
514beacf11bSopenharmony_ci  req = rdcontainer->req;
515beacf11bSopenharmony_ci  if (req == NULL)
516beacf11bSopenharmony_ci    {
517beacf11bSopenharmony_ci      usb_err("illagel request!\r\n");
518beacf11bSopenharmony_ci      return -ENODEV;
519beacf11bSopenharmony_ci    }
520beacf11bSopenharmony_ci
521beacf11bSopenharmony_ci  /* Process the received data unless this is some unusual condition */
522beacf11bSopenharmony_ci
523beacf11bSopenharmony_ci  switch (req->result)
524beacf11bSopenharmony_ci    {
525beacf11bSopenharmony_ci    default: /* Some other error occurred */
526beacf11bSopenharmony_ci      {
527beacf11bSopenharmony_ci        FALOG("unexpected RX status\r\n");
528beacf11bSopenharmony_ci      }
529beacf11bSopenharmony_ci
530beacf11bSopenharmony_ci    case 0: /* Normal completion */
531beacf11bSopenharmony_ci      {
532beacf11bSopenharmony_ci        nbytes = cdcacm_fill_rdrequest(priv, rdcontainer, buflen);
533beacf11bSopenharmony_ci
534beacf11bSopenharmony_ci        /* Tell host device is ready for next read event */
535beacf11bSopenharmony_ci
536beacf11bSopenharmony_ci        (void)cdcacm_requeue_rdrequest(priv, rdcontainer);
537beacf11bSopenharmony_ci      }
538beacf11bSopenharmony_ci      break;
539beacf11bSopenharmony_ci
540beacf11bSopenharmony_ci    case -ESHUTDOWN: /* Disconnection */
541beacf11bSopenharmony_ci      {
542beacf11bSopenharmony_ci        atomic_set(&priv->shutdown, 1);
543beacf11bSopenharmony_ci        atomic_set(&priv->send_char, 0);
544beacf11bSopenharmony_ci        FALOG("serial shutdown!\r\n");
545beacf11bSopenharmony_ci      }
546beacf11bSopenharmony_ci      break;
547beacf11bSopenharmony_ci    }
548beacf11bSopenharmony_ci  return nbytes;
549beacf11bSopenharmony_ci}
550beacf11bSopenharmony_ci
551beacf11bSopenharmony_ci/****************************************************************************
552beacf11bSopenharmony_ci * Name: cdcacm_requeue_rdrequest
553beacf11bSopenharmony_ci *
554beacf11bSopenharmony_ci * Description:
555beacf11bSopenharmony_ci *   Add any pending RX packets to the upper half serial drivers RX buffer.
556beacf11bSopenharmony_ci *
557beacf11bSopenharmony_ci ****************************************************************************/
558beacf11bSopenharmony_ci
559beacf11bSopenharmony_cistatic int cdcacm_requeue_rdrequest(FAR struct cdcacm_dev_s *priv,
560beacf11bSopenharmony_ci                                    FAR struct cdcacm_rdreq_s *rdcontainer)
561beacf11bSopenharmony_ci{
562beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
563beacf11bSopenharmony_ci  FAR struct usbdev_ep_s *ep;
564beacf11bSopenharmony_ci  uint32_t flags;
565beacf11bSopenharmony_ci  int ret = 0;
566beacf11bSopenharmony_ci
567beacf11bSopenharmony_ci  if (priv == NULL || rdcontainer == NULL)
568beacf11bSopenharmony_ci    {
569beacf11bSopenharmony_ci      return -EINVAL;
570beacf11bSopenharmony_ci    }
571beacf11bSopenharmony_ci
572beacf11bSopenharmony_ci  /* Shield shutdown interrupt signal */
573beacf11bSopenharmony_ci
574beacf11bSopenharmony_ci  spin_lock_irqsave(&priv->acm_lock, flags);
575beacf11bSopenharmony_ci  if (atomic_read(&priv->send_char) == 0)
576beacf11bSopenharmony_ci    {
577beacf11bSopenharmony_ci
578beacf11bSopenharmony_ci      atomic_set(&priv->send_char, 1);
579beacf11bSopenharmony_ci
580beacf11bSopenharmony_ci      /* Requeue the read request */
581beacf11bSopenharmony_ci
582beacf11bSopenharmony_ci      req      = rdcontainer->req;
583beacf11bSopenharmony_ci      ep       = priv->epbulkout;
584beacf11bSopenharmony_ci      req->len = ep->maxpacket;
585beacf11bSopenharmony_ci      ret      = EP_SUBMIT(ep, req);
586beacf11bSopenharmony_ci      if (ret != OK)
587beacf11bSopenharmony_ci        {
588beacf11bSopenharmony_ci          usb_err("epbulkout submit failed!\r\n");
589beacf11bSopenharmony_ci          atomic_set(&priv->send_char, 0);
590beacf11bSopenharmony_ci        }
591beacf11bSopenharmony_ci    }
592beacf11bSopenharmony_ci  spin_unlock_irqrestore(&priv->acm_lock, flags);
593beacf11bSopenharmony_ci  return ret;
594beacf11bSopenharmony_ci}
595beacf11bSopenharmony_ci
596beacf11bSopenharmony_ci/****************************************************************************
597beacf11bSopenharmony_ci * Name: cdcacm_release_rxpending
598beacf11bSopenharmony_ci *
599beacf11bSopenharmony_ci * Description:
600beacf11bSopenharmony_ci *   Add any pending RX packets to the upper half serial drivers RX buffer.
601beacf11bSopenharmony_ci *
602beacf11bSopenharmony_ci ****************************************************************************/
603beacf11bSopenharmony_ci
604beacf11bSopenharmony_cistatic ssize_t cdcacm_release_rxpending(FAR struct file *filep, FAR char *buffer, size_t buflen)
605beacf11bSopenharmony_ci{
606beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
607beacf11bSopenharmony_ci  FAR struct cdcacm_rdreq_s *rdcontainer;
608beacf11bSopenharmony_ci  ssize_t nbytes = 0;
609beacf11bSopenharmony_ci  int ret = -1;
610beacf11bSopenharmony_ci
611beacf11bSopenharmony_ci  struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
612beacf11bSopenharmony_ci  priv = (struct cdcacm_dev_s *)drv->priv;
613beacf11bSopenharmony_ci  if (priv == NULL)
614beacf11bSopenharmony_ci    {
615beacf11bSopenharmony_ci      return -EINVAL;
616beacf11bSopenharmony_ci    }
617beacf11bSopenharmony_ci
618beacf11bSopenharmony_ci  rdcontainer         = &priv->rdreqs;
619beacf11bSopenharmony_ci  rdcontainer->buf    = buffer;
620beacf11bSopenharmony_ci  rdcontainer->buflen = buflen;
621beacf11bSopenharmony_ci
622beacf11bSopenharmony_ci  if (g_readpend == true)
623beacf11bSopenharmony_ci    {
624beacf11bSopenharmony_ci      /* cdcacm_recvpacket() will return OK if the entire packet was
625beacf11bSopenharmony_ci       * successful buffered. In the case of RX buffer overrun,
626beacf11bSopenharmony_ci       * cdcacm_recvpacket() will return a failure (-ENOSPC) and will
627beacf11bSopenharmony_ci       * set the req->offset field
628beacf11bSopenharmony_ci       */
629beacf11bSopenharmony_ci
630beacf11bSopenharmony_ci      nbytes = (ssize_t)cdcacm_recvpacket(priv, rdcontainer);
631beacf11bSopenharmony_ci
632beacf11bSopenharmony_ci      /* The entire packet was processed and may be removed from the
633beacf11bSopenharmony_ci       * pending RX list and returned to the DCD.
634beacf11bSopenharmony_ci       */
635beacf11bSopenharmony_ci
636beacf11bSopenharmony_ci      /* If we are still connected, refill the USB RX buffer. */
637beacf11bSopenharmony_ci
638beacf11bSopenharmony_ci      if (atomic_read(&priv->shutdown) == 0)
639beacf11bSopenharmony_ci        {
640beacf11bSopenharmony_ci          ret = cdcacm_requeue_rdrequest(priv, rdcontainer);
641beacf11bSopenharmony_ci          if (ret < 0)
642beacf11bSopenharmony_ci            {
643beacf11bSopenharmony_ci              usb_err("device is not ready for receive next data \r\n");
644beacf11bSopenharmony_ci              return ret;
645beacf11bSopenharmony_ci            }
646beacf11bSopenharmony_ci        }
647beacf11bSopenharmony_ci    }
648beacf11bSopenharmony_ci
649beacf11bSopenharmony_ci  return nbytes;
650beacf11bSopenharmony_ci}
651beacf11bSopenharmony_ci
652beacf11bSopenharmony_ci/****************************************************************************
653beacf11bSopenharmony_ci * Name: cdcacm_allocreq
654beacf11bSopenharmony_ci *
655beacf11bSopenharmony_ci * Description:
656beacf11bSopenharmony_ci *   Allocate a request instance along with its buffer
657beacf11bSopenharmony_ci *
658beacf11bSopenharmony_ci ****************************************************************************/
659beacf11bSopenharmony_ci
660beacf11bSopenharmony_cistatic struct usbdev_req_s *cdcacm_allocreq(FAR struct usbdev_ep_s *ep, uint16_t len)
661beacf11bSopenharmony_ci{
662beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
663beacf11bSopenharmony_ci  req = EP_ALLOCREQ(ep);
664beacf11bSopenharmony_ci  if (req != NULL)
665beacf11bSopenharmony_ci    {
666beacf11bSopenharmony_ci      req->len = len;
667beacf11bSopenharmony_ci      req->buf = EP_ALLOCBUFFER(ep, len);
668beacf11bSopenharmony_ci      if (req->buf == NULL)
669beacf11bSopenharmony_ci        {
670beacf11bSopenharmony_ci          EP_FREEREQ(ep, req);
671beacf11bSopenharmony_ci          return NULL;
672beacf11bSopenharmony_ci        }
673beacf11bSopenharmony_ci      #ifdef CONFIG_USBDEV_DMA
674beacf11bSopenharmony_ci      req->dma = (DMA_ADDR_T)VMM_TO_UNCACHED_ADDR((unsigned long)req->buf);
675beacf11bSopenharmony_ci      #else
676beacf11bSopenharmony_ci      req->dma = NULL;
677beacf11bSopenharmony_ci      #endif
678beacf11bSopenharmony_ci    }
679beacf11bSopenharmony_ci  return req;
680beacf11bSopenharmony_ci}
681beacf11bSopenharmony_ci
682beacf11bSopenharmony_ci/****************************************************************************
683beacf11bSopenharmony_ci * Name: cdcacm_freereq
684beacf11bSopenharmony_ci *
685beacf11bSopenharmony_ci * Description:
686beacf11bSopenharmony_ci *   Free a request instance along with its buffer
687beacf11bSopenharmony_ci *
688beacf11bSopenharmony_ci ****************************************************************************/
689beacf11bSopenharmony_ci
690beacf11bSopenharmony_cistatic void cdcacm_freereq(FAR struct usbdev_ep_s *ep,
691beacf11bSopenharmony_ci                           FAR struct usbdev_req_s *req)
692beacf11bSopenharmony_ci{
693beacf11bSopenharmony_ci  if (ep != NULL && req != NULL)
694beacf11bSopenharmony_ci    {
695beacf11bSopenharmony_ci      if (req->buf != NULL)
696beacf11bSopenharmony_ci        {
697beacf11bSopenharmony_ci          EP_FREEBUFFER(ep, req->buf);
698beacf11bSopenharmony_ci		  req->buf = NULL;
699beacf11bSopenharmony_ci        }
700beacf11bSopenharmony_ci
701beacf11bSopenharmony_ci      EP_FREEREQ(ep, req);
702beacf11bSopenharmony_ci    }
703beacf11bSopenharmony_ci}
704beacf11bSopenharmony_ci
705beacf11bSopenharmony_ci/****************************************************************************
706beacf11bSopenharmony_ci * Name: cdcacm_resetconfig
707beacf11bSopenharmony_ci *
708beacf11bSopenharmony_ci * Description:
709beacf11bSopenharmony_ci *   Mark the device as not configured and disable all endpoints.
710beacf11bSopenharmony_ci *
711beacf11bSopenharmony_ci ****************************************************************************/
712beacf11bSopenharmony_ci
713beacf11bSopenharmony_cistatic void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv)
714beacf11bSopenharmony_ci{
715beacf11bSopenharmony_ci  if (priv == NULL)
716beacf11bSopenharmony_ci    {
717beacf11bSopenharmony_ci      usb_err("Disable ep failed!\r\n");
718beacf11bSopenharmony_ci      return;
719beacf11bSopenharmony_ci    }
720beacf11bSopenharmony_ci
721beacf11bSopenharmony_ci  /* Disable endpoints. This should force completion of all pending
722beacf11bSopenharmony_ci   * transfers.
723beacf11bSopenharmony_ci   */
724beacf11bSopenharmony_ci
725beacf11bSopenharmony_ci  if (priv->epintin_enabled == true)
726beacf11bSopenharmony_ci    {
727beacf11bSopenharmony_ci      EP_DISABLE(priv->epintin);
728beacf11bSopenharmony_ci      priv->epintin_enabled = false;
729beacf11bSopenharmony_ci    }
730beacf11bSopenharmony_ci
731beacf11bSopenharmony_ci  if (priv->epbulkin_enabled == true)
732beacf11bSopenharmony_ci    {
733beacf11bSopenharmony_ci      EP_DISABLE(priv->epbulkin);
734beacf11bSopenharmony_ci      priv->epbulkin_enabled = false;
735beacf11bSopenharmony_ci    }
736beacf11bSopenharmony_ci
737beacf11bSopenharmony_ci  if (priv->epbulkout_enabled == true)
738beacf11bSopenharmony_ci    {
739beacf11bSopenharmony_ci      EP_DISABLE(priv->epbulkout);
740beacf11bSopenharmony_ci      priv->epbulkout_enabled = false;
741beacf11bSopenharmony_ci    }
742beacf11bSopenharmony_ci}
743beacf11bSopenharmony_ci
744beacf11bSopenharmony_ci/****************************************************************************
745beacf11bSopenharmony_ci * Name: cdcacm_epconfigure
746beacf11bSopenharmony_ci *
747beacf11bSopenharmony_ci * Description:
748beacf11bSopenharmony_ci *   Configure one endpoint.
749beacf11bSopenharmony_ci *
750beacf11bSopenharmony_ci ****************************************************************************/
751beacf11bSopenharmony_ci
752beacf11bSopenharmony_cistatic int cdcacm_epconfigure(FAR struct usbdev_ep_s *ep,
753beacf11bSopenharmony_ci                              enum cdcacm_epdesc_e epid,
754beacf11bSopenharmony_ci                              FAR const usb_endpoint_descriptor_t *ep_desc,
755beacf11bSopenharmony_ci                              FAR struct usbdev_s *dev,
756beacf11bSopenharmony_ci                              bool last)
757beacf11bSopenharmony_ci{
758beacf11bSopenharmony_ci  if (epid != CDCACM_EPINTIN)
759beacf11bSopenharmony_ci    {
760beacf11bSopenharmony_ci      usbd_configep_byspeed(dev, (struct usb_endpoint_descriptor *)ep_desc);
761beacf11bSopenharmony_ci    }
762beacf11bSopenharmony_ci  return EP_CONFIGURE(ep, ep_desc, last);
763beacf11bSopenharmony_ci}
764beacf11bSopenharmony_ci
765beacf11bSopenharmony_ci/****************************************************************************
766beacf11bSopenharmony_ci * Name: cdcacm_setconfig
767beacf11bSopenharmony_ci *
768beacf11bSopenharmony_ci * Description:
769beacf11bSopenharmony_ci *   Set the device configuration by allocating and configuring endpoints and
770beacf11bSopenharmony_ci *   by allocating and queue read and write requests.
771beacf11bSopenharmony_ci *
772beacf11bSopenharmony_ci ****************************************************************************/
773beacf11bSopenharmony_ci
774beacf11bSopenharmony_cistatic int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv,
775beacf11bSopenharmony_ci                            struct usbdev_s *dev)
776beacf11bSopenharmony_ci{
777beacf11bSopenharmony_ci  FAR struct cdcacm_rdreq_s *rdcontainer;
778beacf11bSopenharmony_ci  int ret;
779beacf11bSopenharmony_ci  uint32_t flags;
780beacf11bSopenharmony_ci
781beacf11bSopenharmony_ci  if (priv == NULL)
782beacf11bSopenharmony_ci    {
783beacf11bSopenharmony_ci      return -EINVAL;
784beacf11bSopenharmony_ci    }
785beacf11bSopenharmony_ci
786beacf11bSopenharmony_ci  rdcontainer = &priv->rdreqs;
787beacf11bSopenharmony_ci
788beacf11bSopenharmony_ci  if (priv->epintin_enabled == true)
789beacf11bSopenharmony_ci    {
790beacf11bSopenharmony_ci      EP_DISABLE(priv->epintin);
791beacf11bSopenharmony_ci      priv->epintin_enabled = false;
792beacf11bSopenharmony_ci    }
793beacf11bSopenharmony_ci
794beacf11bSopenharmony_ci  /* Configure the IN interrupt endpoint */
795beacf11bSopenharmony_ci
796beacf11bSopenharmony_ci  ret = cdcacm_epconfigure(priv->epintin, CDCACM_EPINTIN,
797beacf11bSopenharmony_ci                           (const usb_endpoint_descriptor_t *)&g_cdcacm_hs_func_desc.nepd, dev, false);
798beacf11bSopenharmony_ci  if (ret < 0)
799beacf11bSopenharmony_ci    {
800beacf11bSopenharmony_ci      usb_err("config interrupt ep failed!\r\n");
801beacf11bSopenharmony_ci      goto errout;
802beacf11bSopenharmony_ci    }
803beacf11bSopenharmony_ci  priv->epintin_enabled = true;
804beacf11bSopenharmony_ci  priv->epintin->priv   = priv;
805beacf11bSopenharmony_ci
806beacf11bSopenharmony_ci  if (priv->epbulkin_enabled == true)
807beacf11bSopenharmony_ci    {
808beacf11bSopenharmony_ci      EP_DISABLE(priv->epbulkin);
809beacf11bSopenharmony_ci      priv->epbulkin_enabled = false;
810beacf11bSopenharmony_ci    }
811beacf11bSopenharmony_ci
812beacf11bSopenharmony_ci  /* Configure the IN bulk endpoint */
813beacf11bSopenharmony_ci
814beacf11bSopenharmony_ci  ret = cdcacm_epconfigure(priv->epbulkin, CDCACM_EPBULKIN,
815beacf11bSopenharmony_ci                           (const usb_endpoint_descriptor_t *)&g_cdcacm_hs_func_desc.iepd, dev, false);
816beacf11bSopenharmony_ci  if (ret < 0)
817beacf11bSopenharmony_ci    {
818beacf11bSopenharmony_ci      usb_err("config bulk in ep failed!\r\n");
819beacf11bSopenharmony_ci      goto errout;
820beacf11bSopenharmony_ci    }
821beacf11bSopenharmony_ci  priv->epbulkin_enabled = true;
822beacf11bSopenharmony_ci  priv->epbulkin->priv   = priv;
823beacf11bSopenharmony_ci
824beacf11bSopenharmony_ci  if (priv->epbulkout_enabled == true)
825beacf11bSopenharmony_ci    {
826beacf11bSopenharmony_ci      EP_DISABLE(priv->epbulkout);
827beacf11bSopenharmony_ci      priv->epbulkout_enabled = false;
828beacf11bSopenharmony_ci    }
829beacf11bSopenharmony_ci
830beacf11bSopenharmony_ci  /* Configure the OUT bulk endpoint */
831beacf11bSopenharmony_ci
832beacf11bSopenharmony_ci  ret = cdcacm_epconfigure(priv->epbulkout, CDCACM_EPBULKOUT,
833beacf11bSopenharmony_ci                           (const usb_endpoint_descriptor_t *)&g_cdcacm_hs_func_desc.oepd, dev, false);
834beacf11bSopenharmony_ci  if (ret < 0)
835beacf11bSopenharmony_ci    {
836beacf11bSopenharmony_ci      usb_err("config bulk out ep failed!\r\n");
837beacf11bSopenharmony_ci      goto errout;
838beacf11bSopenharmony_ci    }
839beacf11bSopenharmony_ci  priv->epbulkout_enabled = true;
840beacf11bSopenharmony_ci  priv->epbulkout->priv   = priv;
841beacf11bSopenharmony_ci
842beacf11bSopenharmony_ci  /* Queue read requests in the bulk OUT endpoint */
843beacf11bSopenharmony_ci
844beacf11bSopenharmony_ci  ret = cdcacm_requeue_rdrequest(priv, rdcontainer);
845beacf11bSopenharmony_ci  if (ret != OK)
846beacf11bSopenharmony_ci    {
847beacf11bSopenharmony_ci      goto errout;
848beacf11bSopenharmony_ci    }
849beacf11bSopenharmony_ci
850beacf11bSopenharmony_ci  /* We are successfully configured.
851beacf11bSopenharmony_ci   * Tell host that device is available
852beacf11bSopenharmony_ci   * and ready for data transfer.
853beacf11bSopenharmony_ci   */
854beacf11bSopenharmony_ci
855beacf11bSopenharmony_ci  spin_lock_irqsave(&priv->acm_lock, flags);
856beacf11bSopenharmony_ci  ret = cdcacm_serial_connect(priv);
857beacf11bSopenharmony_ci  if (ret < 0)
858beacf11bSopenharmony_ci    {
859beacf11bSopenharmony_ci      usb_err("cdcacm connect failed!\r\n");
860beacf11bSopenharmony_ci      spin_unlock_irqrestore(&priv->acm_lock, flags);
861beacf11bSopenharmony_ci      goto errout;
862beacf11bSopenharmony_ci    }
863beacf11bSopenharmony_ci  atomic_set(&priv->shutdown, 0);
864beacf11bSopenharmony_ci  priv->bdisconnect = false;
865beacf11bSopenharmony_ci
866beacf11bSopenharmony_ci  /* tell console dprintf to virtrue serial */
867beacf11bSopenharmony_ci
868beacf11bSopenharmony_ci  g_usbSerialMask = 1;
869beacf11bSopenharmony_ci  spin_unlock_irqrestore(&priv->acm_lock, flags);
870beacf11bSopenharmony_ci
871beacf11bSopenharmony_ci  return OK;
872beacf11bSopenharmony_ci
873beacf11bSopenharmony_cierrout:
874beacf11bSopenharmony_ci  cdcacm_resetconfig(priv);
875beacf11bSopenharmony_ci  return ret;
876beacf11bSopenharmony_ci}
877beacf11bSopenharmony_ci
878beacf11bSopenharmony_ci/****************************************************************************
879beacf11bSopenharmony_ci * Name: cdcacm_rdcomplete
880beacf11bSopenharmony_ci *
881beacf11bSopenharmony_ci * Description:
882beacf11bSopenharmony_ci *   Handle completion of read request on the bulk OUT endpoint.  This
883beacf11bSopenharmony_ci *   is handled like the receipt of serial data on the "UART"
884beacf11bSopenharmony_ci *
885beacf11bSopenharmony_ci ****************************************************************************/
886beacf11bSopenharmony_ci
887beacf11bSopenharmony_cistatic void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
888beacf11bSopenharmony_ci                              FAR struct usbdev_req_s *req)
889beacf11bSopenharmony_ci{
890beacf11bSopenharmony_ci  FAR struct cdcacm_rdreq_s *rdcontainer;
891beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
892beacf11bSopenharmony_ci  uint32_t ret;
893beacf11bSopenharmony_ci  PRINT_ERR("%s req->xfrd:%x\r\n", __FUNCTION__, req->xfrd);
894beacf11bSopenharmony_ci  PRINT_ERR("%s req->xfrd:%x\r\n", __FUNCTION__, req->result);
895beacf11bSopenharmony_ci
896beacf11bSopenharmony_ci  if (ep == NULL || ep->priv == NULL || req == NULL)
897beacf11bSopenharmony_ci    {
898beacf11bSopenharmony_ci      usb_err("illegal request or ep\r\n");
899beacf11bSopenharmony_ci      return;
900beacf11bSopenharmony_ci    }
901beacf11bSopenharmony_ci
902beacf11bSopenharmony_ci  /* Extract references to private data */
903beacf11bSopenharmony_ci
904beacf11bSopenharmony_ci  priv = (struct cdcacm_dev_s *)ep->priv;
905beacf11bSopenharmony_ci
906beacf11bSopenharmony_ci  rdcontainer = &priv->rdreqs;
907beacf11bSopenharmony_ci
908beacf11bSopenharmony_ci  /* Save private data of reqd request */
909beacf11bSopenharmony_ci
910beacf11bSopenharmony_ci  rdcontainer->req      = req;
911beacf11bSopenharmony_ci  rdcontainer->req->len = req->len;
912beacf11bSopenharmony_ci
913beacf11bSopenharmony_ci  /* Magic key */
914beacf11bSopenharmony_ci
915beacf11bSopenharmony_ci  if (CheckMagicKey(*(char *)req->buf, CONSOLE_SERIAL))
916beacf11bSopenharmony_ci    {
917beacf11bSopenharmony_ci      atomic_set(&g_magickey, 1);
918beacf11bSopenharmony_ci      (void)cdcacm_recvpacket(priv, rdcontainer);
919beacf11bSopenharmony_ci      (void)cdcacm_requeue_rdrequest(priv, rdcontainer);
920beacf11bSopenharmony_ci      atomic_set(&g_magickey, 0);
921beacf11bSopenharmony_ci      return;
922beacf11bSopenharmony_ci    }
923beacf11bSopenharmony_ci
924beacf11bSopenharmony_ci  ret = LOS_EventWrite(&priv->read_event, USB_SERIAL_READ_EVENT);
925beacf11bSopenharmony_ci  if (ret != OK)
926beacf11bSopenharmony_ci    {
927beacf11bSopenharmony_ci      usb_err("write event failed!\r\n");
928beacf11bSopenharmony_ci    }
929beacf11bSopenharmony_ci}
930beacf11bSopenharmony_ci
931beacf11bSopenharmony_ci/****************************************************************************
932beacf11bSopenharmony_ci * Name: cdcacm_wrcomplete
933beacf11bSopenharmony_ci *
934beacf11bSopenharmony_ci * Description:
935beacf11bSopenharmony_ci *   Handle completion of write request.  This function probably executes
936beacf11bSopenharmony_ci *   in the context of an interrupt handler.
937beacf11bSopenharmony_ci *
938beacf11bSopenharmony_ci ****************************************************************************/
939beacf11bSopenharmony_ci
940beacf11bSopenharmony_cistatic void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
941beacf11bSopenharmony_ci                              FAR struct usbdev_req_s *req)
942beacf11bSopenharmony_ci{
943beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
944beacf11bSopenharmony_ci  FAR struct cdcacm_wrreq_s *wrcontainer;
945beacf11bSopenharmony_ci
946beacf11bSopenharmony_ci  /* Extract references to our private data */
947beacf11bSopenharmony_ci  PRINT_ERR("%s req->xfrd:%x\r\n", __FUNCTION__, req->xfrd);
948beacf11bSopenharmony_ci  PRINT_ERR("%s req->xfrd:%x\r\n", __FUNCTION__, req->result);
949beacf11bSopenharmony_ci
950beacf11bSopenharmony_ci  priv = (struct cdcacm_dev_s *)ep->priv;
951beacf11bSopenharmony_ci  if (priv == NULL)
952beacf11bSopenharmony_ci    {
953beacf11bSopenharmony_ci      usb_err("device is unavailable!\r\n");
954beacf11bSopenharmony_ci      return;
955beacf11bSopenharmony_ci    }
956beacf11bSopenharmony_ci  spin_lock(&priv->acm_lock);
957beacf11bSopenharmony_ci
958beacf11bSopenharmony_ci  /* protect for received_char */
959beacf11bSopenharmony_ci
960beacf11bSopenharmony_ci  wrcontainer = (struct cdcacm_wrreq_s *)req->priv;
961beacf11bSopenharmony_ci
962beacf11bSopenharmony_ci  priv->received_char = false;
963beacf11bSopenharmony_ci
964beacf11bSopenharmony_ci  /* Send the next packet unless this was some unusual termination
965beacf11bSopenharmony_ci   * condition
966beacf11bSopenharmony_ci   */
967beacf11bSopenharmony_ci
968beacf11bSopenharmony_ci  switch (req->result)
969beacf11bSopenharmony_ci    {
970beacf11bSopenharmony_ci    default: /* Some other error occurred */
971beacf11bSopenharmony_ci      {
972beacf11bSopenharmony_ci        FALOG("unexpected RX status\r\n");
973beacf11bSopenharmony_ci      }
974beacf11bSopenharmony_ci
975beacf11bSopenharmony_ci    case 0: /* Normal completion */
976beacf11bSopenharmony_ci      {
977beacf11bSopenharmony_ci        (void)cdcacm_sndpacket(priv, wrcontainer);
978beacf11bSopenharmony_ci      }
979beacf11bSopenharmony_ci      break;
980beacf11bSopenharmony_ci
981beacf11bSopenharmony_ci    case -ESHUTDOWN: /* Disconnection */
982beacf11bSopenharmony_ci      {
983beacf11bSopenharmony_ci        FALOG("usb device disconnect!");
984beacf11bSopenharmony_ci      }
985beacf11bSopenharmony_ci      break;
986beacf11bSopenharmony_ci    }
987beacf11bSopenharmony_ci  spin_unlock(&priv->acm_lock);
988beacf11bSopenharmony_ci}
989beacf11bSopenharmony_ci
990beacf11bSopenharmony_cistatic void cdcacm_notify_complete(FAR struct usbdev_ep_s *ep,
991beacf11bSopenharmony_ci                                   FAR struct usbdev_req_s *usbd_req)
992beacf11bSopenharmony_ci{
993beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
994beacf11bSopenharmony_ci  bool flag = false;
995beacf11bSopenharmony_ci  int ret;
996beacf11bSopenharmony_ci  uint32_t flags;
997beacf11bSopenharmony_ci  PRINT_ERR("%s req->xfrd:%x\r\n", __FUNCTION__, usbd_req->xfrd);
998beacf11bSopenharmony_ci  PRINT_ERR("%s req->xfrd:%x\r\n", __FUNCTION__, usbd_req->result);
999beacf11bSopenharmony_ci
1000beacf11bSopenharmony_ci  (void)ep;
1001beacf11bSopenharmony_ci  priv = usbd_req->priv;
1002beacf11bSopenharmony_ci  if (priv == NULL)
1003beacf11bSopenharmony_ci    {
1004beacf11bSopenharmony_ci      usb_err("No device!\r\n");
1005beacf11bSopenharmony_ci      return;
1006beacf11bSopenharmony_ci    }
1007beacf11bSopenharmony_ci
1008beacf11bSopenharmony_ci  spin_lock_irqsave(&priv->acm_lock, flags);
1009beacf11bSopenharmony_ci  if (usbd_req->result != -ESHUTDOWN)
1010beacf11bSopenharmony_ci    {
1011beacf11bSopenharmony_ci      flag = priv->wating;
1012beacf11bSopenharmony_ci    }
1013beacf11bSopenharmony_ci
1014beacf11bSopenharmony_ci  if (flag == true)
1015beacf11bSopenharmony_ci    {
1016beacf11bSopenharmony_ci      ret = cdcacm_serial_connect(priv);
1017beacf11bSopenharmony_ci      if (ret < 0)
1018beacf11bSopenharmony_ci        {
1019beacf11bSopenharmony_ci          usb_err("cdcacm connect failed!\r\n");
1020beacf11bSopenharmony_ci        }
1021beacf11bSopenharmony_ci    }
1022beacf11bSopenharmony_ci  spin_unlock_irqrestore(&priv->acm_lock, flags);
1023beacf11bSopenharmony_ci}
1024beacf11bSopenharmony_ci
1025beacf11bSopenharmony_ci/****************************************************************************
1026beacf11bSopenharmony_ci * USB Class Driver Methods
1027beacf11bSopenharmony_ci ****************************************************************************/
1028beacf11bSopenharmony_ci
1029beacf11bSopenharmony_ci/****************************************************************************
1030beacf11bSopenharmony_ci * Name: cdcacm_bind
1031beacf11bSopenharmony_ci *
1032beacf11bSopenharmony_ci * Description:
1033beacf11bSopenharmony_ci *   Invoked when the driver is bound to a USB device driver
1034beacf11bSopenharmony_ci *
1035beacf11bSopenharmony_ci ****************************************************************************/
1036beacf11bSopenharmony_ci
1037beacf11bSopenharmony_cistatic int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
1038beacf11bSopenharmony_ci                       FAR struct usbdev_s *dev)
1039beacf11bSopenharmony_ci{
1040beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1041beacf11bSopenharmony_ci  FAR struct composite_devobj_s *devobj;
1042beacf11bSopenharmony_ci  FAR struct usbdev_devinfo_s *devinfo;
1043beacf11bSopenharmony_ci  FAR struct cdcacm_wrreq_s *wrcontainer;
1044beacf11bSopenharmony_ci  FAR struct cdcacm_rdreq_s *rdcontainer;
1045beacf11bSopenharmony_ci  FAR struct composite_dev_s *cdev;
1046beacf11bSopenharmony_ci  uint16_t reqlen;
1047beacf11bSopenharmony_ci  int ret;
1048beacf11bSopenharmony_ci
1049beacf11bSopenharmony_ci  if (driver == NULL || dev == NULL)
1050beacf11bSopenharmony_ci    {
1051beacf11bSopenharmony_ci      usb_err("Bind failed!\r\n");
1052beacf11bSopenharmony_ci      return -ENODEV;
1053beacf11bSopenharmony_ci    }
1054beacf11bSopenharmony_ci
1055beacf11bSopenharmony_ci  priv = ((struct cdcacm_driver_s *)driver)->dev;
1056beacf11bSopenharmony_ci
1057beacf11bSopenharmony_ci  /* Bind the structures */
1058beacf11bSopenharmony_ci
1059beacf11bSopenharmony_ci  priv->usbdev      = dev;
1060beacf11bSopenharmony_ci  priv->bdisconnect = true;
1061beacf11bSopenharmony_ci  atomic_set(&priv->shutdown, 0);
1062beacf11bSopenharmony_ci
1063beacf11bSopenharmony_ci  /* Save the reference to our private data structure in EP0 so that it
1064beacf11bSopenharmony_ci   * can be recovered in ep0 completion events (Unless we are part of
1065beacf11bSopenharmony_ci   * a composite device and, in that case, the composite device owns
1066beacf11bSopenharmony_ci   * EP0).
1067beacf11bSopenharmony_ci   */
1068beacf11bSopenharmony_ci
1069beacf11bSopenharmony_ci  cdev = dev->ep0->priv;
1070beacf11bSopenharmony_ci  (VOID)LOS_EventInit(&priv->read_event);
1071beacf11bSopenharmony_ci  spin_lock_init(&priv->acm_lock);
1072beacf11bSopenharmony_ci
1073beacf11bSopenharmony_ci  /* Register a character driver inode the pseudo file system */
1074beacf11bSopenharmony_ci
1075beacf11bSopenharmony_ci  ret = register_driver(CDCACM_DEVNAME_FORMAT, &g_vfs_ops, 0666, priv);
1076beacf11bSopenharmony_ci  if (ret != 0)
1077beacf11bSopenharmony_ci    {
1078beacf11bSopenharmony_ci      usb_err("chardev register failed!");
1079beacf11bSopenharmony_ci      return ret;
1080beacf11bSopenharmony_ci    }
1081beacf11bSopenharmony_ci
1082beacf11bSopenharmony_ci  /* Preallocate control request */
1083beacf11bSopenharmony_ci
1084beacf11bSopenharmony_ci  priv->ctrlreq = cdev->ctrlreq;
1085beacf11bSopenharmony_ci  if (priv->ctrlreq == NULL)
1086beacf11bSopenharmony_ci    {
1087beacf11bSopenharmony_ci      ret = -EINVAL;
1088beacf11bSopenharmony_ci      goto errout;
1089beacf11bSopenharmony_ci    }
1090beacf11bSopenharmony_ci
1091beacf11bSopenharmony_ci  devobj = usbclass_devobj_get(cdev, DEV_SERIAL);
1092beacf11bSopenharmony_ci  if (devobj == NULL)
1093beacf11bSopenharmony_ci    {
1094beacf11bSopenharmony_ci      ret = -EINVAL;
1095beacf11bSopenharmony_ci      goto errout;
1096beacf11bSopenharmony_ci    }
1097beacf11bSopenharmony_ci  devinfo = &devobj->compdesc.devinfo;
1098beacf11bSopenharmony_ci
1099beacf11bSopenharmony_ci  priv->ctrl_id = (uint8_t)devinfo->ifnobase;
1100beacf11bSopenharmony_ci  priv->data_id = (uint8_t)devinfo->ifnobase + 1;
1101beacf11bSopenharmony_ci
1102beacf11bSopenharmony_ci  /* Pre-allocate all endpoints... the endpoints will not be functional
1103beacf11bSopenharmony_ci   * until the SET CONFIGURATION request is processed in cdcacm_setconfig.
1104beacf11bSopenharmony_ci   * This is done here because there may be calls to kmm_malloc and the SET
1105beacf11bSopenharmony_ci   * CONFIGURATION processing probably occurrs within interrupt handling
1106beacf11bSopenharmony_ci   * logic where kmm_malloc calls will fail.
1107beacf11bSopenharmony_ci   */
1108beacf11bSopenharmony_ci
1109beacf11bSopenharmony_ci  /* Pre-allocate the IN interrupt endpoint */
1110beacf11bSopenharmony_ci
1111beacf11bSopenharmony_ci  priv->epintin = DEV_ALLOCEP(dev, g_cdcacm_hs_func_desc.nepd.bEndpointAddress, &g_cdcacm_hs_func_desc.nepd);
1112beacf11bSopenharmony_ci  if (!priv->epintin)
1113beacf11bSopenharmony_ci    {
1114beacf11bSopenharmony_ci      usb_err("alloc epintin fail!");
1115beacf11bSopenharmony_ci      ret = -ENODEV;
1116beacf11bSopenharmony_ci      goto errout;
1117beacf11bSopenharmony_ci    }
1118beacf11bSopenharmony_ci  CDCACM_MKEPINTIN(devinfo) = priv->epintin->eplog;
1119beacf11bSopenharmony_ci  priv->epintin->priv = priv;
1120beacf11bSopenharmony_ci  priv->epintin->handle_req = cdcacm_allocreq(priv->epintin,
1121beacf11bSopenharmony_ci                                              sizeof(struct usb_cdc_notification) + sizeof(priv->serialstate));
1122beacf11bSopenharmony_ci  if (priv->epintin->handle_req == NULL)
1123beacf11bSopenharmony_ci    {
1124beacf11bSopenharmony_ci      ret = -ENOMEM;
1125beacf11bSopenharmony_ci      goto errout;
1126beacf11bSopenharmony_ci    }
1127beacf11bSopenharmony_ci  priv->epintin->handle_req->callback = cdcacm_notify_complete;
1128beacf11bSopenharmony_ci
1129beacf11bSopenharmony_ci  /* Pre-allocate the IN bulk endpoint */
1130beacf11bSopenharmony_ci
1131beacf11bSopenharmony_ci  priv->epbulkin = DEV_ALLOCEP(dev, g_cdcacm_hs_func_desc.iepd.bEndpointAddress, &g_cdcacm_hs_func_desc.iepd);
1132beacf11bSopenharmony_ci  if (!priv->epbulkin)
1133beacf11bSopenharmony_ci    {
1134beacf11bSopenharmony_ci      usb_err("alloc epbulkin fail!");
1135beacf11bSopenharmony_ci      ret = -ENODEV;
1136beacf11bSopenharmony_ci      goto errout;
1137beacf11bSopenharmony_ci    }
1138beacf11bSopenharmony_ci  CDCACM_MKEPBULKIN(devinfo) = priv->epbulkin->eplog;
1139beacf11bSopenharmony_ci  priv->epbulkin->priv = priv;
1140beacf11bSopenharmony_ci
1141beacf11bSopenharmony_ci  /* Pre-allocate the OUT bulk endpoint */
1142beacf11bSopenharmony_ci
1143beacf11bSopenharmony_ci  priv->epbulkout = DEV_ALLOCEP(dev, g_cdcacm_hs_func_desc.oepd.bEndpointAddress, &g_cdcacm_hs_func_desc.oepd);
1144beacf11bSopenharmony_ci  if (!priv->epbulkout)
1145beacf11bSopenharmony_ci    {
1146beacf11bSopenharmony_ci      usb_err("alloc epbulkout fail!");
1147beacf11bSopenharmony_ci      ret = -ENODEV;
1148beacf11bSopenharmony_ci      goto errout;
1149beacf11bSopenharmony_ci    }
1150beacf11bSopenharmony_ci  CDCACM_MKEPBULKOUT(devinfo) = priv->epbulkout->eplog;
1151beacf11bSopenharmony_ci  priv->epbulkout->priv = priv;
1152beacf11bSopenharmony_ci
1153beacf11bSopenharmony_ci  /* Pre-allocate read requests.  The buffer size is one full packet. */
1154beacf11bSopenharmony_ci
1155beacf11bSopenharmony_ci#ifdef DWC3_USB_SERIAL
1156beacf11bSopenharmony_ci  reqlen = CONFIG_CDCACM_EPBULKOUT_HSSIZE;
1157beacf11bSopenharmony_ci#else
1158beacf11bSopenharmony_ci  reqlen = CONFIG_CDCACM_EPBULKOUT_FSSIZE;
1159beacf11bSopenharmony_ci#endif
1160beacf11bSopenharmony_ci
1161beacf11bSopenharmony_ci  priv->epbulkout->maxpacket = reqlen;
1162beacf11bSopenharmony_ci
1163beacf11bSopenharmony_ci  /* initialize read req buffer */
1164beacf11bSopenharmony_ci
1165beacf11bSopenharmony_ci  rdcontainer = &priv->rdreqs;
1166beacf11bSopenharmony_ci
1167beacf11bSopenharmony_ci  /* alloc req and req->buf */
1168beacf11bSopenharmony_ci
1169beacf11bSopenharmony_ci  rdcontainer->req = cdcacm_allocreq(priv->epbulkout, reqlen);
1170beacf11bSopenharmony_ci  if (rdcontainer->req == NULL)
1171beacf11bSopenharmony_ci    {
1172beacf11bSopenharmony_ci      usb_err("allocreq failed!\r\n");
1173beacf11bSopenharmony_ci      ret = -ENOMEM;
1174beacf11bSopenharmony_ci      goto errout;
1175beacf11bSopenharmony_ci    }
1176beacf11bSopenharmony_ci
1177beacf11bSopenharmony_ci  rdcontainer->buflen         = reqlen;
1178beacf11bSopenharmony_ci  rdcontainer->req->priv      = rdcontainer;
1179beacf11bSopenharmony_ci  rdcontainer->req->callback  = cdcacm_rdcomplete;
1180beacf11bSopenharmony_ci  priv->epbulkout->handle_req = rdcontainer->req;
1181beacf11bSopenharmony_ci
1182beacf11bSopenharmony_ci  /* Pre-allocate write request containers and put in a free list.  The
1183beacf11bSopenharmony_ci   * buffer size should be larger than a full build IN packet.  Otherwise,
1184beacf11bSopenharmony_ci   * we will send a bogus null packet at the end of each packet.
1185beacf11bSopenharmony_ci   *
1186beacf11bSopenharmony_ci   * Pick the larger of the max packet size and the configured request size.
1187beacf11bSopenharmony_ci   *
1188beacf11bSopenharmony_ci   * NOTE: These write requests are sized for the bulk IN endpoint but are
1189beacf11bSopenharmony_ci   * shared with interrupt IN endpoint which does not need a large buffer.
1190beacf11bSopenharmony_ci   */
1191beacf11bSopenharmony_ci
1192beacf11bSopenharmony_ci#ifdef DWC3_USB_SERIAL
1193beacf11bSopenharmony_ci  reqlen = CONFIG_CDCACM_EPBULKIN_HSSIZE;
1194beacf11bSopenharmony_ci#else
1195beacf11bSopenharmony_ci  reqlen = CONFIG_CDCACM_EPBULKIN_FSSIZE;
1196beacf11bSopenharmony_ci#endif
1197beacf11bSopenharmony_ci
1198beacf11bSopenharmony_ci  wrcontainer      = &priv->wrreqs;
1199beacf11bSopenharmony_ci  wrcontainer->req = cdcacm_allocreq(priv->epbulkin, reqlen);
1200beacf11bSopenharmony_ci  if (wrcontainer->req == NULL)
1201beacf11bSopenharmony_ci    {
1202beacf11bSopenharmony_ci      ret = -ENOMEM;
1203beacf11bSopenharmony_ci      goto errout;
1204beacf11bSopenharmony_ci    }
1205beacf11bSopenharmony_ci  wrcontainer->req->priv     = wrcontainer;
1206beacf11bSopenharmony_ci  wrcontainer->req->callback = cdcacm_wrcomplete;
1207beacf11bSopenharmony_ci  priv->epbulkin->handle_req = wrcontainer->req;
1208beacf11bSopenharmony_ci
1209beacf11bSopenharmony_ci  /* Alloc mem for ringbuffer */
1210beacf11bSopenharmony_ci
1211beacf11bSopenharmony_ci  wrcontainer->data_buffer = malloc(RING_BUFFER_SIZE);
1212beacf11bSopenharmony_ci  if (wrcontainer->data_buffer == NULL)
1213beacf11bSopenharmony_ci    {
1214beacf11bSopenharmony_ci      ret = -ENOMEM;
1215beacf11bSopenharmony_ci      goto errout;
1216beacf11bSopenharmony_ci    }
1217beacf11bSopenharmony_ci  (void)memset_s(wrcontainer->data_buffer, RING_BUFFER_SIZE, 0, RING_BUFFER_SIZE);
1218beacf11bSopenharmony_ci  wrcontainer->receive_buffer = wrcontainer->data_buffer;
1219beacf11bSopenharmony_ci  wrcontainer->send_buffer    = wrcontainer->data_buffer;
1220beacf11bSopenharmony_ci
1221beacf11bSopenharmony_ci  return OK;
1222beacf11bSopenharmony_ci
1223beacf11bSopenharmony_cierrout:
1224beacf11bSopenharmony_ci  (void)cdcacm_unbind(driver, dev);
1225beacf11bSopenharmony_ci  return ret;
1226beacf11bSopenharmony_ci}
1227beacf11bSopenharmony_ci
1228beacf11bSopenharmony_ci/****************************************************************************
1229beacf11bSopenharmony_ci * Name: cdcacm_unbind
1230beacf11bSopenharmony_ci *
1231beacf11bSopenharmony_ci * Description:
1232beacf11bSopenharmony_ci *    Invoked when the driver is unbound from a USB device driver
1233beacf11bSopenharmony_ci *
1234beacf11bSopenharmony_ci ****************************************************************************/
1235beacf11bSopenharmony_ci
1236beacf11bSopenharmony_cistatic int cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
1237beacf11bSopenharmony_ci                         FAR struct usbdev_s *dev)
1238beacf11bSopenharmony_ci{
1239beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1240beacf11bSopenharmony_ci  FAR struct cdcacm_wrreq_s *wrcontainer;
1241beacf11bSopenharmony_ci  FAR struct cdcacm_rdreq_s *rdcontainer;
1242beacf11bSopenharmony_ci  int ret = -EINVAL;
1243beacf11bSopenharmony_ci
1244beacf11bSopenharmony_ci  if (driver == NULL || dev == NULL)
1245beacf11bSopenharmony_ci    {
1246beacf11bSopenharmony_ci      usb_err("no device!\r\n");
1247beacf11bSopenharmony_ci      return -EINVAL;
1248beacf11bSopenharmony_ci    }
1249beacf11bSopenharmony_ci
1250beacf11bSopenharmony_ci  /* Extract reference to private data */
1251beacf11bSopenharmony_ci
1252beacf11bSopenharmony_ci  priv = ((FAR struct cdcacm_driver_s *)driver)->dev;
1253beacf11bSopenharmony_ci
1254beacf11bSopenharmony_ci  /* Make sure that we are not already unbound */
1255beacf11bSopenharmony_ci
1256beacf11bSopenharmony_ci  if (priv != NULL)
1257beacf11bSopenharmony_ci    {
1258beacf11bSopenharmony_ci      /* Close device */
1259beacf11bSopenharmony_ci
1260beacf11bSopenharmony_ci      cdcacm_disconnect(driver, dev);
1261beacf11bSopenharmony_ci
1262beacf11bSopenharmony_ci      if (priv->epintin->handle_req != NULL)
1263beacf11bSopenharmony_ci        {
1264beacf11bSopenharmony_ci          cdcacm_freereq(priv->epintin, priv->epintin->handle_req);
1265beacf11bSopenharmony_ci          priv->epintin->handle_req = NULL;
1266beacf11bSopenharmony_ci        }
1267beacf11bSopenharmony_ci
1268beacf11bSopenharmony_ci      /* Free the interrupt IN endpoint */
1269beacf11bSopenharmony_ci
1270beacf11bSopenharmony_ci      if (priv->epintin)
1271beacf11bSopenharmony_ci        {
1272beacf11bSopenharmony_ci          DEV_FREEEP(dev, priv->epintin);
1273beacf11bSopenharmony_ci          priv->epintin = NULL;
1274beacf11bSopenharmony_ci        }
1275beacf11bSopenharmony_ci
1276beacf11bSopenharmony_ci      /* Free pre-allocated read requests (which should all have
1277beacf11bSopenharmony_ci       * been returned to the free list at this time -- we don't check)
1278beacf11bSopenharmony_ci       */
1279beacf11bSopenharmony_ci
1280beacf11bSopenharmony_ci      rdcontainer = &priv->rdreqs;
1281beacf11bSopenharmony_ci      if (rdcontainer->req != NULL)
1282beacf11bSopenharmony_ci        {
1283beacf11bSopenharmony_ci          cdcacm_freereq(priv->epbulkout, rdcontainer->req);
1284beacf11bSopenharmony_ci          rdcontainer->req = NULL;
1285beacf11bSopenharmony_ci        }
1286beacf11bSopenharmony_ci
1287beacf11bSopenharmony_ci      /* Free the bulk OUT endpoint */
1288beacf11bSopenharmony_ci
1289beacf11bSopenharmony_ci      if (priv->epbulkout)
1290beacf11bSopenharmony_ci        {
1291beacf11bSopenharmony_ci          DEV_FREEEP(dev, priv->epbulkout);
1292beacf11bSopenharmony_ci          priv->epbulkout = NULL;
1293beacf11bSopenharmony_ci        }
1294beacf11bSopenharmony_ci
1295beacf11bSopenharmony_ci      /* Free write requests that are not in use (which should be all
1296beacf11bSopenharmony_ci       * of them)
1297beacf11bSopenharmony_ci       */
1298beacf11bSopenharmony_ci
1299beacf11bSopenharmony_ci      wrcontainer = &priv->wrreqs;
1300beacf11bSopenharmony_ci      if (wrcontainer->req != NULL)
1301beacf11bSopenharmony_ci        {
1302beacf11bSopenharmony_ci          cdcacm_freereq(priv->epbulkin, wrcontainer->req);
1303beacf11bSopenharmony_ci          wrcontainer->req = NULL;
1304beacf11bSopenharmony_ci        }
1305beacf11bSopenharmony_ci
1306beacf11bSopenharmony_ci      /* Free the bulk IN endpoint */
1307beacf11bSopenharmony_ci
1308beacf11bSopenharmony_ci      if (priv->epbulkin)
1309beacf11bSopenharmony_ci        {
1310beacf11bSopenharmony_ci          DEV_FREEEP(dev, priv->epbulkin);
1311beacf11bSopenharmony_ci          priv->epbulkin = NULL;
1312beacf11bSopenharmony_ci        }
1313beacf11bSopenharmony_ci
1314beacf11bSopenharmony_ci      /* Unregister driver */
1315beacf11bSopenharmony_ci
1316beacf11bSopenharmony_ci      ret = unregister_driver(CDCACM_DEVNAME_FORMAT);
1317beacf11bSopenharmony_ci      if (ret != OK)
1318beacf11bSopenharmony_ci        {
1319beacf11bSopenharmony_ci          PRINT_ERR("%s chardev unregister failed!\n", __FUNCTION__);
1320beacf11bSopenharmony_ci          return ret;
1321beacf11bSopenharmony_ci        }
1322beacf11bSopenharmony_ci
1323beacf11bSopenharmony_ci        /* Destroy read event */
1324beacf11bSopenharmony_ci
1325beacf11bSopenharmony_ci      (void)LOS_EventDestroy(&priv->read_event);
1326beacf11bSopenharmony_ci
1327beacf11bSopenharmony_ci      /* Free ringbuffer */
1328beacf11bSopenharmony_ci
1329beacf11bSopenharmony_ci      if (wrcontainer->data_buffer != NULL)
1330beacf11bSopenharmony_ci        {
1331beacf11bSopenharmony_ci          free(wrcontainer->data_buffer);
1332beacf11bSopenharmony_ci          wrcontainer->data_buffer = NULL;
1333beacf11bSopenharmony_ci        }
1334beacf11bSopenharmony_ci    }
1335beacf11bSopenharmony_ci
1336beacf11bSopenharmony_ci  return ret;
1337beacf11bSopenharmony_ci}
1338beacf11bSopenharmony_ci
1339beacf11bSopenharmony_cistatic void cdcacm_set_line_complete(FAR struct usbdev_ep_s *ep,
1340beacf11bSopenharmony_ci                                     FAR struct usbdev_req_s *req)
1341beacf11bSopenharmony_ci{
1342beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1343beacf11bSopenharmony_ci  int ret;
1344beacf11bSopenharmony_ci
1345beacf11bSopenharmony_ci  (void)ep;
1346beacf11bSopenharmony_ci  priv = req->priv;
1347beacf11bSopenharmony_ci  if (req->result != 0)
1348beacf11bSopenharmony_ci    {
1349beacf11bSopenharmony_ci      return;
1350beacf11bSopenharmony_ci    }
1351beacf11bSopenharmony_ci
1352beacf11bSopenharmony_ci  g_usbSerialMask = 1;
1353beacf11bSopenharmony_ci  ret = memcpy_s(&priv->linecoding, sizeof(struct usb_cdc_line_state), req->buf, SIZEOF_CDC_LINECODING);
1354beacf11bSopenharmony_ci  if (ret != EOK)
1355beacf11bSopenharmony_ci    {
1356beacf11bSopenharmony_ci      usb_err("Memcpy failed!\r\n");
1357beacf11bSopenharmony_ci      return;
1358beacf11bSopenharmony_ci    }
1359beacf11bSopenharmony_ci}
1360beacf11bSopenharmony_ci
1361beacf11bSopenharmony_ci/****************************************************************************
1362beacf11bSopenharmony_ci * Name: cdcacm_setup
1363beacf11bSopenharmony_ci *
1364beacf11bSopenharmony_ci * Description:
1365beacf11bSopenharmony_ci *   Invoked for ep0 control requests.  This function probably executes
1366beacf11bSopenharmony_ci *   in the context of an interrupt handler.
1367beacf11bSopenharmony_ci *
1368beacf11bSopenharmony_ci ****************************************************************************/
1369beacf11bSopenharmony_ci
1370beacf11bSopenharmony_cistatic int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
1371beacf11bSopenharmony_ci                        FAR struct usbdev_s *dev,
1372beacf11bSopenharmony_ci                        FAR const struct usb_device_request *ctrl,
1373beacf11bSopenharmony_ci                        uint8_t *dataout, size_t outlen)
1374beacf11bSopenharmony_ci{
1375beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1376beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
1377beacf11bSopenharmony_ci  uint16_t value;
1378beacf11bSopenharmony_ci  uint16_t index;
1379beacf11bSopenharmony_ci  uint16_t len;
1380beacf11bSopenharmony_ci  int val = -EOPNOTSUPP;
1381beacf11bSopenharmony_ci  int ret;
1382beacf11bSopenharmony_ci
1383beacf11bSopenharmony_ci  (void)dataout;
1384beacf11bSopenharmony_ci  (void)outlen;
1385beacf11bSopenharmony_ci  if (driver == NULL || dev == NULL || ctrl == NULL)
1386beacf11bSopenharmony_ci    {
1387beacf11bSopenharmony_ci      return -EINVAL;
1388beacf11bSopenharmony_ci    }
1389beacf11bSopenharmony_ci
1390beacf11bSopenharmony_ci  /* Extract reference to private data */
1391beacf11bSopenharmony_ci
1392beacf11bSopenharmony_ci  priv = ((struct cdcacm_driver_s *)driver)->dev;
1393beacf11bSopenharmony_ci  if (priv == NULL)
1394beacf11bSopenharmony_ci    {
1395beacf11bSopenharmony_ci      return -ENODEV;
1396beacf11bSopenharmony_ci    }
1397beacf11bSopenharmony_ci
1398beacf11bSopenharmony_ci  req = priv->ctrlreq;
1399beacf11bSopenharmony_ci
1400beacf11bSopenharmony_ci  /* Extract the little-endian 16-bit values to host order */
1401beacf11bSopenharmony_ci
1402beacf11bSopenharmony_ci  value = UGETW(ctrl->wValue);
1403beacf11bSopenharmony_ci  index = UGETW(ctrl->wIndex);
1404beacf11bSopenharmony_ci  len   = UGETW(ctrl->wLength);
1405beacf11bSopenharmony_ci
1406beacf11bSopenharmony_ci  FALOG("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
1407beacf11bSopenharmony_ci        ctrl->bmRequestType, ctrl->bRequest, value, index, len);
1408beacf11bSopenharmony_ci  if (UT_GET_TYPE(ctrl->bmRequestType) == UT_STANDARD)
1409beacf11bSopenharmony_ci    {
1410beacf11bSopenharmony_ci      /**********************************************************************
1411beacf11bSopenharmony_ci       * Standard Requests
1412beacf11bSopenharmony_ci      **********************************************************************/
1413beacf11bSopenharmony_ci
1414beacf11bSopenharmony_ci      switch (ctrl->bRequest)
1415beacf11bSopenharmony_ci        {
1416beacf11bSopenharmony_ci        case USB_REQ_SET_CONFIGURATION:
1417beacf11bSopenharmony_ci          if (ctrl->bmRequestType == 0)
1418beacf11bSopenharmony_ci            {
1419beacf11bSopenharmony_ci              val = cdcacm_setconfig(priv, dev);
1420beacf11bSopenharmony_ci              return val;
1421beacf11bSopenharmony_ci            }
1422beacf11bSopenharmony_ci          break;
1423beacf11bSopenharmony_ci
1424beacf11bSopenharmony_ci        case USB_REQ_SET_INTERFACE:
1425beacf11bSopenharmony_ci          break;
1426beacf11bSopenharmony_ci
1427beacf11bSopenharmony_ci        /* If the serial device is used in as part of a composite device,
1428beacf11bSopenharmony_ci         * then the overall composite class configuration is managed by logic
1429beacf11bSopenharmony_ci         * in the composite device implementation.
1430beacf11bSopenharmony_ci         */
1431beacf11bSopenharmony_ci
1432beacf11bSopenharmony_ci        default:
1433beacf11bSopenharmony_ci          break;
1434beacf11bSopenharmony_ci        }
1435beacf11bSopenharmony_ci    }
1436beacf11bSopenharmony_ci  else if (UT_GET_TYPE(ctrl->bmRequestType) == UT_CLASS)
1437beacf11bSopenharmony_ci    {
1438beacf11bSopenharmony_ci      switch (ctrl->bRequest)
1439beacf11bSopenharmony_ci        {
1440beacf11bSopenharmony_ci        /* ACM_GET_LINE_CODING requests current DTE rate, stop-bits, parity,
1441beacf11bSopenharmony_ci         * and number-of-character bits. (Optional)
1442beacf11bSopenharmony_ci         */
1443beacf11bSopenharmony_ci
1444beacf11bSopenharmony_ci        case ACM_GET_LINE_CODING:
1445beacf11bSopenharmony_ci          if (ctrl->bmRequestType == (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) &&
1446beacf11bSopenharmony_ci              index == priv->devinfo.ifnobase) /* bmRequestType = 0xa1, bRequest = 0x21 */
1447beacf11bSopenharmony_ci            {
1448beacf11bSopenharmony_ci              if(index != priv->ctrl_id)
1449beacf11bSopenharmony_ci                {
1450beacf11bSopenharmony_ci                  goto failed_out;
1451beacf11bSopenharmony_ci                }
1452beacf11bSopenharmony_ci
1453beacf11bSopenharmony_ci              /* Return the current line status from the private data structure. */
1454beacf11bSopenharmony_ci
1455beacf11bSopenharmony_ci              val = (int)min_t(unsigned, len, sizeof(struct usb_cdc_line_state));
1456beacf11bSopenharmony_ci              ret = memcpy_s(req->buf, USB_COMP_EP0_BUFSIZ, &priv->linecoding, (uint32_t)val);
1457beacf11bSopenharmony_ci              if (ret != EOK)
1458beacf11bSopenharmony_ci                {
1459beacf11bSopenharmony_ci                  usb_err("memcpy_s fail, ret:%d\n", ret);
1460beacf11bSopenharmony_ci                  return ret;
1461beacf11bSopenharmony_ci                }
1462beacf11bSopenharmony_ci            }
1463beacf11bSopenharmony_ci          else
1464beacf11bSopenharmony_ci            {
1465beacf11bSopenharmony_ci              goto failed_out;
1466beacf11bSopenharmony_ci            }
1467beacf11bSopenharmony_ci          break;
1468beacf11bSopenharmony_ci
1469beacf11bSopenharmony_ci        /* ACM_SET_LINE_CODING configures DTE rate, stop-bits, parity, and
1470beacf11bSopenharmony_ci         * number-of-character bits. (Optional)
1471beacf11bSopenharmony_ci         */
1472beacf11bSopenharmony_ci
1473beacf11bSopenharmony_ci        case ACM_SET_LINE_CODING:
1474beacf11bSopenharmony_ci          if (ctrl->bmRequestType == (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) &&
1475beacf11bSopenharmony_ci              len == SIZEOF_CDC_LINECODING && /* dataout && len == outlen && */
1476beacf11bSopenharmony_ci              index == priv->devinfo.ifnobase) /* bmRequestType = 0x21, bRequest = 0x20 */
1477beacf11bSopenharmony_ci            {
1478beacf11bSopenharmony_ci              if (len != sizeof(struct usb_cdc_line_state) ||
1479beacf11bSopenharmony_ci                  index != priv->ctrl_id)
1480beacf11bSopenharmony_ci                {
1481beacf11bSopenharmony_ci                  goto failed_out;
1482beacf11bSopenharmony_ci                }
1483beacf11bSopenharmony_ci
1484beacf11bSopenharmony_ci              /* Save the new line coding in the private data structure.
1485beacf11bSopenharmony_ci               * NOTE: that this is conditional now because not all device
1486beacf11bSopenharmony_ci               * controller drivers supported provision of EP0 OUT data
1487beacf11bSopenharmony_ci               * with the setup command.
1488beacf11bSopenharmony_ci               */
1489beacf11bSopenharmony_ci
1490beacf11bSopenharmony_ci              req->priv = priv;
1491beacf11bSopenharmony_ci              req->callback = cdcacm_set_line_complete;
1492beacf11bSopenharmony_ci
1493beacf11bSopenharmony_ci              /* Respond with a zero length packet */
1494beacf11bSopenharmony_ci
1495beacf11bSopenharmony_ci              val = len;
1496beacf11bSopenharmony_ci            }
1497beacf11bSopenharmony_ci          else
1498beacf11bSopenharmony_ci            {
1499beacf11bSopenharmony_ci              goto failed_out;
1500beacf11bSopenharmony_ci            }
1501beacf11bSopenharmony_ci          break;
1502beacf11bSopenharmony_ci
1503beacf11bSopenharmony_ci        /* ACM_SET_CTRL_LINE_STATE: RS-232 signal used to tell the DCE
1504beacf11bSopenharmony_ci         * device the DTE device is now present. (Optional)
1505beacf11bSopenharmony_ci         */
1506beacf11bSopenharmony_ci
1507beacf11bSopenharmony_ci        case ACM_SET_CTRL_LINE_STATE:
1508beacf11bSopenharmony_ci          if (ctrl->bmRequestType == (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) &&
1509beacf11bSopenharmony_ci              index == priv->devinfo.ifnobase) /* bmRequestType = 0x21, bRequest = 0x22 */
1510beacf11bSopenharmony_ci            {
1511beacf11bSopenharmony_ci              if(index != priv->ctrl_id)
1512beacf11bSopenharmony_ci                {
1513beacf11bSopenharmony_ci                  goto failed_out;
1514beacf11bSopenharmony_ci                }
1515beacf11bSopenharmony_ci
1516beacf11bSopenharmony_ci              /* Save the control line state in the private data
1517beacf11bSopenharmony_ci               * structure. Only bits 0 and 1 have meaning.  Respond with a zero length packet.
1518beacf11bSopenharmony_ci               */
1519beacf11bSopenharmony_ci
1520beacf11bSopenharmony_ci              val = 0;
1521beacf11bSopenharmony_ci            }
1522beacf11bSopenharmony_ci          else
1523beacf11bSopenharmony_ci            {
1524beacf11bSopenharmony_ci              goto failed_out;
1525beacf11bSopenharmony_ci            }
1526beacf11bSopenharmony_ci          break;
1527beacf11bSopenharmony_ci        default:
1528beacf11bSopenharmony_ci          break;
1529beacf11bSopenharmony_cifailed_out:
1530beacf11bSopenharmony_ci          usb_err("type=%02x req=%02x value=%04x index=%04x len=%04x\n",
1531beacf11bSopenharmony_ci                  ctrl->bmRequestType, ctrl->bRequest, value, index, len);
1532beacf11bSopenharmony_ci        }
1533beacf11bSopenharmony_ci    }
1534beacf11bSopenharmony_ci
1535beacf11bSopenharmony_ci  if (val >= 0)
1536beacf11bSopenharmony_ci    {
1537beacf11bSopenharmony_ci      /* Configure the response */
1538beacf11bSopenharmony_ci
1539beacf11bSopenharmony_ci      req->len = (uint32_t)val;
1540beacf11bSopenharmony_ci      val      = EP_SUBMIT(dev->ep0, req);
1541beacf11bSopenharmony_ci      if (val != OK)
1542beacf11bSopenharmony_ci        {
1543beacf11bSopenharmony_ci          usb_err("acm response on err %d\n", val);
1544beacf11bSopenharmony_ci          req->result = OK;
1545beacf11bSopenharmony_ci        }
1546beacf11bSopenharmony_ci    }
1547beacf11bSopenharmony_ci  return val;
1548beacf11bSopenharmony_ci}
1549beacf11bSopenharmony_ci
1550beacf11bSopenharmony_cistatic uint32_t cdcacm_serial_connect_state(const struct cdcacm_dev_s *priv,
1551beacf11bSopenharmony_ci                                            struct usbdev_req_s *req,
1552beacf11bSopenharmony_ci                                            const void *data,
1553beacf11bSopenharmony_ci                                            uint16_t value,
1554beacf11bSopenharmony_ci                                            uint32_t len)
1555beacf11bSopenharmony_ci{
1556beacf11bSopenharmony_ci  struct usb_cdc_notification *state_buf;
1557beacf11bSopenharmony_ci  void *buf;
1558beacf11bSopenharmony_ci  uint32_t length;
1559beacf11bSopenharmony_ci  uint32_t ret;
1560beacf11bSopenharmony_ci
1561beacf11bSopenharmony_ci  state_buf = (struct usb_cdc_notification *)req->buf;
1562beacf11bSopenharmony_ci
1563beacf11bSopenharmony_ci  /* bmRequestType = 0xa1 , bNotification = 0x20 */
1564beacf11bSopenharmony_ci
1565beacf11bSopenharmony_ci  state_buf->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
1566beacf11bSopenharmony_ci  state_buf->bNotification = ACM_NOTIFY_SERIAL_STATE;
1567beacf11bSopenharmony_ci  USETW(state_buf->wValue, value);
1568beacf11bSopenharmony_ci  USETW(state_buf->wIndex, priv->ctrl_id);
1569beacf11bSopenharmony_ci  USETW(state_buf->wLength, len);
1570beacf11bSopenharmony_ci  length = sizeof(struct usb_cdc_notification) + len;
1571beacf11bSopenharmony_ci
1572beacf11bSopenharmony_ci  buf = state_buf + STAE_BUFFER_OFFSET;
1573beacf11bSopenharmony_ci  ret = (uint32_t)memcpy_s(buf, sizeof(struct usb_cdc_notification), data, len);
1574beacf11bSopenharmony_ci  if (ret != EOK)
1575beacf11bSopenharmony_ci    {
1576beacf11bSopenharmony_ci      usb_err("memcpy failed!\r\n");
1577beacf11bSopenharmony_ci      return ret;
1578beacf11bSopenharmony_ci    }
1579beacf11bSopenharmony_ci
1580beacf11bSopenharmony_ci  return length;
1581beacf11bSopenharmony_ci}
1582beacf11bSopenharmony_ci
1583beacf11bSopenharmony_cistatic int cdcacm_serial_connect(FAR struct cdcacm_dev_s *priv)
1584beacf11bSopenharmony_ci{
1585beacf11bSopenharmony_ci  FAR struct usbdev_ep_s *ep;
1586beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
1587beacf11bSopenharmony_ci  uint32_t length;
1588beacf11bSopenharmony_ci  int ret;
1589beacf11bSopenharmony_ci
1590beacf11bSopenharmony_ci  if (priv == NULL)
1591beacf11bSopenharmony_ci    {
1592beacf11bSopenharmony_ci      usb_err("no device can be found!\r\n");
1593beacf11bSopenharmony_ci      return -ENODEV;
1594beacf11bSopenharmony_ci    }
1595beacf11bSopenharmony_ci
1596beacf11bSopenharmony_ci  /* DCD:online; DSR:ready for data transhfer */
1597beacf11bSopenharmony_ci
1598beacf11bSopenharmony_ci  priv->serialstate |= CDCACM_UART_DSR | CDCACM_UART_DCD;
1599beacf11bSopenharmony_ci  ep = priv->epintin;
1600beacf11bSopenharmony_ci  if (ep == NULL)
1601beacf11bSopenharmony_ci    {
1602beacf11bSopenharmony_ci      return -EINVAL;
1603beacf11bSopenharmony_ci    }
1604beacf11bSopenharmony_ci  req = ep->handle_req;
1605beacf11bSopenharmony_ci  if (req == NULL)
1606beacf11bSopenharmony_ci    {
1607beacf11bSopenharmony_ci      priv->wating = true;
1608beacf11bSopenharmony_ci      return 0;
1609beacf11bSopenharmony_ci    }
1610beacf11bSopenharmony_ci
1611beacf11bSopenharmony_ci  /* Status of serial for connect and disconnect */
1612beacf11bSopenharmony_ci
1613beacf11bSopenharmony_ci  length = cdcacm_serial_connect_state(priv, req, &priv->serialstate, 0, sizeof(priv->serialstate));
1614beacf11bSopenharmony_ci
1615beacf11bSopenharmony_ci  req->priv = priv;
1616beacf11bSopenharmony_ci  req->len  = length;
1617beacf11bSopenharmony_ci
1618beacf11bSopenharmony_ci  /* submit serial notify state */
1619beacf11bSopenharmony_ci
1620beacf11bSopenharmony_ci  ret = EP_SUBMIT(ep, req);
1621beacf11bSopenharmony_ci  if (ret != OK)
1622beacf11bSopenharmony_ci    {
1623beacf11bSopenharmony_ci      usb_err("can not send notify data to host\r\n");
1624beacf11bSopenharmony_ci    }
1625beacf11bSopenharmony_ci  priv->wating = false;
1626beacf11bSopenharmony_ci  return ret;
1627beacf11bSopenharmony_ci}
1628beacf11bSopenharmony_ci
1629beacf11bSopenharmony_cistatic int cdcacm_serial_disconnect(FAR struct cdcacm_dev_s *priv)
1630beacf11bSopenharmony_ci{
1631beacf11bSopenharmony_ci  FAR struct usbdev_req_s *req;
1632beacf11bSopenharmony_ci  FAR struct usbdev_ep_s *ep;
1633beacf11bSopenharmony_ci  uint32_t length;
1634beacf11bSopenharmony_ci  int ret;
1635beacf11bSopenharmony_ci
1636beacf11bSopenharmony_ci  g_usbSerialMask = 0;
1637beacf11bSopenharmony_ci  priv->received_char = false;
1638beacf11bSopenharmony_ci
1639beacf11bSopenharmony_ci  /* Offline, close data transfer */
1640beacf11bSopenharmony_ci
1641beacf11bSopenharmony_ci  priv->serialstate &= ~CDC_UART_CONSISTENT;
1642beacf11bSopenharmony_ci  ep  = priv->epintin;
1643beacf11bSopenharmony_ci  req = ep->handle_req;
1644beacf11bSopenharmony_ci
1645beacf11bSopenharmony_ci  /* Status of serial for connect and disconnect */
1646beacf11bSopenharmony_ci
1647beacf11bSopenharmony_ci  length = cdcacm_serial_connect_state(priv, req, &priv->serialstate, 0, sizeof(priv->serialstate));
1648beacf11bSopenharmony_ci
1649beacf11bSopenharmony_ci  req->len = length;
1650beacf11bSopenharmony_ci
1651beacf11bSopenharmony_ci  /* Submit serial notify state */
1652beacf11bSopenharmony_ci
1653beacf11bSopenharmony_ci  ret = EP_SUBMIT(ep, req);
1654beacf11bSopenharmony_ci  if (ret != OK)
1655beacf11bSopenharmony_ci    {
1656beacf11bSopenharmony_ci      usb_err("Can not send notify data to host!\r\n");
1657beacf11bSopenharmony_ci    }
1658beacf11bSopenharmony_ci
1659beacf11bSopenharmony_ci  return ret;
1660beacf11bSopenharmony_ci}
1661beacf11bSopenharmony_ci
1662beacf11bSopenharmony_cistatic int cdcuart_open(FAR struct file *filep)
1663beacf11bSopenharmony_ci{
1664beacf11bSopenharmony_ci  /* do nothing */
1665beacf11bSopenharmony_ci
1666beacf11bSopenharmony_ci  (void)filep;
1667beacf11bSopenharmony_ci  return 0;
1668beacf11bSopenharmony_ci}
1669beacf11bSopenharmony_ci
1670beacf11bSopenharmony_ci/****************************************************************************
1671beacf11bSopenharmony_ci * Name: cdcuart_ioctl
1672beacf11bSopenharmony_ci *
1673beacf11bSopenharmony_ci * Description:
1674beacf11bSopenharmony_ci *   All ioctl calls will be routed through this method
1675beacf11bSopenharmony_ci *
1676beacf11bSopenharmony_ci ****************************************************************************/
1677beacf11bSopenharmony_ci
1678beacf11bSopenharmony_cistatic int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
1679beacf11bSopenharmony_ci{
1680beacf11bSopenharmony_ci  //FAR struct inode *inode;
1681beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1682beacf11bSopenharmony_ci
1683beacf11bSopenharmony_ci  struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
1684beacf11bSopenharmony_ci  priv = (struct cdcacm_dev_s *)drv->priv;
1685beacf11bSopenharmony_ci  if (priv == NULL)
1686beacf11bSopenharmony_ci    {
1687beacf11bSopenharmony_ci      usb_err("No Device!\r\n");
1688beacf11bSopenharmony_ci      return -ENODEV;
1689beacf11bSopenharmony_ci    }
1690beacf11bSopenharmony_ci  switch (cmd)
1691beacf11bSopenharmony_ci    {
1692beacf11bSopenharmony_ci    /* CAICO_REGISTERCB
1693beacf11bSopenharmony_ci     *   Register a callback for serial event notification. Argument:
1694beacf11bSopenharmony_ci     *   cdcacm_callback_t.  See cdcacm_callback_t type definition below.
1695beacf11bSopenharmony_ci     *   NOTE:  The callback will most likely invoked at the interrupt level.
1696beacf11bSopenharmony_ci     *   The called back function should, therefore, limit its operations to
1697beacf11bSopenharmony_ci     *   invoking some kind of IPC to handle the serial event in some normal
1698beacf11bSopenharmony_ci     *   task environment.
1699beacf11bSopenharmony_ci     */
1700beacf11bSopenharmony_ci
1701beacf11bSopenharmony_ci    case CONSOLE_CMD_RD_BLOCK_SERIAL:
1702beacf11bSopenharmony_ci      {
1703beacf11bSopenharmony_ci        if (arg != 0)
1704beacf11bSopenharmony_ci          {
1705beacf11bSopenharmony_ci            g_readpend = true;
1706beacf11bSopenharmony_ci          }
1707beacf11bSopenharmony_ci        else
1708beacf11bSopenharmony_ci          {
1709beacf11bSopenharmony_ci            g_readpend = false;
1710beacf11bSopenharmony_ci            (void)LOS_EventWrite(&priv->read_event, USB_SERIAL_READ_EVENT);
1711beacf11bSopenharmony_ci          }
1712beacf11bSopenharmony_ci      }
1713beacf11bSopenharmony_ci      break;
1714beacf11bSopenharmony_ci
1715beacf11bSopenharmony_ci    default:
1716beacf11bSopenharmony_ci      usb_err("Unknown CMD!\r\n");
1717beacf11bSopenharmony_ci      break;
1718beacf11bSopenharmony_ci    }
1719beacf11bSopenharmony_ci
1720beacf11bSopenharmony_ci  return OK;
1721beacf11bSopenharmony_ci}
1722beacf11bSopenharmony_ci
1723beacf11bSopenharmony_ci/****************************************************************************
1724beacf11bSopenharmony_ci * Name: cdcacm_disconnect
1725beacf11bSopenharmony_ci *
1726beacf11bSopenharmony_ci * Description:
1727beacf11bSopenharmony_ci *   Invoked after all transfers have been stopped, when the host is
1728beacf11bSopenharmony_ci *   disconnected.  This function is probably called from the context of an
1729beacf11bSopenharmony_ci *   interrupt handler.
1730beacf11bSopenharmony_ci *
1731beacf11bSopenharmony_ci ****************************************************************************/
1732beacf11bSopenharmony_ci
1733beacf11bSopenharmony_cistatic void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
1734beacf11bSopenharmony_ci                              FAR struct usbdev_s *dev)
1735beacf11bSopenharmony_ci{
1736beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1737beacf11bSopenharmony_ci
1738beacf11bSopenharmony_ci  (void)dev;
1739beacf11bSopenharmony_ci  if (driver == NULL)
1740beacf11bSopenharmony_ci    {
1741beacf11bSopenharmony_ci      usb_err("driver pointer is NULL!\r\n");
1742beacf11bSopenharmony_ci      return;
1743beacf11bSopenharmony_ci    }
1744beacf11bSopenharmony_ci
1745beacf11bSopenharmony_ci  priv = ((FAR struct cdcacm_driver_s *)driver)->dev;
1746beacf11bSopenharmony_ci  if (priv == NULL)
1747beacf11bSopenharmony_ci    {
1748beacf11bSopenharmony_ci      usb_err("No device!\r\n");
1749beacf11bSopenharmony_ci      return;
1750beacf11bSopenharmony_ci    }
1751beacf11bSopenharmony_ci
1752beacf11bSopenharmony_ci  if (priv->bdisconnect == false)
1753beacf11bSopenharmony_ci    {
1754beacf11bSopenharmony_ci      (void)cdcacm_serial_disconnect(priv);
1755beacf11bSopenharmony_ci      cdcacm_resetconfig(priv);
1756beacf11bSopenharmony_ci      priv->bdisconnect = true;
1757beacf11bSopenharmony_ci    }
1758beacf11bSopenharmony_ci}
1759beacf11bSopenharmony_ci
1760beacf11bSopenharmony_ci/****************************************************************************
1761beacf11bSopenharmony_ci * Public Functions
1762beacf11bSopenharmony_ci ****************************************************************************/
1763beacf11bSopenharmony_ci
1764beacf11bSopenharmony_civolatile unsigned int userial_mask_get(void)
1765beacf11bSopenharmony_ci{
1766beacf11bSopenharmony_ci  return g_usbSerialMask;
1767beacf11bSopenharmony_ci}
1768beacf11bSopenharmony_ci
1769beacf11bSopenharmony_civoid userial_mask_set(unsigned int val)
1770beacf11bSopenharmony_ci{
1771beacf11bSopenharmony_ci  g_usbSerialMask = val;
1772beacf11bSopenharmony_ci}
1773beacf11bSopenharmony_ci
1774beacf11bSopenharmony_ci/****************************************************************************
1775beacf11bSopenharmony_ci * Name: cdcacm_classobject
1776beacf11bSopenharmony_ci *
1777beacf11bSopenharmony_ci * Description:
1778beacf11bSopenharmony_ci *   Register USB serial port (and USB serial console if so configured) and
1779beacf11bSopenharmony_ci *   return the class object.
1780beacf11bSopenharmony_ci *
1781beacf11bSopenharmony_ci * Input Parameters:
1782beacf11bSopenharmony_ci *   devinfo - Describes the low level bindings of an usb device.
1783beacf11bSopenharmony_ci *   classdev - The location to return the CDC serial class' device
1784beacf11bSopenharmony_ci *     instance.
1785beacf11bSopenharmony_ci *
1786beacf11bSopenharmony_ci * Returned Value:
1787beacf11bSopenharmony_ci *   A pointer to the allocated class object (NULL on failure).
1788beacf11bSopenharmony_ci *
1789beacf11bSopenharmony_ci ****************************************************************************/
1790beacf11bSopenharmony_ci
1791beacf11bSopenharmony_ciint cdcacm_classobject(int minor,
1792beacf11bSopenharmony_ci                       FAR struct usbdev_devinfo_s *devinfo,
1793beacf11bSopenharmony_ci                       FAR struct usbdevclass_driver_s **classdev)
1794beacf11bSopenharmony_ci{
1795beacf11bSopenharmony_ci  FAR struct cdcacm_alloc_s *alloc;
1796beacf11bSopenharmony_ci  FAR struct cdcacm_dev_s *priv;
1797beacf11bSopenharmony_ci  FAR struct cdcacm_driver_s *drvr;
1798beacf11bSopenharmony_ci
1799beacf11bSopenharmony_ci  (void)minor;
1800beacf11bSopenharmony_ci
1801beacf11bSopenharmony_ci  /* Allocate the structures needed */
1802beacf11bSopenharmony_ci
1803beacf11bSopenharmony_ci  alloc = (FAR struct cdcacm_alloc_s *)malloc(sizeof(struct cdcacm_alloc_s));
1804beacf11bSopenharmony_ci  if (alloc == NULL)
1805beacf11bSopenharmony_ci    {
1806beacf11bSopenharmony_ci      usb_err("%s: malloc fialed!\r\n", __FUNCTION__);
1807beacf11bSopenharmony_ci      return -ENOMEM;
1808beacf11bSopenharmony_ci    }
1809beacf11bSopenharmony_ci
1810beacf11bSopenharmony_ci  /* Convenience pointers into the allocated blob */
1811beacf11bSopenharmony_ci
1812beacf11bSopenharmony_ci  priv = &alloc->dev;
1813beacf11bSopenharmony_ci  drvr = &alloc->drvr;
1814beacf11bSopenharmony_ci
1815beacf11bSopenharmony_ci  /* Initialize the USB serial driver structure */
1816beacf11bSopenharmony_ci
1817beacf11bSopenharmony_ci  (void)memset_s(priv, sizeof(struct cdcacm_dev_s), 0, sizeof(struct cdcacm_dev_s));
1818beacf11bSopenharmony_ci  (void)memcpy_s(&priv->devinfo, sizeof(struct usbdev_devinfo_s), devinfo, sizeof(struct usbdev_devinfo_s));
1819beacf11bSopenharmony_ci
1820beacf11bSopenharmony_ci  /* Fake line status */
1821beacf11bSopenharmony_ci
1822beacf11bSopenharmony_ci  USETDW(priv->linecoding.dwDTERate, 9600);        /* Baud = 9600 */
1823beacf11bSopenharmony_ci  priv->linecoding.bCharFormat = UCDC_STOP_BIT_1;  /* Stop bits */
1824beacf11bSopenharmony_ci  priv->linecoding.bParityType = UCDC_PARITY_NONE; /* No parity */
1825beacf11bSopenharmony_ci  priv->linecoding.bDataBits   = 8;                /* 8 data bits */
1826beacf11bSopenharmony_ci
1827beacf11bSopenharmony_ci  /* Initialize the USB class driver structure */
1828beacf11bSopenharmony_ci
1829beacf11bSopenharmony_ci  drvr->drvr.speed = USB_SPEED_HIGH;
1830beacf11bSopenharmony_ci  drvr->drvr.ops   = &g_driver_ops;
1831beacf11bSopenharmony_ci  drvr->dev        = priv;
1832beacf11bSopenharmony_ci  *classdev        = &drvr->drvr;
1833beacf11bSopenharmony_ci
1834beacf11bSopenharmony_ci  return 0;
1835beacf11bSopenharmony_ci}
1836beacf11bSopenharmony_ci
1837beacf11bSopenharmony_ci/****************************************************************************
1838beacf11bSopenharmony_ci * Name: cdcacm_uninitialize
1839beacf11bSopenharmony_ci *
1840beacf11bSopenharmony_ci * Description:
1841beacf11bSopenharmony_ci *   Un-initialize the USB storage class driver.  This function is used
1842beacf11bSopenharmony_ci *   internally by the USB composite driver to uninitialize the CDC/ACM
1843beacf11bSopenharmony_ci *   driver.  This same interface is available (with an untyped input
1844beacf11bSopenharmony_ci *   parameter) when the CDC/ACM driver is used standalone.
1845beacf11bSopenharmony_ci *
1846beacf11bSopenharmony_ci * Input Parameters:
1847beacf11bSopenharmony_ci *   There is one parameter, it differs in typing depending upon whether the
1848beacf11bSopenharmony_ci *   CDC/ACM driver is an internal part of a composite device, or a standalone
1849beacf11bSopenharmony_ci *   USB driver:
1850beacf11bSopenharmony_ci *
1851beacf11bSopenharmony_ci *     classdev - The class object returned by cdcacm_classobject()
1852beacf11bSopenharmony_ci *     handle - The opaque handle representing the class object returned by
1853beacf11bSopenharmony_ci *       a previous call to cdcacm_initialize().
1854beacf11bSopenharmony_ci *
1855beacf11bSopenharmony_ci * Returned Value:
1856beacf11bSopenharmony_ci *   None
1857beacf11bSopenharmony_ci *
1858beacf11bSopenharmony_ci ****************************************************************************/
1859beacf11bSopenharmony_ci
1860beacf11bSopenharmony_civoid cdcacm_uninitialize(FAR struct usbdevclass_driver_s *devclass_drvr)
1861beacf11bSopenharmony_ci{
1862beacf11bSopenharmony_ci  FAR struct cdcacm_driver_s *drvr = (struct cdcacm_driver_s *)devclass_drvr;
1863beacf11bSopenharmony_ci  FAR struct cdcacm_alloc_s *alloc;
1864beacf11bSopenharmony_ci
1865beacf11bSopenharmony_ci  if (drvr == NULL)
1866beacf11bSopenharmony_ci    {
1867beacf11bSopenharmony_ci      usb_err("Invalid pointer!\r\n");
1868beacf11bSopenharmony_ci      return;
1869beacf11bSopenharmony_ci    }
1870beacf11bSopenharmony_ci
1871beacf11bSopenharmony_ci  alloc = container_of(drvr, struct cdcacm_alloc_s, drvr);
1872beacf11bSopenharmony_ci  free(alloc);
1873beacf11bSopenharmony_ci}
1874beacf11bSopenharmony_ci
1875beacf11bSopenharmony_ci/****************************************************************************
1876beacf11bSopenharmony_ci * Name: cdcacm_get_composite_devdesc
1877beacf11bSopenharmony_ci *
1878beacf11bSopenharmony_ci * Description:
1879beacf11bSopenharmony_ci *   Helper function to fill in some constants into the composite
1880beacf11bSopenharmony_ci *   configuration struct.
1881beacf11bSopenharmony_ci *
1882beacf11bSopenharmony_ci * Input Parameters:
1883beacf11bSopenharmony_ci *     dev - Pointer to the configuration struct we should fill
1884beacf11bSopenharmony_ci *
1885beacf11bSopenharmony_ci * Returned Value:
1886beacf11bSopenharmony_ci *   None
1887beacf11bSopenharmony_ci *
1888beacf11bSopenharmony_ci ****************************************************************************/
1889beacf11bSopenharmony_ci
1890beacf11bSopenharmony_civoid cdcacm_get_composite_devdesc(struct composite_devdesc_s *dev)
1891beacf11bSopenharmony_ci{
1892beacf11bSopenharmony_ci  (void)memset_s(dev, sizeof(struct composite_devdesc_s), 0, sizeof(struct composite_devdesc_s));
1893beacf11bSopenharmony_ci
1894beacf11bSopenharmony_ci  dev->mkdevdesc  = cdcacm_mkdevdesc;
1895beacf11bSopenharmony_ci  dev->mkconfdesc = cdcacm_mkcfgdesc;
1896beacf11bSopenharmony_ci  dev->mkstrdesc  = cdcacm_mkstrdesc;
1897beacf11bSopenharmony_ci
1898beacf11bSopenharmony_ci  dev->nconfigs = CDCACM_NCONFIGS;  /* Number of configurations supported */
1899beacf11bSopenharmony_ci  dev->configid = CDCACM_CONFIGID;  /* The only supported configuration ID */
1900beacf11bSopenharmony_ci
1901beacf11bSopenharmony_ci  /* Interfaces.
1902beacf11bSopenharmony_ci   *
1903beacf11bSopenharmony_ci   * ifnobase must be provided by board-specific logic
1904beacf11bSopenharmony_ci   */
1905beacf11bSopenharmony_ci
1906beacf11bSopenharmony_ci  dev->devinfo.ninterfaces = CDCACM_NINTERFACES;  /* Number of interfaces in the configuration */
1907beacf11bSopenharmony_ci
1908beacf11bSopenharmony_ci  /* Strings.
1909beacf11bSopenharmony_ci   *
1910beacf11bSopenharmony_ci   * strbase must be provided by board-specific logic
1911beacf11bSopenharmony_ci   */
1912beacf11bSopenharmony_ci
1913beacf11bSopenharmony_ci  dev->devinfo.nstrings = CDCACM_NSTRIDS;  /* Number of Strings */
1914beacf11bSopenharmony_ci
1915beacf11bSopenharmony_ci  /* Endpoints.
1916beacf11bSopenharmony_ci   *
1917beacf11bSopenharmony_ci   * Endpoint numbers must be provided by board-specific logic.
1918beacf11bSopenharmony_ci   */
1919beacf11bSopenharmony_ci
1920beacf11bSopenharmony_ci  dev->devinfo.nendpoints = CDCACM_NUM_EPS; /* Number of Endpoint */
1921beacf11bSopenharmony_ci}
1922beacf11bSopenharmony_ci
1923beacf11bSopenharmony_ci/* Init composite public action */
1924beacf11bSopenharmony_ci
1925beacf11bSopenharmony_civoid usbdev_cdcacm_initialize_sub(FAR struct composite_devdesc_s *dev, int ifnobase, int minor)
1926beacf11bSopenharmony_ci{
1927beacf11bSopenharmony_ci  /* Ask the serial driver to fill in the constants we didn't
1928beacf11bSopenharmony_ci   * know here.
1929beacf11bSopenharmony_ci   */
1930beacf11bSopenharmony_ci
1931beacf11bSopenharmony_ci  cdcacm_get_composite_devdesc(dev);
1932beacf11bSopenharmony_ci
1933beacf11bSopenharmony_ci  /* Overwrite and correct some values... */
1934beacf11bSopenharmony_ci
1935beacf11bSopenharmony_ci  dev->classobject  = cdcacm_classobject;
1936beacf11bSopenharmony_ci  dev->uninitialize = cdcacm_uninitialize;
1937beacf11bSopenharmony_ci
1938beacf11bSopenharmony_ci  /* init ifnobase of usbdev_devinfo_s for judegment wIndex */
1939beacf11bSopenharmony_ci
1940beacf11bSopenharmony_ci  dev->devinfo.ifnobase = ifnobase;  /* Offset to Interface-IDs */
1941beacf11bSopenharmony_ci  dev->minor            = minor;     /* The minor interface number */
1942beacf11bSopenharmony_ci
1943beacf11bSopenharmony_ci  /* Strings */
1944beacf11bSopenharmony_ci
1945beacf11bSopenharmony_ci  dev->devinfo.strbase = 0;          /* Offset to String Numbers */
1946beacf11bSopenharmony_ci}
1947beacf11bSopenharmony_ci
1948beacf11bSopenharmony_ciint usbdev_cdcacm_initialize (FAR struct module *mod, int n, FAR void *arg)
1949beacf11bSopenharmony_ci{
1950beacf11bSopenharmony_ci  FAR struct composite_softc *com_s = (struct composite_softc *)arg;
1951beacf11bSopenharmony_ci  struct composite_devdesc_s dev;
1952beacf11bSopenharmony_ci  int ret;
1953beacf11bSopenharmony_ci
1954beacf11bSopenharmony_ci  (void)mod;
1955beacf11bSopenharmony_ci  (void)n;
1956beacf11bSopenharmony_ci  if (com_s == NULL)
1957beacf11bSopenharmony_ci    {
1958beacf11bSopenharmony_ci      return -1;
1959beacf11bSopenharmony_ci    }
1960beacf11bSopenharmony_ci
1961beacf11bSopenharmony_ci  usbdev_cdcacm_initialize_sub(&dev, 0, DEV_SERIAL);
1962beacf11bSopenharmony_ci  ret = composite_initialize(com_s, 1, &dev);
1963beacf11bSopenharmony_ci  if (ret)
1964beacf11bSopenharmony_ci    {
1965beacf11bSopenharmony_ci      return -1;
1966beacf11bSopenharmony_ci    }
1967beacf11bSopenharmony_ci  PRINTK(" ** Serial device initialized successfully! **\n ");
1968beacf11bSopenharmony_ci
1969beacf11bSopenharmony_ci  return 0;
1970beacf11bSopenharmony_ci}
1971