1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3 * Description: LiteOS USB Driver Composite Devices
4 * Author: huangjieliang
5 * Create: 2017-04-21
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28 /* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36
37 #include "gadget/composite.h"
38 #include "gadget/cdcacm.h"
39 #include "gadget/rndis.h"
40
41 #ifdef __cplusplus
42 #if __cplusplus
43 extern "C" {
44 #endif /* __cplusplus */
45 #endif /* __cplusplus */
46
47 #define FMULTI_DEBUG
48 #ifdef FMULTI_DEBUG
49 #define FMSLOG(x...) dprintf(x)
50 #else
51 #define FMSLOG(x...) do {} while(0)
52 #endif
53
54 #define USB_ETHER_FIRST_INTERFACE_NUM 0
55 #define USB_SERIAL_FIRST_INTERFACE_NUM 2
56
57 int usbdev_multi_initialize(struct module *mod, int n, void *arg);
58
59 /* device driver structure definition */
60
61 static driver_t g_fmulti_driver_t =
62 {
63 .name = "fmulti",
64 .methods = NULL,
65 .size = 0
66 };
67
68 /* private device class information */
69
70 static devclass_t g_fmulti_devclass;
71 DRIVER_MODULE(fmulti, simple, g_fmulti_driver_t, g_fmulti_devclass, usbdev_multi_initialize, 0);
72
73 #define MULTI_VENDOR_ID 0x1d6b
74 #define MULTI_PRODUCT_ID 0x0104
75
76 /* This struct is aimed at enumerating index for composite device strings. */
77
78 enum
79 {
80 /* Rndis Device */
81
82 MULTI_RNDIS_CTRL_IDX = 6,
83 MULTI_RNDIS_DATA_IDX,
84 MULTI_RNDIS_IAD_IDX,
85
86 /* ACM Device */
87
88 MULTI_ACM_CTRL_IDX = 0xa,
89 MULTI_ACM_DATA_IDX,
90 MULTI_ACM_IAD_IDX
91 };
92
93 /* Define and initialize multi device descriptor. */
94
95 static const struct usb_device_descriptor g_fmulti_device_desc =
96 {
97 .bLength = sizeof(struct usb_device_descriptor),
98 .bDescriptorType = UDESC_DEVICE,
99 HSETW(.bcdUSB, UD_BCD_USB), /* USB version */
100 .bDeviceClass = UDCLASS_MISC,
101 .bDeviceSubClass = 2,
102 .bDeviceProtocol = 1,
103 .bMaxPacketSize = UD_USB_MPS,
104 HSETW(.idVendor, MULTI_VENDOR_ID), /* vendor */
105 HSETW(.idProduct, MULTI_PRODUCT_ID), /* product */
106 HSETW(.bcdDevice, 0x0318), /* device version */
107 .iManufacturer = 1,
108 .iProduct = 2,
109 .iSerialNumber = 0,
110 .bNumConfigurations = 1,
111 };
112
113 #define MULTI_STRING_ID_LEN 4
114 static const char g_multi_string_id[MULTI_STRING_ID_LEN] =
115 {
116 MULTI_STRING_ID_LEN,
117 UDESC_STRING,
118 0x09,
119 0x04,
120 };
121
122 #define MULTI_VERSION_STRING_LEN 62
123 static const char g_multi_version_string[MULTI_VERSION_STRING_LEN] =
124 {
125 MULTI_VERSION_STRING_LEN, UDESC_STRING,
126 'M', 0, 'u', 0, 'l', 0, 't', 0, 'i', 0, 'f', 0, 'u', 0, 'n', 0, 'c', 0, 't', 0,
127 'i', 0, 'o', 0, 'n', 0, ' ', 0, 'C', 0, 'o', 0, 'm', 0, 'p', 0, 'o', 0, 's', 0,
128 'i', 0, 't', 0, 'e', 0, ' ', 0, 'G', 0, 'a', 0, 'd', 0, 'g', 0, 'e', 0, 't', 0
129 };
130
131 #define MULTI_STRING_4_LEN 38
132 static const char g_dt_string_4[MULTI_STRING_4_LEN] =
133 {
134 MULTI_STRING_4_LEN,
135 UDESC_STRING,
136 0x47, 0, 0x61, 0, 0x64, 0, 0x67, 0, 0x65, 0, 0x74, 0, 0x20, 0,
137 0x53, 0, 0x65, 0, 0x72, 0, 0x69, 0, 0x61, 0, 0x6c, 0, 0x20, 0,
138 0x76, 0, 0x32, 0, 0x2e, 0, 0x34, 0
139 };
140
141 #define DT_STRING_6_LEN 26
142 static const char g_dt_string_6[DT_STRING_6_LEN] =
143 {
144 DT_STRING_6_LEN,
145 UDESC_STRING,
146 0x43, 0, 0x44, 0, 0x43, 0, 0x20, 0, 0x41, 0,
147 0x43, 0, 0x4d, 0, 0x20, 0, 0x44, 0, 0x61, 0, 0x74, 0, 0x61, 0
148 };
149
150 #define DT_STRING_7_LEN 22
151 static const char g_dt_string_7[DT_STRING_7_LEN] =
152 {
153 DT_STRING_7_LEN,
154 UDESC_STRING,
155 0x43, 0, 0x44, 0, 0x43, 0, 0x20, 0, 0x53, 0, 0x65, 0,
156 0x72, 0, 0x69, 0, 0x61, 0, 0x6c, 0
157 };
158
159 #define MULTI_RNDIS_STRING_LEN 12
160 static const char g_multi_rndis_string[MULTI_RNDIS_STRING_LEN] =
161 {
162 MULTI_RNDIS_STRING_LEN,
163 UDESC_STRING,
164 'R',0,'N',0,'D',0,'I',0,'S',0
165 };
166
167 #define MULTI_SERIAL_STRING_LEN 22
168 static const char g_multi_serial_string[MULTI_SERIAL_STRING_LEN] =
169 {
170 MULTI_SERIAL_STRING_LEN,
171 UDESC_STRING,
172 'C',0,'D',0,'C',0,' ',0,'S',0,'e',0,'i',0,'a',0,'l',0
173 };
174
175 #define FMULTI_DSTR_IDX 8
176 struct usbd_string g_fmulti_device_strings[FMULTI_DSTR_IDX] =
177 {
178 { 0, g_multi_string_id },
179 { 2, g_multi_version_string },
180 { 4, g_dt_string_4 },
181 { 6, g_dt_string_6 },
182 { 7, g_dt_string_7 },
183 { MULTI_RNDIS_IAD_IDX, g_multi_rndis_string },
184 { MULTI_ACM_IAD_IDX, g_multi_serial_string },
185 USBD_DEVICE_STRINGS_END
186 };
187
multi_mkdevdesc(uint8_t * buf)188 void multi_mkdevdesc(uint8_t *buf)
189 {
190 errno_t ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_fmulti_device_desc, sizeof(g_fmulti_device_desc));
191 if (ret != EOK)
192 {
193 usb_err("memcpy_s fail!, ret:%d\n", ret);
194 return;
195 }
196 }
197
multi_mkstrdesc(uint8_t id,uint8_t * buf)198 int multi_mkstrdesc(uint8_t id, uint8_t *buf)
199 {
200 errno_t ret;
201 const char *str;
202 int i;
203
204 for (i = 0; g_fmulti_device_strings[i].s != NULL; i++)
205 {
206 str = g_fmulti_device_strings[i].s;
207 if (g_fmulti_device_strings[i].id == id)
208 {
209 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, str, str[0]);
210 if (ret != EOK)
211 {
212 usb_err("memcpy_s failed, ret = %d\n", ret);
213 return -1;
214 }
215 return str[0];
216 }
217 }
218
219 usb_err("Can not find the id = %u of string\n", id);
220 return -1;
221 }
222
multi_get_composite_devdesc(struct composite_devdesc_s * dev)223 void multi_get_composite_devdesc(struct composite_devdesc_s *dev)
224 {
225 dev->mkdevdesc = multi_mkdevdesc;
226 dev->mkstrdesc = multi_mkstrdesc;
227 }
228
usbdev_multi_initialize(struct module * mod,int n,void * arg)229 int usbdev_multi_initialize (struct module *mod, int n, void *arg)
230 {
231 struct composite_softc *com_s = (struct composite_softc *)arg;
232 struct composite_devdesc_s dev[USB_COMPOSITE_DEV_NUM];
233 int ret;
234
235 (void)mod;
236 (void)n;
237 if (com_s == NULL)
238 {
239 PRINTK("com_s is NULL!\n");
240 return -1;
241 }
242
243 usbdev_rndis_initialize_sub(&dev[0], USB_ETHER_FIRST_INTERFACE_NUM, DEV_ETHERNET);
244 multi_get_composite_devdesc(&dev[0]);
245 usbdev_cdcacm_initialize_sub(&dev[1], USB_SERIAL_FIRST_INTERFACE_NUM, DEV_SERIAL);
246 multi_get_composite_devdesc(&dev[1]);
247
248 ret = composite_initialize(com_s, USB_COMPOSITE_DEV_NUM, dev);
249 if (ret < 0)
250 {
251 PRINTK(" ** multi device initialized failed! **\n");
252 return -1;
253 }
254
255 PRINTK(" ** multi device initialized successfully! **\n");
256 return 0;
257 }
258
259 #ifdef __cplusplus
260 #if __cplusplus
261 }
262 #endif /* __cplusplus */
263 #endif /* __cplusplus */