1beacf11bSopenharmony_ci/****************************************************************************
2beacf11bSopenharmony_ci * drivers/usbdev/dfu.c
3beacf11bSopenharmony_ci *
4beacf11bSopenharmony_ci *   Copyright (C) 2011-2018 Gregory Nutt. All rights reserved.
5beacf11bSopenharmony_ci *   Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
6beacf11bSopenharmony_ci *
7beacf11bSopenharmony_ci *   Authors: Petteri Aimonen <jpa@git.mail.kapsi.fi>
8beacf11bSopenharmony_ci *
9beacf11bSopenharmony_ci * Redistribution and use in source and binary forms, with or without
10beacf11bSopenharmony_ci * modification, are permitted provided that the following conditions
11beacf11bSopenharmony_ci * are met:
12beacf11bSopenharmony_ci *
13beacf11bSopenharmony_ci * 1. Redistributions of source code must retain the above copyright
14beacf11bSopenharmony_ci *    notice, this list of conditions and the following disclaimer.
15beacf11bSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
16beacf11bSopenharmony_ci *    notice, this list of conditions and the following disclaimer in
17beacf11bSopenharmony_ci *    the documentation and/or other materials provided with the
18beacf11bSopenharmony_ci *    distribution.
19beacf11bSopenharmony_ci * 3. Neither the name NuttX nor the names of its contributors may be
20beacf11bSopenharmony_ci *    used to endorse or promote products derived from this software
21beacf11bSopenharmony_ci *    without specific prior written permission.
22beacf11bSopenharmony_ci *
23beacf11bSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24beacf11bSopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25beacf11bSopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26beacf11bSopenharmony_ci * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27beacf11bSopenharmony_ci * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28beacf11bSopenharmony_ci * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29beacf11bSopenharmony_ci * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
30beacf11bSopenharmony_ci * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31beacf11bSopenharmony_ci * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32beacf11bSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33beacf11bSopenharmony_ci * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34beacf11bSopenharmony_ci * POSSIBILITY OF SUCH DAMAGE.
35beacf11bSopenharmony_ci *
36beacf11bSopenharmony_ci ****************************************************************************/
37beacf11bSopenharmony_ci/****************************************************************************
38beacf11bSopenharmony_ci * Notice of Export Control Law
39beacf11bSopenharmony_ci * ===============================================
40beacf11bSopenharmony_ci * Huawei LiteOS may be subject to applicable export control laws and regulations,
41beacf11bSopenharmony_ci * which might include those applicable to Huawei LiteOS of U.S. and the country in
42beacf11bSopenharmony_ci * which you are located.
43beacf11bSopenharmony_ci * Import, export and usage of Huawei LiteOS in any manner by you shall be in
44beacf11bSopenharmony_ci * compliance with such applicable export control laws and regulations.
45beacf11bSopenharmony_ci ****************************************************************************/
46beacf11bSopenharmony_ci
47beacf11bSopenharmony_ci/* This is a driver for the USB Device Firmware Upgrade protocol v1.1.
48beacf11bSopenharmony_ci * Currently it supports the app-side ("Run-Time") part of the protocol:
49beacf11bSopenharmony_ci * a sequence of DFU_DETACH and USB reset commands, which will reboot into
50beacf11bSopenharmony_ci * a separate USB DFU bootloader.
51beacf11bSopenharmony_ci *
52beacf11bSopenharmony_ci * The bootloader is provided by board-specific logic, or STM32's
53beacf11bSopenharmony_ci * built-in ROM bootloader can be used.
54beacf11bSopenharmony_ci *
55beacf11bSopenharmony_ci * https://www.usb.org/sites/default/files/DFU_1.1.pdf
56beacf11bSopenharmony_ci */
57beacf11bSopenharmony_ci
58beacf11bSopenharmony_ci/****************************************************************************
59beacf11bSopenharmony_ci * Included Files
60beacf11bSopenharmony_ci ****************************************************************************/
61beacf11bSopenharmony_ci
62beacf11bSopenharmony_ci#include <errno.h>
63beacf11bSopenharmony_ci#include <string.h>
64beacf11bSopenharmony_ci#include <stdlib.h>
65beacf11bSopenharmony_ci#include <stdio.h>
66beacf11bSopenharmony_ci#include "gadget/composite.h"
67beacf11bSopenharmony_ci#include "gadget/f_dfu.h"
68beacf11bSopenharmony_ci
69beacf11bSopenharmony_ci/****************************************************************************
70beacf11bSopenharmony_ci * Pre-processor definitions
71beacf11bSopenharmony_ci ****************************************************************************/
72beacf11bSopenharmony_ci
73beacf11bSopenharmony_ci#define DFU_MAX_TIMEOUT     255
74beacf11bSopenharmony_ci#define DFU_MAX_TRANSFER    4096
75beacf11bSopenharmony_ci#define DFU_VERSION         0x0110
76beacf11bSopenharmony_ci
77beacf11bSopenharmony_ci/* All 16-bit values must be little-endian */
78beacf11bSopenharmony_ci
79beacf11bSopenharmony_ci#define MSBYTE(u16)         ((u16) >> 8)     /* Get MS byte from uint16_t */
80beacf11bSopenharmony_ci#define LSBYTE(u16)         ((u16) & 0xff)   /* Get LS byte from uint16_t */
81beacf11bSopenharmony_ci
82beacf11bSopenharmony_ci/****************************************************************************
83beacf11bSopenharmony_ci * Private Types
84beacf11bSopenharmony_ci ****************************************************************************/
85beacf11bSopenharmony_ci
86beacf11bSopenharmony_ci/* DFU functional descriptor */
87beacf11bSopenharmony_ci
88beacf11bSopenharmony_cistruct dfu_funcdesc_s
89beacf11bSopenharmony_ci{
90beacf11bSopenharmony_ci  uint8_t   len;                /* Descriptor length */
91beacf11bSopenharmony_ci  uint8_t   type;               /* 0x21 = DFU FUNCTIONAL */
92beacf11bSopenharmony_ci  uint8_t   attributes;         /* Bit mask of supported features */
93beacf11bSopenharmony_ci  uint8_t   detach_timeout[2];  /* Maximum time in milliseconds between DFU_DETACH and USB reset */
94beacf11bSopenharmony_ci  uint8_t   transfer_size[2];   /* Maximum number of bytes in control writes */
95beacf11bSopenharmony_ci  uint8_t   dfu_version[2];     /* Version of DFU specification supported */
96beacf11bSopenharmony_ci};
97beacf11bSopenharmony_ci
98beacf11bSopenharmony_ci/* USB configuration descriptor */
99beacf11bSopenharmony_ci
100beacf11bSopenharmony_cistruct dfu_cfgdesc_s
101beacf11bSopenharmony_ci{
102beacf11bSopenharmony_ci  struct usb_interface_descriptor ifdesc; /* DFU interface descriptor */
103beacf11bSopenharmony_ci  struct dfu_funcdesc_s funcdesc;         /* DFU functional descriptor */
104beacf11bSopenharmony_ci};
105beacf11bSopenharmony_ci
106beacf11bSopenharmony_cistruct dfu_driver_s
107beacf11bSopenharmony_ci{
108beacf11bSopenharmony_ci  struct usbdevclass_driver_s drvr;
109beacf11bSopenharmony_ci  FAR struct usbdev_req_s *ctrlreq;  /* Pointer to preallocated control request */
110beacf11bSopenharmony_ci};
111beacf11bSopenharmony_ci
112beacf11bSopenharmony_ci/****************************************************************************
113beacf11bSopenharmony_ci * Private Function Prototypes
114beacf11bSopenharmony_ci ****************************************************************************/
115beacf11bSopenharmony_ci
116beacf11bSopenharmony_ci/* usbclass callbacks */
117beacf11bSopenharmony_ci
118beacf11bSopenharmony_cistatic int  usbclass_setup(FAR struct usbdevclass_driver_s *driver,
119beacf11bSopenharmony_ci                           FAR struct usbdev_s *dev,
120beacf11bSopenharmony_ci                           FAR const struct usb_device_request *ctrl,
121beacf11bSopenharmony_ci                           FAR uint8_t *dataout, size_t outlen);
122beacf11bSopenharmony_cistatic int  usbclass_bind(FAR struct usbdevclass_driver_s *driver,
123beacf11bSopenharmony_ci                          FAR struct usbdev_s *dev);
124beacf11bSopenharmony_cistatic int usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
125beacf11bSopenharmony_ci                           FAR struct usbdev_s *dev);
126beacf11bSopenharmony_cistatic void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
127beacf11bSopenharmony_ci                                FAR struct usbdev_s *dev);
128beacf11bSopenharmony_ci
129beacf11bSopenharmony_ci/****************************************************************************
130beacf11bSopenharmony_ci * Private Data
131beacf11bSopenharmony_ci ****************************************************************************/
132beacf11bSopenharmony_ci
133beacf11bSopenharmony_ci/* USB driver operations */
134beacf11bSopenharmony_ci
135beacf11bSopenharmony_ciconst static struct usbdevclass_driverops_s g_dfu_driverops =
136beacf11bSopenharmony_ci{
137beacf11bSopenharmony_ci  &usbclass_bind,
138beacf11bSopenharmony_ci  &usbclass_unbind,
139beacf11bSopenharmony_ci  &usbclass_setup,
140beacf11bSopenharmony_ci  &usbclass_disconnect,
141beacf11bSopenharmony_ci  NULL,
142beacf11bSopenharmony_ci  NULL
143beacf11bSopenharmony_ci};
144beacf11bSopenharmony_ci
145beacf11bSopenharmony_cistatic struct dfu_cfgdesc_s g_dfu_cfgdesc =
146beacf11bSopenharmony_ci{
147beacf11bSopenharmony_ci  {
148beacf11bSopenharmony_ci    .bLength            = sizeof(struct usb_interface_descriptor),
149beacf11bSopenharmony_ci    .bDescriptorType    = UDESC_INTERFACE,
150beacf11bSopenharmony_ci    .bInterfaceNumber   = 0,
151beacf11bSopenharmony_ci    .bAlternateSetting  = 0,
152beacf11bSopenharmony_ci    .bNumEndpoints      = 0,
153beacf11bSopenharmony_ci    .bInterfaceClass    = 0xFE,
154beacf11bSopenharmony_ci    .bInterfaceSubClass = 0x01,
155beacf11bSopenharmony_ci    .bInterfaceProtocol = 0x01, /* DFU runtime protocol */
156beacf11bSopenharmony_ci    .iInterface         = 0x01
157beacf11bSopenharmony_ci  },
158beacf11bSopenharmony_ci  {
159beacf11bSopenharmony_ci    .len            = sizeof(struct dfu_funcdesc_s),
160beacf11bSopenharmony_ci    .type           = 0x21,
161beacf11bSopenharmony_ci    .attributes     = 0x0F,
162beacf11bSopenharmony_ci    .detach_timeout = { LSBYTE(DFU_MAX_TIMEOUT), MSBYTE(DFU_MAX_TIMEOUT) },
163beacf11bSopenharmony_ci    .transfer_size  = { LSBYTE(DFU_MAX_TRANSFER), MSBYTE(DFU_MAX_TRANSFER) },
164beacf11bSopenharmony_ci    .dfu_version    = { LSBYTE(DFU_VERSION), MSBYTE(DFU_VERSION) }
165beacf11bSopenharmony_ci  }
166beacf11bSopenharmony_ci};
167beacf11bSopenharmony_ci
168beacf11bSopenharmony_civoid to_runtime_mode(void)
169beacf11bSopenharmony_ci{
170beacf11bSopenharmony_ci  g_dfu_cfgdesc.ifdesc.bInterfaceProtocol = 0x01; /* The runtime mode */
171beacf11bSopenharmony_ci}
172beacf11bSopenharmony_ci
173beacf11bSopenharmony_civoid to_dfu_mode(void)
174beacf11bSopenharmony_ci{
175beacf11bSopenharmony_ci  g_dfu_cfgdesc.ifdesc.bInterfaceProtocol = 0x02; /* The DFU mode */
176beacf11bSopenharmony_ci}
177beacf11bSopenharmony_ci
178beacf11bSopenharmony_ci/****************************************************************************
179beacf11bSopenharmony_ci * Private Functions
180beacf11bSopenharmony_ci ****************************************************************************/
181beacf11bSopenharmony_ci
182beacf11bSopenharmony_cistatic void usbclass_ep0incomplete(FAR struct usbdev_ep_s *ep,
183beacf11bSopenharmony_ci                                   FAR struct usbdev_req_s *req)
184beacf11bSopenharmony_ci{
185beacf11bSopenharmony_ci  (void)ep;
186beacf11bSopenharmony_ci  (void)req;
187beacf11bSopenharmony_ci}
188beacf11bSopenharmony_ci
189beacf11bSopenharmony_cistatic void usbclass_mkdevdesc(uint8_t *buf)
190beacf11bSopenharmony_ci{
191beacf11bSopenharmony_ci  usbdev_dfu_mkdevdesc(buf);
192beacf11bSopenharmony_ci}
193beacf11bSopenharmony_ci
194beacf11bSopenharmony_cistatic int16_t usbclass_mkcfgdesc(FAR uint8_t *buf,
195beacf11bSopenharmony_ci                                  FAR struct usbdev_devinfo_s *devinfo)
196beacf11bSopenharmony_ci{
197beacf11bSopenharmony_ci  int16_t total_len = 0;
198beacf11bSopenharmony_ci  int16_t len       = USB_CONFIG_DESC_SIZE;
199beacf11bSopenharmony_ci  int ret;
200beacf11bSopenharmony_ci
201beacf11bSopenharmony_ci  /* Modify according to the actual length. */
202beacf11bSopenharmony_ci
203beacf11bSopenharmony_ci  USETW(g_dfu_config_desc.wTotalLength, (USB_CONFIG_DESC_SIZE + sizeof(g_dfu_cfgdesc)));
204beacf11bSopenharmony_ci
205beacf11bSopenharmony_ci  /* Copy DFU device configure descriptor. */
206beacf11bSopenharmony_ci
207beacf11bSopenharmony_ci  ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_dfu_config_desc, (uint16_t)len);
208beacf11bSopenharmony_ci  if (ret != EOK)
209beacf11bSopenharmony_ci    {
210beacf11bSopenharmony_ci      usb_err("memcpy_s fail, ret:%d\n", ret);
211beacf11bSopenharmony_ci      return -1;
212beacf11bSopenharmony_ci    }
213beacf11bSopenharmony_ci  total_len += len;
214beacf11bSopenharmony_ci
215beacf11bSopenharmony_ci  /* Copy DFU device function descriptor. */
216beacf11bSopenharmony_ci
217beacf11bSopenharmony_ci  buf += USB_CONFIG_DESC_SIZE;
218beacf11bSopenharmony_ci  len  = sizeof(g_dfu_cfgdesc);
219beacf11bSopenharmony_ci  ret  = memcpy_s(buf, (size_t)(USB_COMP_EP0_BUFSIZ - total_len), &g_dfu_cfgdesc, (uint16_t)len);
220beacf11bSopenharmony_ci  if (ret != EOK)
221beacf11bSopenharmony_ci    {
222beacf11bSopenharmony_ci      usb_err("memcpy_s fail, ret:%d\n", ret);
223beacf11bSopenharmony_ci      return -1;
224beacf11bSopenharmony_ci    }
225beacf11bSopenharmony_ci  total_len += len;
226beacf11bSopenharmony_ci
227beacf11bSopenharmony_ci  return total_len;
228beacf11bSopenharmony_ci}
229beacf11bSopenharmony_ci
230beacf11bSopenharmony_cistatic int usbclass_mkstrdesc(uint8_t id, uint8_t *buf)
231beacf11bSopenharmony_ci{
232beacf11bSopenharmony_ci  return usbdev_dfu_mkstrdesc(id, buf);
233beacf11bSopenharmony_ci}
234beacf11bSopenharmony_ci
235beacf11bSopenharmony_cistatic int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
236beacf11bSopenharmony_ci                          FAR struct usbdev_s *dev,
237beacf11bSopenharmony_ci                          FAR const struct usb_device_request *ctrl,
238beacf11bSopenharmony_ci                          FAR uint8_t *dataout, size_t outlen)
239beacf11bSopenharmony_ci{
240beacf11bSopenharmony_ci  FAR struct dfu_driver_s *priv = (FAR struct dfu_driver_s *)driver;
241beacf11bSopenharmony_ci  FAR struct usbdev_req_s *ctrlreq = priv->ctrlreq;
242beacf11bSopenharmony_ci  uint16_t value;
243beacf11bSopenharmony_ci  uint16_t len;
244beacf11bSopenharmony_ci  int ret = -EOPNOTSUPP;
245beacf11bSopenharmony_ci
246beacf11bSopenharmony_ci  (void)dataout;
247beacf11bSopenharmony_ci  (void)outlen;
248beacf11bSopenharmony_ci
249beacf11bSopenharmony_ci  value = UGETW(ctrl->wValue);
250beacf11bSopenharmony_ci  len   = UGETW(ctrl->wLength);
251beacf11bSopenharmony_ci
252beacf11bSopenharmony_ci  if ((ctrl->bmRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD)
253beacf11bSopenharmony_ci    {
254beacf11bSopenharmony_ci      if (ctrl->bRequest == USB_REQ_SET_CONFIGURATION)
255beacf11bSopenharmony_ci        {
256beacf11bSopenharmony_ci          usbdev_dfu_set_config();
257beacf11bSopenharmony_ci          return 0; /* Composite driver will send the reply */
258beacf11bSopenharmony_ci        }
259beacf11bSopenharmony_ci      else if (ctrl->bRequest == USB_REQ_SET_INTERFACE)
260beacf11bSopenharmony_ci        {
261beacf11bSopenharmony_ci          /* Only one alternate setting (0) is supported */
262beacf11bSopenharmony_ci
263beacf11bSopenharmony_ci          if (value == 0)
264beacf11bSopenharmony_ci            {
265beacf11bSopenharmony_ci              ret = 0;
266beacf11bSopenharmony_ci            }
267beacf11bSopenharmony_ci        }
268beacf11bSopenharmony_ci      else if (ctrl->bRequest == USB_REQ_GET_INTERFACE)
269beacf11bSopenharmony_ci        {
270beacf11bSopenharmony_ci          *(FAR uint8_t *)ctrlreq->buf = 0;
271beacf11bSopenharmony_ci          ret = 1;
272beacf11bSopenharmony_ci        }
273beacf11bSopenharmony_ci    }
274beacf11bSopenharmony_ci  else if ((ctrl->bmRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS)
275beacf11bSopenharmony_ci    {
276beacf11bSopenharmony_ci      ret = usbdev_dfu_class_requests(dev, ctrl, ctrlreq);
277beacf11bSopenharmony_ci    }
278beacf11bSopenharmony_ci
279beacf11bSopenharmony_ci  /* Respond to the setup command if data was returned.  On an error return
280beacf11bSopenharmony_ci   * value (ret < 0), the USB driver will stall.
281beacf11bSopenharmony_ci   */
282beacf11bSopenharmony_ci
283beacf11bSopenharmony_ci  if (ret >= 0)
284beacf11bSopenharmony_ci    {
285beacf11bSopenharmony_ci      ctrlreq->len   = (len < ret) ? len : (uint32_t)ret;
286beacf11bSopenharmony_ci      ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
287beacf11bSopenharmony_ci      ret            = EP_SUBMIT(dev->ep0, ctrlreq);
288beacf11bSopenharmony_ci      if (ret < 0)
289beacf11bSopenharmony_ci        {
290beacf11bSopenharmony_ci          usb_err("req submit failed!\r\n");
291beacf11bSopenharmony_ci          ctrlreq->result = OK;
292beacf11bSopenharmony_ci        }
293beacf11bSopenharmony_ci    }
294beacf11bSopenharmony_ci
295beacf11bSopenharmony_ci  return ret;
296beacf11bSopenharmony_ci}
297beacf11bSopenharmony_ci
298beacf11bSopenharmony_cistatic int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
299beacf11bSopenharmony_ci                         FAR struct usbdev_s *dev)
300beacf11bSopenharmony_ci{
301beacf11bSopenharmony_ci  FAR struct dfu_driver_s *priv = (FAR struct dfu_driver_s *)driver;
302beacf11bSopenharmony_ci  struct composite_dev_s *cdev  = dev->ep0->priv;
303beacf11bSopenharmony_ci
304beacf11bSopenharmony_ci  priv->ctrlreq = cdev->ctrlreq;
305beacf11bSopenharmony_ci  if (priv->ctrlreq == NULL)
306beacf11bSopenharmony_ci    {
307beacf11bSopenharmony_ci      usb_err("Ctrlreq is NULL!\r\n");
308beacf11bSopenharmony_ci      return -ENOMEM;
309beacf11bSopenharmony_ci    }
310beacf11bSopenharmony_ci
311beacf11bSopenharmony_ci  priv->ctrlreq->callback = usbclass_ep0incomplete;
312beacf11bSopenharmony_ci
313beacf11bSopenharmony_ci  return OK;
314beacf11bSopenharmony_ci}
315beacf11bSopenharmony_ci
316beacf11bSopenharmony_cistatic int usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
317beacf11bSopenharmony_ci                           FAR struct usbdev_s *dev)
318beacf11bSopenharmony_ci{
319beacf11bSopenharmony_ci  FAR struct dfu_driver_s *priv = (FAR struct dfu_driver_s *)driver;
320beacf11bSopenharmony_ci
321beacf11bSopenharmony_ci  (void)dev;
322beacf11bSopenharmony_ci
323beacf11bSopenharmony_ci  if (usb_dfu_running())
324beacf11bSopenharmony_ci    {
325beacf11bSopenharmony_ci      PRINT_ERR("%s fail, dfu busy\n", __FUNCTION__);
326beacf11bSopenharmony_ci      return -1;
327beacf11bSopenharmony_ci    }
328beacf11bSopenharmony_ci
329beacf11bSopenharmony_ci  if (priv->ctrlreq != NULL)
330beacf11bSopenharmony_ci    {
331beacf11bSopenharmony_ci      priv->ctrlreq = NULL;
332beacf11bSopenharmony_ci    }
333beacf11bSopenharmony_ci  usbdev_dfu_init();
334beacf11bSopenharmony_ci
335beacf11bSopenharmony_ci  return 0;
336beacf11bSopenharmony_ci}
337beacf11bSopenharmony_ci
338beacf11bSopenharmony_cistatic void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
339beacf11bSopenharmony_ci                                FAR struct usbdev_s *dev)
340beacf11bSopenharmony_ci{
341beacf11bSopenharmony_ci  (void)driver;
342beacf11bSopenharmony_ci  (void)dev;
343beacf11bSopenharmony_ci
344beacf11bSopenharmony_ci  usbdev_dfu_transaction_cleanup();
345beacf11bSopenharmony_ci  dprintf("reset config\n");
346beacf11bSopenharmony_ci}
347beacf11bSopenharmony_ci
348beacf11bSopenharmony_ci/****************************************************************************
349beacf11bSopenharmony_ci * Name: usbclass_classobject
350beacf11bSopenharmony_ci *
351beacf11bSopenharmony_ci * Description:
352beacf11bSopenharmony_ci *   Allocate memory for the RNDIS driver class object
353beacf11bSopenharmony_ci *
354beacf11bSopenharmony_ci * Returned Value:
355beacf11bSopenharmony_ci *   0 on success, negative error code on failure.
356beacf11bSopenharmony_ci *
357beacf11bSopenharmony_ci ****************************************************************************/
358beacf11bSopenharmony_ci
359beacf11bSopenharmony_cistatic int usbclass_classobject(int minor,
360beacf11bSopenharmony_ci                                FAR struct usbdev_devinfo_s *devinfo,
361beacf11bSopenharmony_ci                                FAR struct usbdevclass_driver_s **classdev)
362beacf11bSopenharmony_ci{
363beacf11bSopenharmony_ci  FAR struct dfu_driver_s *alloc;
364beacf11bSopenharmony_ci
365beacf11bSopenharmony_ci  (void)minor;
366beacf11bSopenharmony_ci  (void)devinfo;
367beacf11bSopenharmony_ci
368beacf11bSopenharmony_ci  alloc = malloc(sizeof(struct dfu_driver_s));
369beacf11bSopenharmony_ci  if (alloc == NULL)
370beacf11bSopenharmony_ci    {
371beacf11bSopenharmony_ci      return -ENOMEM;
372beacf11bSopenharmony_ci    }
373beacf11bSopenharmony_ci
374beacf11bSopenharmony_ci  *classdev = &alloc->drvr;
375beacf11bSopenharmony_ci
376beacf11bSopenharmony_ci  alloc->drvr.speed = USB_SPEED_FULL;
377beacf11bSopenharmony_ci  alloc->drvr.ops   = &g_dfu_driverops;
378beacf11bSopenharmony_ci
379beacf11bSopenharmony_ci  usbdev_dfu_dev_init();
380beacf11bSopenharmony_ci
381beacf11bSopenharmony_ci  return OK;
382beacf11bSopenharmony_ci}
383beacf11bSopenharmony_ci
384beacf11bSopenharmony_ci/****************************************************************************
385beacf11bSopenharmony_ci * Name: usbclass_uninitialize
386beacf11bSopenharmony_ci *
387beacf11bSopenharmony_ci * Description:
388beacf11bSopenharmony_ci *   Free allocated memory
389beacf11bSopenharmony_ci *
390beacf11bSopenharmony_ci * Returned Value:
391beacf11bSopenharmony_ci *   0 on success, negative error code on failure.
392beacf11bSopenharmony_ci *
393beacf11bSopenharmony_ci ****************************************************************************/
394beacf11bSopenharmony_ci
395beacf11bSopenharmony_cistatic void usbclass_uninitialize(FAR struct usbdevclass_driver_s *classdev)
396beacf11bSopenharmony_ci{
397beacf11bSopenharmony_ci  usbdev_dfu_dev_deinit();
398beacf11bSopenharmony_ci  free(classdev);
399beacf11bSopenharmony_ci}
400beacf11bSopenharmony_ci
401beacf11bSopenharmony_ci/****************************************************************************
402beacf11bSopenharmony_ci * Public Functions
403beacf11bSopenharmony_ci ****************************************************************************/
404beacf11bSopenharmony_ci
405beacf11bSopenharmony_civoid usbdev_dfu_get_composite_devdesc(struct composite_devdesc_s *dev)
406beacf11bSopenharmony_ci{
407beacf11bSopenharmony_ci  (void)memset_s(dev, sizeof(struct composite_devdesc_s), 0, sizeof(struct composite_devdesc_s));
408beacf11bSopenharmony_ci
409beacf11bSopenharmony_ci  dev->mkdevdesc           = usbclass_mkdevdesc;
410beacf11bSopenharmony_ci  dev->mkconfdesc          = usbclass_mkcfgdesc;
411beacf11bSopenharmony_ci  dev->mkstrdesc           = usbclass_mkstrdesc;
412beacf11bSopenharmony_ci  dev->classobject         = usbclass_classobject;
413beacf11bSopenharmony_ci  dev->uninitialize        = usbclass_uninitialize;
414beacf11bSopenharmony_ci  dev->nconfigs            = 1;
415beacf11bSopenharmony_ci  dev->configid            = 0;
416beacf11bSopenharmony_ci  dev->cfgdescsize         = (int)sizeof(g_dfu_cfgdesc);
417beacf11bSopenharmony_ci  dev->devinfo.ninterfaces = 1;
418beacf11bSopenharmony_ci  dev->devinfo.nstrings    = 1;
419beacf11bSopenharmony_ci  dev->devinfo.nendpoints  = 0;
420beacf11bSopenharmony_ci}
421