1beacf11bSopenharmony_ci/****************************************************************************
2beacf11bSopenharmony_ci * drivers/usbdev/composite_desc.c
3beacf11bSopenharmony_ci *
4beacf11bSopenharmony_ci *   Copyright (C) 2011-2012, 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 "gadget/composite.h"
51beacf11bSopenharmony_ci
52beacf11bSopenharmony_ci#ifdef CONFIG_USBDEV_COMPOSITE
53beacf11bSopenharmony_ci
54beacf11bSopenharmony_ci#define OS_STRING_SIGN_LEN 18
55beacf11bSopenharmony_ci#define OS_STRING_ID       0xEE
56beacf11bSopenharmony_ci
57beacf11bSopenharmony_cistatic const char g_os_string[OS_STRING_SIGN_LEN] =
58beacf11bSopenharmony_ci{
59beacf11bSopenharmony_ci  OS_STRING_SIGN_LEN,
60beacf11bSopenharmony_ci  UDESC_STRING,
61beacf11bSopenharmony_ci  'L', 0, 'i', 0, 't', 0, 'e', 0,
62beacf11bSopenharmony_ci  'O', 0, 'S', 0, ' ', 0, 0, 0
63beacf11bSopenharmony_ci};
64beacf11bSopenharmony_ci
65beacf11bSopenharmony_ci/****************************************************************************
66beacf11bSopenharmony_ci * Public Functions
67beacf11bSopenharmony_ci ****************************************************************************/
68beacf11bSopenharmony_ci
69beacf11bSopenharmony_ci/****************************************************************************
70beacf11bSopenharmony_ci * Name: composite_mkstrdesc
71beacf11bSopenharmony_ci *
72beacf11bSopenharmony_ci * Description:
73beacf11bSopenharmony_ci *   Construct a string descriptor
74beacf11bSopenharmony_ci *
75beacf11bSopenharmony_ci ****************************************************************************/
76beacf11bSopenharmony_ci
77beacf11bSopenharmony_ciint composite_mkstrdesc(struct composite_dev_s *priv, uint8_t id, uint16_t index, uint8_t *buf)
78beacf11bSopenharmony_ci{
79beacf11bSopenharmony_ci  int len = -1;
80beacf11bSopenharmony_ci  int i;
81beacf11bSopenharmony_ci  int ret;
82beacf11bSopenharmony_ci
83beacf11bSopenharmony_ci  if (index == 0 && id == OS_STRING_ID)
84beacf11bSopenharmony_ci    {
85beacf11bSopenharmony_ci      ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, (void *)g_os_string, g_os_string[0]);
86beacf11bSopenharmony_ci      if (ret != EOK)
87beacf11bSopenharmony_ci        {
88beacf11bSopenharmony_ci          return -1;
89beacf11bSopenharmony_ci        }
90beacf11bSopenharmony_ci      return g_os_string[0];
91beacf11bSopenharmony_ci    }
92beacf11bSopenharmony_ci
93beacf11bSopenharmony_ci  for (i = 0; i < priv->ndevices; i++)
94beacf11bSopenharmony_ci    {
95beacf11bSopenharmony_ci      len = priv->device[i].compdesc.mkstrdesc(id, buf);
96beacf11bSopenharmony_ci    }
97beacf11bSopenharmony_ci
98beacf11bSopenharmony_ci  return len;
99beacf11bSopenharmony_ci}
100beacf11bSopenharmony_ci
101beacf11bSopenharmony_civoid composite_mkdevdesc(struct composite_dev_s *priv, uint8_t *buf)
102beacf11bSopenharmony_ci{
103beacf11bSopenharmony_ci  int i;
104beacf11bSopenharmony_ci
105beacf11bSopenharmony_ci  for (i = 0; i < priv->ndevices; i++)
106beacf11bSopenharmony_ci    {
107beacf11bSopenharmony_ci      priv->device[i].compdesc.mkdevdesc(buf);
108beacf11bSopenharmony_ci    }
109beacf11bSopenharmony_ci}
110beacf11bSopenharmony_ci
111beacf11bSopenharmony_ciint16_t composite_mkcfgdesc_sub(uint8_t *buf, int16_t len)
112beacf11bSopenharmony_ci{
113beacf11bSopenharmony_ci  uint8_t *buf_tmp;
114beacf11bSopenharmony_ci  struct usb_descriptor *desc;
115beacf11bSopenharmony_ci  int16_t new_config_len = 0;
116beacf11bSopenharmony_ci  int ret;
117beacf11bSopenharmony_ci  int i;
118beacf11bSopenharmony_ci
119beacf11bSopenharmony_ci  buf_tmp = (uint8_t *)malloc(len);
120beacf11bSopenharmony_ci  if (buf_tmp == NULL)
121beacf11bSopenharmony_ci    {
122beacf11bSopenharmony_ci      return -1;
123beacf11bSopenharmony_ci    }
124beacf11bSopenharmony_ci
125beacf11bSopenharmony_ci  ret = memcpy_s(buf_tmp, len, buf, USB_CONFIG_DESC_SIZE);
126beacf11bSopenharmony_ci  if (ret != EOK)
127beacf11bSopenharmony_ci    {
128beacf11bSopenharmony_ci      goto err;
129beacf11bSopenharmony_ci    }
130beacf11bSopenharmony_ci  len -= USB_CONFIG_DESC_SIZE;
131beacf11bSopenharmony_ci  new_config_len += USB_CONFIG_DESC_SIZE;
132beacf11bSopenharmony_ci
133beacf11bSopenharmony_ci  desc = (struct usb_descriptor *)(buf + USB_CONFIG_DESC_SIZE);
134beacf11bSopenharmony_ci  i = 0;
135beacf11bSopenharmony_ci  while (i < len)
136beacf11bSopenharmony_ci    {
137beacf11bSopenharmony_ci      i += desc->bLength;
138beacf11bSopenharmony_ci      if (desc->bDescriptorType == UDESC_CONFIG)
139beacf11bSopenharmony_ci        {
140beacf11bSopenharmony_ci          desc = (struct usb_descriptor *)((char *)desc + desc->bLength);
141beacf11bSopenharmony_ci          continue;
142beacf11bSopenharmony_ci        }
143beacf11bSopenharmony_ci      ret = memcpy_s(buf_tmp + new_config_len, (len + USB_CONFIG_DESC_SIZE - new_config_len),
144beacf11bSopenharmony_ci                     desc, desc->bLength);
145beacf11bSopenharmony_ci      if (ret != EOK)
146beacf11bSopenharmony_ci        {
147beacf11bSopenharmony_ci          goto err;
148beacf11bSopenharmony_ci        }
149beacf11bSopenharmony_ci      new_config_len += desc->bLength;
150beacf11bSopenharmony_ci      desc = (struct usb_descriptor *)((char *)desc + desc->bLength);
151beacf11bSopenharmony_ci    }
152beacf11bSopenharmony_ci
153beacf11bSopenharmony_ci  ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, buf_tmp, new_config_len);
154beacf11bSopenharmony_ci  if (ret != EOK)
155beacf11bSopenharmony_ci    {
156beacf11bSopenharmony_ci      goto err;
157beacf11bSopenharmony_ci    }
158beacf11bSopenharmony_ci  free(buf_tmp);
159beacf11bSopenharmony_ci
160beacf11bSopenharmony_ci  return new_config_len;
161beacf11bSopenharmony_ci
162beacf11bSopenharmony_cierr:
163beacf11bSopenharmony_ci  free(buf_tmp);
164beacf11bSopenharmony_ci  return -1;
165beacf11bSopenharmony_ci}
166beacf11bSopenharmony_ci
167beacf11bSopenharmony_ci/****************************************************************************
168beacf11bSopenharmony_ci * Name: composite_mkcfgdesc
169beacf11bSopenharmony_ci *
170beacf11bSopenharmony_ci * Description:
171beacf11bSopenharmony_ci *   Construct the configuration descriptor
172beacf11bSopenharmony_ci *
173beacf11bSopenharmony_ci ****************************************************************************/
174beacf11bSopenharmony_ci
175beacf11bSopenharmony_ciint16_t composite_mkcfgdesc(struct composite_dev_s *priv, uint8_t *buf)
176beacf11bSopenharmony_ci{
177beacf11bSopenharmony_ci  struct usb_config_descriptor *config_desc;
178beacf11bSopenharmony_ci  uint8_t *buf_tmp = buf;
179beacf11bSopenharmony_ci  int16_t len;
180beacf11bSopenharmony_ci  int16_t total = 0;
181beacf11bSopenharmony_ci  int16_t config_len;
182beacf11bSopenharmony_ci  int i;
183beacf11bSopenharmony_ci
184beacf11bSopenharmony_ci  /* Copy all contained interface descriptors into the buffer too */
185beacf11bSopenharmony_ci
186beacf11bSopenharmony_ci  for (i = 0; i < priv->ndevices; i++)
187beacf11bSopenharmony_ci    {
188beacf11bSopenharmony_ci      len = priv->device[i].compdesc.mkconfdesc(buf_tmp, &priv->device[i].compdesc.devinfo);
189beacf11bSopenharmony_ci      if (len <= 0)
190beacf11bSopenharmony_ci        {
191beacf11bSopenharmony_ci          return -1;
192beacf11bSopenharmony_ci        }
193beacf11bSopenharmony_ci      total   += len;
194beacf11bSopenharmony_ci      buf_tmp += len;
195beacf11bSopenharmony_ci    }
196beacf11bSopenharmony_ci
197beacf11bSopenharmony_ci  if (priv->ndevices > 1)
198beacf11bSopenharmony_ci    {
199beacf11bSopenharmony_ci      config_len = total;
200beacf11bSopenharmony_ci      total      = composite_mkcfgdesc_sub(buf, config_len);
201beacf11bSopenharmony_ci      if (total < 0)
202beacf11bSopenharmony_ci        {
203beacf11bSopenharmony_ci          return -1;
204beacf11bSopenharmony_ci        }
205beacf11bSopenharmony_ci
206beacf11bSopenharmony_ci      config_len  = total;
207beacf11bSopenharmony_ci      config_desc = (struct usb_config_descriptor *)buf;
208beacf11bSopenharmony_ci      USETW(config_desc->wTotalLength, config_len);
209beacf11bSopenharmony_ci      config_desc->bNumInterface = priv->ninterfaces;
210beacf11bSopenharmony_ci    }
211beacf11bSopenharmony_ci
212beacf11bSopenharmony_ci  return total;
213beacf11bSopenharmony_ci}
214beacf11bSopenharmony_ci
215beacf11bSopenharmony_ci#endif /* CONFIG_USBDEV_COMPOSITE */
216