blob: 63b0b5c956a75a7382a83a74bc2e11f8557a48eb [file] [log] [blame]
Sylvain Munautbc9f5c42020-09-14 10:22:29 +02001/*
2 * usb_desc_app.c
3 *
4 * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
5 * SPDX-License-Identifier: GPL-3.0-or-later
6 */
7
8#include <no2usb/usb_proto.h>
Sylvain Munautb9d93632021-05-31 14:03:44 +02009#include <no2usb/usb_cdc_proto.h>
Sylvain Munaut4ea7d272020-10-29 13:17:11 +010010#include <no2usb/usb_dfu_proto.h>
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020011#include <no2usb/usb.h>
12
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +010013#include "usb_desc_ids.h"
14
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020015#define NULL ((void*)0)
16#define num_elem(a) (sizeof(a) / sizeof(a[0]))
17
18
Sylvain Munautb9d93632021-05-31 14:03:44 +020019usb_cdc_union_desc_def(1);
20
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020021static const struct {
22 /* Configuration */
23 struct usb_conf_desc conf;
24
25 /* E1 */
26 struct {
Harald Welte30fc5602020-12-14 15:56:28 +010027 /* Two altsettings are required, as isochronous
28 * interfaces must have a setting where they don't
Sylvain Munaut96744362022-01-03 17:03:26 +010029 * transceive any data. We just remove the isochronous
30 * endpoints in the 'off' altsetting */
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020031 struct {
32 struct usb_intf_desc intf;
Harald Welte805f2cf2020-12-14 17:31:03 +010033 struct usb_ep_desc ep_interrupt;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020034 } __attribute__ ((packed)) off;
35 struct {
36 struct usb_intf_desc intf;
37 struct usb_ep_desc ep_data_in;
38 struct usb_ep_desc ep_data_out;
39 struct usb_ep_desc ep_fb;
Harald Welte805f2cf2020-12-14 17:31:03 +010040 struct usb_ep_desc ep_interrupt;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020041 } __attribute__ ((packed)) on;
Sylvain Munautdb0b8102022-09-01 18:43:41 +020042 } __attribute__ ((packed)) e1[NUM_E1_PORTS];
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020043
44 /* CDC */
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020045 struct {
46 struct usb_intf_desc intf_ctl;
Sylvain Munautb9d93632021-05-31 14:03:44 +020047 struct usb_cdc_hdr_desc cdc_hdr;
48 struct usb_cdc_acm_desc cdc_acm;
49 struct usb_cdc_union_desc__1 cdc_union;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020050 struct usb_ep_desc ep_ctl;
51 struct usb_intf_desc intf_data;
52 struct usb_ep_desc ep_data_out;
53 struct usb_ep_desc ep_data_in;
54 } __attribute__ ((packed)) cdc;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020055
Harald Weltecac342a2022-01-30 20:41:12 +010056 /* GPS-DO (control EP only) */
57 struct {
58 struct usb_intf_desc intf;
59 } __attribute__ ((packed)) gpsdo;
60
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020061 /* DFU Runtime */
62 struct {
63 struct usb_intf_desc intf;
Sylvain Munaut4ea7d272020-10-29 13:17:11 +010064 struct usb_dfu_func_desc func;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020065 } __attribute__ ((packed)) dfu;
66} __attribute__ ((packed)) _app_conf_desc = {
67 .conf = {
68 .bLength = sizeof(struct usb_conf_desc),
69 .bDescriptorType = USB_DT_CONF,
70 .wTotalLength = sizeof(_app_conf_desc),
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +010071 .bNumInterfaces = USB_INTF_NUM,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020072 .bConfigurationValue = 1,
73 .iConfiguration = 4,
74 .bmAttributes = 0x80,
75 .bMaxPower = 0x32, /* 100 mA */
76 },
Sylvain Munaut41c98b62022-01-05 21:11:35 +010077 .e1[0] = {
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020078 .off = {
79 .intf = {
80 .bLength = sizeof(struct usb_intf_desc),
81 .bDescriptorType = USB_DT_INTF,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +010082 .bInterfaceNumber = USB_INTF_E1(0),
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020083 .bAlternateSetting = 0,
Sylvain Munaut96744362022-01-03 17:03:26 +010084 .bNumEndpoints = 1,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020085 .bInterfaceClass = 0xff,
86 .bInterfaceSubClass = 0xe1,
87 .bInterfaceProtocol = 0x00,
88 .iInterface = 5,
89 },
Harald Welte805f2cf2020-12-14 17:31:03 +010090 .ep_interrupt = {
91 .bLength = sizeof(struct usb_ep_desc),
92 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +010093 .bEndpointAddress = USB_EP_E1_INT(0),
Harald Welte805f2cf2020-12-14 17:31:03 +010094 .bmAttributes = 0x03,
95 .wMaxPacketSize = 10,
Sylvain Munaut1d987092022-01-05 21:04:09 +010096 .bInterval = 4, /* every 4 ms */
Harald Welte805f2cf2020-12-14 17:31:03 +010097 },
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020098 },
99 .on = {
100 .intf = {
101 .bLength = sizeof(struct usb_intf_desc),
102 .bDescriptorType = USB_DT_INTF,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100103 .bInterfaceNumber = USB_INTF_E1(0),
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200104 .bAlternateSetting = 1,
Harald Welte805f2cf2020-12-14 17:31:03 +0100105 .bNumEndpoints = 4,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200106 .bInterfaceClass = 0xff,
107 .bInterfaceSubClass = 0xe1,
108 .bInterfaceProtocol = 0x00,
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100109 .iInterface = 6,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200110 },
111 .ep_data_in = {
112 .bLength = sizeof(struct usb_ep_desc),
113 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100114 .bEndpointAddress = USB_EP_E1_IN(0),
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200115 .bmAttributes = 0x05,
Sylvain Munaut1d987092022-01-05 21:04:09 +0100116 .wMaxPacketSize = 292,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200117 .bInterval = 1,
118 },
119 .ep_data_out = {
120 .bLength = sizeof(struct usb_ep_desc),
121 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100122 .bEndpointAddress = USB_EP_E1_OUT(0),
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200123 .bmAttributes = 0x05,
Sylvain Munaut1d987092022-01-05 21:04:09 +0100124 .wMaxPacketSize = 292,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200125 .bInterval = 1,
126 },
127 .ep_fb = {
128 .bLength = sizeof(struct usb_ep_desc),
129 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100130 .bEndpointAddress = USB_EP_E1_FB(0),
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200131 .bmAttributes = 0x11,
Sylvain Munaut1d987092022-01-05 21:04:09 +0100132 .wMaxPacketSize = 3,
133 .bInterval = 3, /* every 2^(3-1) = 4 ms */
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200134 },
Harald Welte805f2cf2020-12-14 17:31:03 +0100135 .ep_interrupt = {
136 .bLength = sizeof(struct usb_ep_desc),
137 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100138 .bEndpointAddress = USB_EP_E1_INT(0),
Harald Welte805f2cf2020-12-14 17:31:03 +0100139 .bmAttributes = 0x03,
140 .wMaxPacketSize = 10,
Sylvain Munaut1d987092022-01-05 21:04:09 +0100141 .bInterval = 4, /* every 4 ms */
Harald Welte805f2cf2020-12-14 17:31:03 +0100142 },
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200143 },
144 },
Sylvain Munautdb0b8102022-09-01 18:43:41 +0200145#if NUM_E1_PORTS >= 2
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100146 .e1[1] = {
147 .off = {
148 .intf = {
149 .bLength = sizeof(struct usb_intf_desc),
150 .bDescriptorType = USB_DT_INTF,
151 .bInterfaceNumber = USB_INTF_E1(1),
152 .bAlternateSetting = 0,
153 .bNumEndpoints = 1,
154 .bInterfaceClass = 0xff,
155 .bInterfaceSubClass = 0xe1,
156 .bInterfaceProtocol = 0x00,
157 .iInterface = 7,
158 },
159 .ep_interrupt = {
160 .bLength = sizeof(struct usb_ep_desc),
161 .bDescriptorType = USB_DT_EP,
162 .bEndpointAddress = USB_EP_E1_INT(1),
163 .bmAttributes = 0x03,
164 .wMaxPacketSize = 10,
165 .bInterval = 4, /* every 4 ms */
166 },
167 },
168 .on = {
169 .intf = {
170 .bLength = sizeof(struct usb_intf_desc),
171 .bDescriptorType = USB_DT_INTF,
172 .bInterfaceNumber = USB_INTF_E1(1),
173 .bAlternateSetting = 1,
174 .bNumEndpoints = 4,
175 .bInterfaceClass = 0xff,
176 .bInterfaceSubClass = 0xe1,
177 .bInterfaceProtocol = 0x00,
178 .iInterface = 8,
179 },
180 .ep_data_in = {
181 .bLength = sizeof(struct usb_ep_desc),
182 .bDescriptorType = USB_DT_EP,
183 .bEndpointAddress = USB_EP_E1_IN(1),
184 .bmAttributes = 0x05,
185 .wMaxPacketSize = 292,
186 .bInterval = 1,
187 },
188 .ep_data_out = {
189 .bLength = sizeof(struct usb_ep_desc),
190 .bDescriptorType = USB_DT_EP,
191 .bEndpointAddress = USB_EP_E1_OUT(1),
192 .bmAttributes = 0x05,
193 .wMaxPacketSize = 292,
194 .bInterval = 1,
195 },
196 .ep_fb = {
197 .bLength = sizeof(struct usb_ep_desc),
198 .bDescriptorType = USB_DT_EP,
199 .bEndpointAddress = USB_EP_E1_FB(1),
200 .bmAttributes = 0x11,
201 .wMaxPacketSize = 3,
202 .bInterval = 3, /* every 2^(3-1) = 4 ms */
203 },
204 .ep_interrupt = {
205 .bLength = sizeof(struct usb_ep_desc),
206 .bDescriptorType = USB_DT_EP,
207 .bEndpointAddress = USB_EP_E1_INT(1),
208 .bmAttributes = 0x03,
209 .wMaxPacketSize = 10,
210 .bInterval = 4, /* every 4 ms */
211 },
212 },
213 },
Sylvain Munautdb0b8102022-09-01 18:43:41 +0200214#endif
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200215 .cdc = {
216 .intf_ctl = {
217 .bLength = sizeof(struct usb_intf_desc),
218 .bDescriptorType = USB_DT_INTF,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100219 .bInterfaceNumber = USB_INTF_GPS_CDC_CTL,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200220 .bAlternateSetting = 0,
221 .bNumEndpoints = 1,
Sylvain Munautb9d93632021-05-31 14:03:44 +0200222 .bInterfaceClass = USB_CLS_CDC_CONTROL,
223 .bInterfaceSubClass = USB_CDC_SCLS_ACM,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200224 .bInterfaceProtocol = 0x00,
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100225 .iInterface = 9,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200226 },
Sylvain Munautb9d93632021-05-31 14:03:44 +0200227 .cdc_hdr = {
228 .bLength = sizeof(struct usb_cdc_hdr_desc),
229 .bDescriptorType = USB_CS_DT_INTF,
230 .bDescriptorsubtype = USB_CDC_DST_HEADER,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200231 .bcdCDC = 0x0110,
232 },
Sylvain Munautb9d93632021-05-31 14:03:44 +0200233 .cdc_acm = {
234 .bLength = sizeof(struct usb_cdc_acm_desc),
235 .bDescriptorType = USB_CS_DT_INTF,
236 .bDescriptorsubtype = USB_CDC_DST_ACM,
Sylvain Munaut70c10f02022-01-12 11:58:34 +0100237 /* Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, */
238 /* and the notification Serial_State */
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200239 .bmCapabilities = 0x02,
240 },
Sylvain Munautb9d93632021-05-31 14:03:44 +0200241 .cdc_union = {
242 .bLength = sizeof(struct usb_cdc_union_desc) + 1,
243 .bDescriptorType = USB_CS_DT_INTF,
244 .bDescriptorsubtype = USB_CDC_DST_UNION,
Sylvain Munaut70c10f02022-01-12 11:58:34 +0100245 .bMasterInterface = USB_INTF_GPS_CDC_CTL,
246 .bSlaveInterface = { USB_INTF_GPS_CDC_DATA },
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200247 },
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200248 .ep_ctl = {
249 .bLength = sizeof(struct usb_ep_desc),
250 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100251 .bEndpointAddress = USB_EP_GPS_CDC_CTL,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200252 .bmAttributes = 0x03,
Sylvain Munaut70c10f02022-01-12 11:58:34 +0100253 /* Longest notif is SERIAL_STATE with 2 data bytes */
254 .wMaxPacketSize = sizeof(struct usb_ctrl_req) + 2,
Sylvain Munautdc1d7412022-08-25 16:56:43 +0200255#ifdef GPS_PPS_ON_CD
256 .bInterval = 1,
257#else
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200258 .bInterval = 0x40,
Sylvain Munautdc1d7412022-08-25 16:56:43 +0200259#endif
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200260 },
261 .intf_data = {
262 .bLength = sizeof(struct usb_intf_desc),
263 .bDescriptorType = USB_DT_INTF,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100264 .bInterfaceNumber = USB_INTF_GPS_CDC_DATA,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200265 .bAlternateSetting = 0,
266 .bNumEndpoints = 2,
Sylvain Munautb9d93632021-05-31 14:03:44 +0200267 .bInterfaceClass = USB_CLS_CDC_DATA,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200268 .bInterfaceSubClass = 0x00,
269 .bInterfaceProtocol = 0x00,
Sylvain Munaut41c98b62022-01-05 21:11:35 +0100270 .iInterface = 10,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200271 },
272 .ep_data_out = {
273 .bLength = sizeof(struct usb_ep_desc),
274 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100275 .bEndpointAddress = USB_EP_GPS_CDC_OUT,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200276 .bmAttributes = 0x02,
277 .wMaxPacketSize = 64,
278 .bInterval = 0x00,
279 },
280 .ep_data_in = {
281 .bLength = sizeof(struct usb_ep_desc),
282 .bDescriptorType = USB_DT_EP,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100283 .bEndpointAddress = USB_EP_GPS_CDC_IN,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200284 .bmAttributes = 0x02,
285 .wMaxPacketSize = 64,
286 .bInterval = 0x00,
287 },
288 },
Harald Weltecac342a2022-01-30 20:41:12 +0100289 .gpsdo = {
290 .intf = {
291 .bLength = sizeof(struct usb_intf_desc),
292 .bDescriptorType = USB_DT_INTF,
293 .bInterfaceNumber = USB_INTF_GPSDO,
294 .bAlternateSetting = 0,
295 .bNumEndpoints = 0,
296 .bInterfaceClass = 0xff,
297 .bInterfaceSubClass = 0xe1,
298 .bInterfaceProtocol = 0xd0,
299 .iInterface = 11,
300 }
301 },
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200302 .dfu = {
303 .intf = {
304 .bLength = sizeof(struct usb_intf_desc),
305 .bDescriptorType = USB_DT_INTF,
Sylvain Munaut8a5a9d42022-01-03 18:44:33 +0100306 .bInterfaceNumber = USB_INTF_DFU,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200307 .bAlternateSetting = 0,
308 .bNumEndpoints = 0,
309 .bInterfaceClass = 0xfe,
310 .bInterfaceSubClass = 0x01,
311 .bInterfaceProtocol = 0x01,
Harald Weltecac342a2022-01-30 20:41:12 +0100312 .iInterface = 12,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200313 },
314 .func = {
Sylvain Munaut4ea7d272020-10-29 13:17:11 +0100315 .bLength = sizeof(struct usb_dfu_func_desc),
316 .bDescriptorType = USB_DFU_DT_FUNC,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200317 .bmAttributes = 0x0d,
Sylvain Munaut3c3ae792022-01-05 20:55:37 +0100318 .wDetachTimeOut = 0,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200319 .wTransferSize = 4096,
320 .bcdDFUVersion = 0x0101,
321 },
322 },
323};
324
325static const struct usb_conf_desc * const _conf_desc_array[] = {
326 &_app_conf_desc.conf,
327};
328
329static const struct usb_dev_desc _dev_desc = {
330 .bLength = sizeof(struct usb_dev_desc),
331 .bDescriptorType = USB_DT_DEV,
332 .bcdUSB = 0x0200,
333 .bDeviceClass = 0,
334 .bDeviceSubClass = 0,
335 .bDeviceProtocol = 0,
336 .bMaxPacketSize0 = 64,
337 .idVendor = 0x1d50,
338 .idProduct = 0x6145,
339 .bcdDevice = 0x0003, /* v0.3 */
340 .iManufacturer = 2,
341 .iProduct = 3,
342 .iSerialNumber = 1,
343 .bNumConfigurations = num_elem(_conf_desc_array),
344};
345
346#include "usb_str_app.gen.h"
347
348const struct usb_stack_descriptors app_stack_desc = {
349 .dev = &_dev_desc,
350 .conf = _conf_desc_array,
351 .n_conf = num_elem(_conf_desc_array),
352 .str = _str_desc_array,
353 .n_str = num_elem(_str_desc_array),
354};