1 /****************************************************************************
2 * drivers/usbdev/composite_desc.c
3 *
4 * Copyright (C) 2011-2012, 2017 Gregory Nutt. All rights reserved.
5 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
6 * Author: Gregory Nutt <gnutt@nuttx.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name NuttX nor the names of its contributors may be
19 * used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ****************************************************************************/
36 /****************************************************************************
37 * Notice of Export Control Law
38 * ===============================================
39 * Huawei LiteOS may be subject to applicable export control laws and regulations,
40 * which might include those applicable to Huawei LiteOS of U.S. and the country in
41 * which you are located.
42 * Import, export and usage of Huawei LiteOS in any manner by you shall be in
43 * compliance with such applicable export control laws and regulations.
44 ****************************************************************************/
45
46 /****************************************************************************
47 * Included Files
48 ****************************************************************************/
49
50 #include "gadget/composite.h"
51
52 #ifdef CONFIG_USBDEV_COMPOSITE
53
54 #define OS_STRING_SIGN_LEN 18
55 #define OS_STRING_ID 0xEE
56
57 static const char g_os_string[OS_STRING_SIGN_LEN] =
58 {
59 OS_STRING_SIGN_LEN,
60 UDESC_STRING,
61 'L', 0, 'i', 0, 't', 0, 'e', 0,
62 'O', 0, 'S', 0, ' ', 0, 0, 0
63 };
64
65 /****************************************************************************
66 * Public Functions
67 ****************************************************************************/
68
69 /****************************************************************************
70 * Name: composite_mkstrdesc
71 *
72 * Description:
73 * Construct a string descriptor
74 *
75 ****************************************************************************/
76
composite_mkstrdesc(struct composite_dev_s * priv,uint8_t id,uint16_t index,uint8_t * buf)77 int composite_mkstrdesc(struct composite_dev_s *priv, uint8_t id, uint16_t index, uint8_t *buf)
78 {
79 int len = -1;
80 int i;
81 int ret;
82
83 if (index == 0 && id == OS_STRING_ID)
84 {
85 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, (void *)g_os_string, g_os_string[0]);
86 if (ret != EOK)
87 {
88 return -1;
89 }
90 return g_os_string[0];
91 }
92
93 for (i = 0; i < priv->ndevices; i++)
94 {
95 len = priv->device[i].compdesc.mkstrdesc(id, buf);
96 }
97
98 return len;
99 }
100
composite_mkdevdesc(struct composite_dev_s * priv,uint8_t * buf)101 void composite_mkdevdesc(struct composite_dev_s *priv, uint8_t *buf)
102 {
103 int i;
104
105 for (i = 0; i < priv->ndevices; i++)
106 {
107 priv->device[i].compdesc.mkdevdesc(buf);
108 }
109 }
110
composite_mkcfgdesc_sub(uint8_t * buf,int16_t len)111 int16_t composite_mkcfgdesc_sub(uint8_t *buf, int16_t len)
112 {
113 uint8_t *buf_tmp;
114 struct usb_descriptor *desc;
115 int16_t new_config_len = 0;
116 int ret;
117 int i;
118
119 buf_tmp = (uint8_t *)malloc(len);
120 if (buf_tmp == NULL)
121 {
122 return -1;
123 }
124
125 ret = memcpy_s(buf_tmp, len, buf, USB_CONFIG_DESC_SIZE);
126 if (ret != EOK)
127 {
128 goto err;
129 }
130 len -= USB_CONFIG_DESC_SIZE;
131 new_config_len += USB_CONFIG_DESC_SIZE;
132
133 desc = (struct usb_descriptor *)(buf + USB_CONFIG_DESC_SIZE);
134 i = 0;
135 while (i < len)
136 {
137 i += desc->bLength;
138 if (desc->bDescriptorType == UDESC_CONFIG)
139 {
140 desc = (struct usb_descriptor *)((char *)desc + desc->bLength);
141 continue;
142 }
143 ret = memcpy_s(buf_tmp + new_config_len, (len + USB_CONFIG_DESC_SIZE - new_config_len),
144 desc, desc->bLength);
145 if (ret != EOK)
146 {
147 goto err;
148 }
149 new_config_len += desc->bLength;
150 desc = (struct usb_descriptor *)((char *)desc + desc->bLength);
151 }
152
153 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, buf_tmp, new_config_len);
154 if (ret != EOK)
155 {
156 goto err;
157 }
158 free(buf_tmp);
159
160 return new_config_len;
161
162 err:
163 free(buf_tmp);
164 return -1;
165 }
166
167 /****************************************************************************
168 * Name: composite_mkcfgdesc
169 *
170 * Description:
171 * Construct the configuration descriptor
172 *
173 ****************************************************************************/
174
composite_mkcfgdesc(struct composite_dev_s * priv,uint8_t * buf)175 int16_t composite_mkcfgdesc(struct composite_dev_s *priv, uint8_t *buf)
176 {
177 struct usb_config_descriptor *config_desc;
178 uint8_t *buf_tmp = buf;
179 int16_t len;
180 int16_t total = 0;
181 int16_t config_len;
182 int i;
183
184 /* Copy all contained interface descriptors into the buffer too */
185
186 for (i = 0; i < priv->ndevices; i++)
187 {
188 len = priv->device[i].compdesc.mkconfdesc(buf_tmp, &priv->device[i].compdesc.devinfo);
189 if (len <= 0)
190 {
191 return -1;
192 }
193 total += len;
194 buf_tmp += len;
195 }
196
197 if (priv->ndevices > 1)
198 {
199 config_len = total;
200 total = composite_mkcfgdesc_sub(buf, config_len);
201 if (total < 0)
202 {
203 return -1;
204 }
205
206 config_len = total;
207 config_desc = (struct usb_config_descriptor *)buf;
208 USETW(config_desc->wTotalLength, config_len);
209 config_desc->bNumInterface = priv->ninterfaces;
210 }
211
212 return total;
213 }
214
215 #endif /* CONFIG_USBDEV_COMPOSITE */
216