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