Deleted Added
full compact
usb_template_audio.c (246122) usb_template_audio.c (246123)
1/* $FreeBSD: head/sys/dev/usb/template/usb_template_audio.c 246122 2013-01-30 15:26:04Z hselasky $ */
1/* $FreeBSD: head/sys/dev/usb/template/usb_template_audio.c 246123 2013-01-30 15:46:26Z hselasky $ */
2/*-
3 * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * This file contains the USB template for an USB Audio Device.
29 */
30
31#ifdef USB_GLOBAL_INCLUDE_FILE
32#include USB_GLOBAL_INCLUDE_FILE
33#else
34#include <sys/stdint.h>
35#include <sys/stddef.h>
36#include <sys/param.h>
37#include <sys/queue.h>
38#include <sys/types.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/bus.h>
42#include <sys/module.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/condvar.h>
46#include <sys/sysctl.h>
47#include <sys/sx.h>
48#include <sys/unistd.h>
49#include <sys/callout.h>
50#include <sys/malloc.h>
51#include <sys/priv.h>
52
53#include <dev/usb/usb.h>
54#include <dev/usb/usbdi.h>
2/*-
3 * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*
28 * This file contains the USB template for an USB Audio Device.
29 */
30
31#ifdef USB_GLOBAL_INCLUDE_FILE
32#include USB_GLOBAL_INCLUDE_FILE
33#else
34#include <sys/stdint.h>
35#include <sys/stddef.h>
36#include <sys/param.h>
37#include <sys/queue.h>
38#include <sys/types.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/bus.h>
42#include <sys/module.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/condvar.h>
46#include <sys/sysctl.h>
47#include <sys/sx.h>
48#include <sys/unistd.h>
49#include <sys/callout.h>
50#include <sys/malloc.h>
51#include <sys/priv.h>
52
53#include <dev/usb/usb.h>
54#include <dev/usb/usbdi.h>
55#include <dev/usb/usb_core.h>
55#include <dev/usb/usb_cdc.h>
56
57#include <dev/usb/template/usb_template.h>
58#endif /* USB_GLOBAL_INCLUDE_FILE */
59
60enum {
61 INDEX_AUDIO_LANG,
62 INDEX_AUDIO_MIXER,
63 INDEX_AUDIO_RECORD,
64 INDEX_AUDIO_PLAYBACK,
65 INDEX_AUDIO_PRODUCT,
66 INDEX_AUDIO_MAX,
67};
68
56#include <dev/usb/usb_cdc.h>
57
58#include <dev/usb/template/usb_template.h>
59#endif /* USB_GLOBAL_INCLUDE_FILE */
60
61enum {
62 INDEX_AUDIO_LANG,
63 INDEX_AUDIO_MIXER,
64 INDEX_AUDIO_RECORD,
65 INDEX_AUDIO_PLAYBACK,
66 INDEX_AUDIO_PRODUCT,
67 INDEX_AUDIO_MAX,
68};
69
69#define STRING_LANG \
70 0x09, 0x04, /* American English */
71
72#define STRING_AUDIO_PRODUCT \
73 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, \
74 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
75 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
76
77#define STRING_AUDIO_MIXER \
78 'M', 0, 'i', 0, 'x', 0, 'e', 0, 'r', 0, ' ', 0, \
79 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
80
81#define STRING_AUDIO_RECORD \
82 'R', 0, 'e', 0, 'c', 0, 'o', 0, 'r', 0, 'd', 0, ' ', 0, \
83 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
84
85#define STRING_AUDIO_PLAYBACK \
86 'P', 0, 'l', 0, 'a', 0, 'y', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, \
87 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
88
89
90/* make the real string descriptors */
91
70#define STRING_AUDIO_PRODUCT \
71 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, \
72 'T', 0, 'e', 0, 's', 0, 't', 0, ' ', 0, \
73 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0,
74
75#define STRING_AUDIO_MIXER \
76 'M', 0, 'i', 0, 'x', 0, 'e', 0, 'r', 0, ' ', 0, \
77 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
78
79#define STRING_AUDIO_RECORD \
80 'R', 0, 'e', 0, 'c', 0, 'o', 0, 'r', 0, 'd', 0, ' ', 0, \
81 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
82
83#define STRING_AUDIO_PLAYBACK \
84 'P', 0, 'l', 0, 'a', 0, 'y', 0, 'b', 0, 'a', 0, 'c', 0, 'k', 0, ' ', 0, \
85 'i', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0,
86
87
88/* make the real string descriptors */
89
92USB_MAKE_STRING_DESC(STRING_LANG, string_lang);
93USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer);
94USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record);
95USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback);
96USB_MAKE_STRING_DESC(STRING_AUDIO_PRODUCT, string_audio_product);
97
98/* prototypes */
99
100/*
101 * Audio Mixer description structures
102 *
103 * Some of the audio descriptors were dumped
104 * from a Creative Labs USB audio device.
105 */
106
107static const uint8_t audio_raw_desc_0[] = {
108 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02,
109 0x01, 0x02
110};
111
112static const uint8_t audio_raw_desc_1[] = {
113 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
114 0x03, 0x00, 0x00, 0x00
115};
116
117static const uint8_t audio_raw_desc_2[] = {
118 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02,
119 0x03, 0x00, 0x00, 0x00
120};
121
122static const uint8_t audio_raw_desc_3[] = {
123 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02,
124 0x03, 0x00, 0x00, 0x00
125};
126
127static const uint8_t audio_raw_desc_4[] = {
128 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02,
129 0x03, 0x00, 0x00, 0x00
130};
131
132static const uint8_t audio_raw_desc_5[] = {
133 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01,
134 0x00
135};
136
137static const uint8_t audio_raw_desc_6[] = {
138 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09,
139 0x00
140};
141
142static const uint8_t audio_raw_desc_7[] = {
143 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08,
144 0x00
145};
146
147static const uint8_t audio_raw_desc_8[] = {
148 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c,
149 0x00
150};
151
152static const uint8_t audio_raw_desc_9[] = {
153 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02,
154 0x02, 0x00
155};
156
157static const uint8_t audio_raw_desc_10[] = {
158 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00,
159 0x00, 0x00
160};
161
162static const uint8_t audio_raw_desc_11[] = {
163 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02,
164 0x02, 0x00
165};
166
167static const uint8_t audio_raw_desc_12[] = {
168 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00,
169 0x00, 0x00
170};
171
172static const uint8_t audio_raw_desc_13[] = {
173 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00,
174 0x00, 0x00
175};
176
177static const uint8_t audio_raw_desc_14[] = {
178 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02,
179 0x02, 0x00
180};
181
182static const uint8_t audio_raw_desc_15[] = {
183 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e,
184 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
185};
186
187static const void *audio_raw_iface_0_desc[] = {
188 audio_raw_desc_0,
189 audio_raw_desc_1,
190 audio_raw_desc_2,
191 audio_raw_desc_3,
192 audio_raw_desc_4,
193 audio_raw_desc_5,
194 audio_raw_desc_6,
195 audio_raw_desc_7,
196 audio_raw_desc_8,
197 audio_raw_desc_9,
198 audio_raw_desc_10,
199 audio_raw_desc_11,
200 audio_raw_desc_12,
201 audio_raw_desc_13,
202 audio_raw_desc_14,
203 audio_raw_desc_15,
204 NULL,
205};
206
207static const struct usb_temp_interface_desc audio_iface_0 = {
208 .ppEndpoints = NULL, /* no endpoints */
209 .ppRawDesc = audio_raw_iface_0_desc,
210 .bInterfaceClass = 1,
211 .bInterfaceSubClass = 1,
212 .bInterfaceProtocol = 0,
213 .iInterface = INDEX_AUDIO_MIXER,
214};
215
216static const uint8_t audio_raw_desc_20[] = {
217 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00
218
219};
220
221static const uint8_t audio_raw_desc_21[] = {
222 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01,
223 /* 48kHz */
224 0x80, 0xbb, 0x00
225};
226
227static const uint8_t audio_raw_desc_22[] = {
228 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00
229};
230
231static const void *audio_raw_iface_1_desc[] = {
232 audio_raw_desc_20,
233 audio_raw_desc_21,
234 NULL,
235};
236
237static const void *audio_raw_ep_1_desc[] = {
238 audio_raw_desc_22,
239 NULL,
240};
241
242static const struct usb_temp_packet_size audio_isoc_mps = {
243 .mps[USB_SPEED_FULL] = 0xC8,
244 .mps[USB_SPEED_HIGH] = 0xC8,
245};
246
247static const struct usb_temp_interval audio_isoc_interval = {
248 .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */
249 .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */
250};
251
252static const struct usb_temp_endpoint_desc audio_isoc_out_ep = {
253 .ppRawDesc = audio_raw_ep_1_desc,
254 .pPacketSize = &audio_isoc_mps,
255 .pIntervals = &audio_isoc_interval,
256 .bEndpointAddress = UE_DIR_OUT,
257 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT,
258};
259
260static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = {
261 &audio_isoc_out_ep,
262 NULL,
263};
264
265static const struct usb_temp_interface_desc audio_iface_1_alt_0 = {
266 .ppEndpoints = NULL, /* no endpoints */
267 .ppRawDesc = NULL, /* no raw descriptors */
268 .bInterfaceClass = 1,
269 .bInterfaceSubClass = 2,
270 .bInterfaceProtocol = 0,
271 .iInterface = INDEX_AUDIO_PLAYBACK,
272};
273
274static const struct usb_temp_interface_desc audio_iface_1_alt_1 = {
275 .ppEndpoints = audio_iface_1_ep,
276 .ppRawDesc = audio_raw_iface_1_desc,
277 .bInterfaceClass = 1,
278 .bInterfaceSubClass = 2,
279 .bInterfaceProtocol = 0,
280 .iInterface = INDEX_AUDIO_PLAYBACK,
281 .isAltInterface = 1, /* this is an alternate setting */
282};
283
284static const uint8_t audio_raw_desc_30[] = {
285 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00
286
287};
288
289static const uint8_t audio_raw_desc_31[] = {
290 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01,
291 /* 48kHz */
292 0x80, 0xbb, 0x00
293};
294
295static const uint8_t audio_raw_desc_32[] = {
296 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00
297};
298
299static const void *audio_raw_iface_2_desc[] = {
300 audio_raw_desc_30,
301 audio_raw_desc_31,
302 NULL,
303};
304
305static const void *audio_raw_ep_2_desc[] = {
306 audio_raw_desc_32,
307 NULL,
308};
309
310static const struct usb_temp_endpoint_desc audio_isoc_in_ep = {
311 .ppRawDesc = audio_raw_ep_2_desc,
312 .pPacketSize = &audio_isoc_mps,
313 .pIntervals = &audio_isoc_interval,
314 .bEndpointAddress = UE_DIR_IN,
315 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT,
316};
317
318static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = {
319 &audio_isoc_in_ep,
320 NULL,
321};
322
323static const struct usb_temp_interface_desc audio_iface_2_alt_0 = {
324 .ppEndpoints = NULL, /* no endpoints */
325 .ppRawDesc = NULL, /* no raw descriptors */
326 .bInterfaceClass = 1,
327 .bInterfaceSubClass = 2,
328 .bInterfaceProtocol = 0,
329 .iInterface = INDEX_AUDIO_RECORD,
330};
331
332static const struct usb_temp_interface_desc audio_iface_2_alt_1 = {
333 .ppEndpoints = audio_iface_2_ep,
334 .ppRawDesc = audio_raw_iface_2_desc,
335 .bInterfaceClass = 1,
336 .bInterfaceSubClass = 2,
337 .bInterfaceProtocol = 0,
338 .iInterface = INDEX_AUDIO_RECORD,
339 .isAltInterface = 1, /* this is an alternate setting */
340};
341
342static const struct usb_temp_interface_desc *audio_interfaces[] = {
343 &audio_iface_0,
344 &audio_iface_1_alt_0,
345 &audio_iface_1_alt_1,
346 &audio_iface_2_alt_0,
347 &audio_iface_2_alt_1,
348 NULL,
349};
350
351static const struct usb_temp_config_desc audio_config_desc = {
352 .ppIfaceDesc = audio_interfaces,
353 .bmAttributes = UC_BUS_POWERED,
354 .bMaxPower = 25, /* 50 mA */
355 .iConfiguration = INDEX_AUDIO_PRODUCT,
356};
357
358static const struct usb_temp_config_desc *audio_configs[] = {
359 &audio_config_desc,
360 NULL,
361};
362
363static usb_temp_get_string_desc_t audio_get_string_desc;
364
365const struct usb_temp_device_desc usb_template_audio = {
366 .getStringDesc = &audio_get_string_desc,
367 .ppConfigDesc = audio_configs,
368 .idVendor = USB_TEMPLATE_VENDOR,
369 .idProduct = 0x000A,
370 .bcdDevice = 0x0100,
371 .bDeviceClass = UDCLASS_COMM,
372 .bDeviceSubClass = 0,
373 .bDeviceProtocol = 0,
374 .iManufacturer = 0,
375 .iProduct = INDEX_AUDIO_PRODUCT,
376 .iSerialNumber = 0,
377};
378
379/*------------------------------------------------------------------------*
380 * audio_get_string_desc
381 *
382 * Return values:
383 * NULL: Failure. No such string.
384 * Else: Success. Pointer to string descriptor is returned.
385 *------------------------------------------------------------------------*/
386static const void *
387audio_get_string_desc(uint16_t lang_id, uint8_t string_index)
388{
389 static const void *ptr[INDEX_AUDIO_MAX] = {
90USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer);
91USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record);
92USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback);
93USB_MAKE_STRING_DESC(STRING_AUDIO_PRODUCT, string_audio_product);
94
95/* prototypes */
96
97/*
98 * Audio Mixer description structures
99 *
100 * Some of the audio descriptors were dumped
101 * from a Creative Labs USB audio device.
102 */
103
104static const uint8_t audio_raw_desc_0[] = {
105 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02,
106 0x01, 0x02
107};
108
109static const uint8_t audio_raw_desc_1[] = {
110 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02,
111 0x03, 0x00, 0x00, 0x00
112};
113
114static const uint8_t audio_raw_desc_2[] = {
115 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02,
116 0x03, 0x00, 0x00, 0x00
117};
118
119static const uint8_t audio_raw_desc_3[] = {
120 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02,
121 0x03, 0x00, 0x00, 0x00
122};
123
124static const uint8_t audio_raw_desc_4[] = {
125 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02,
126 0x03, 0x00, 0x00, 0x00
127};
128
129static const uint8_t audio_raw_desc_5[] = {
130 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01,
131 0x00
132};
133
134static const uint8_t audio_raw_desc_6[] = {
135 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09,
136 0x00
137};
138
139static const uint8_t audio_raw_desc_7[] = {
140 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08,
141 0x00
142};
143
144static const uint8_t audio_raw_desc_8[] = {
145 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c,
146 0x00
147};
148
149static const uint8_t audio_raw_desc_9[] = {
150 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02,
151 0x02, 0x00
152};
153
154static const uint8_t audio_raw_desc_10[] = {
155 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00,
156 0x00, 0x00
157};
158
159static const uint8_t audio_raw_desc_11[] = {
160 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02,
161 0x02, 0x00
162};
163
164static const uint8_t audio_raw_desc_12[] = {
165 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00,
166 0x00, 0x00
167};
168
169static const uint8_t audio_raw_desc_13[] = {
170 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00,
171 0x00, 0x00
172};
173
174static const uint8_t audio_raw_desc_14[] = {
175 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02,
176 0x02, 0x00
177};
178
179static const uint8_t audio_raw_desc_15[] = {
180 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e,
181 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00
182};
183
184static const void *audio_raw_iface_0_desc[] = {
185 audio_raw_desc_0,
186 audio_raw_desc_1,
187 audio_raw_desc_2,
188 audio_raw_desc_3,
189 audio_raw_desc_4,
190 audio_raw_desc_5,
191 audio_raw_desc_6,
192 audio_raw_desc_7,
193 audio_raw_desc_8,
194 audio_raw_desc_9,
195 audio_raw_desc_10,
196 audio_raw_desc_11,
197 audio_raw_desc_12,
198 audio_raw_desc_13,
199 audio_raw_desc_14,
200 audio_raw_desc_15,
201 NULL,
202};
203
204static const struct usb_temp_interface_desc audio_iface_0 = {
205 .ppEndpoints = NULL, /* no endpoints */
206 .ppRawDesc = audio_raw_iface_0_desc,
207 .bInterfaceClass = 1,
208 .bInterfaceSubClass = 1,
209 .bInterfaceProtocol = 0,
210 .iInterface = INDEX_AUDIO_MIXER,
211};
212
213static const uint8_t audio_raw_desc_20[] = {
214 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00
215
216};
217
218static const uint8_t audio_raw_desc_21[] = {
219 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01,
220 /* 48kHz */
221 0x80, 0xbb, 0x00
222};
223
224static const uint8_t audio_raw_desc_22[] = {
225 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00
226};
227
228static const void *audio_raw_iface_1_desc[] = {
229 audio_raw_desc_20,
230 audio_raw_desc_21,
231 NULL,
232};
233
234static const void *audio_raw_ep_1_desc[] = {
235 audio_raw_desc_22,
236 NULL,
237};
238
239static const struct usb_temp_packet_size audio_isoc_mps = {
240 .mps[USB_SPEED_FULL] = 0xC8,
241 .mps[USB_SPEED_HIGH] = 0xC8,
242};
243
244static const struct usb_temp_interval audio_isoc_interval = {
245 .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */
246 .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */
247};
248
249static const struct usb_temp_endpoint_desc audio_isoc_out_ep = {
250 .ppRawDesc = audio_raw_ep_1_desc,
251 .pPacketSize = &audio_isoc_mps,
252 .pIntervals = &audio_isoc_interval,
253 .bEndpointAddress = UE_DIR_OUT,
254 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT,
255};
256
257static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = {
258 &audio_isoc_out_ep,
259 NULL,
260};
261
262static const struct usb_temp_interface_desc audio_iface_1_alt_0 = {
263 .ppEndpoints = NULL, /* no endpoints */
264 .ppRawDesc = NULL, /* no raw descriptors */
265 .bInterfaceClass = 1,
266 .bInterfaceSubClass = 2,
267 .bInterfaceProtocol = 0,
268 .iInterface = INDEX_AUDIO_PLAYBACK,
269};
270
271static const struct usb_temp_interface_desc audio_iface_1_alt_1 = {
272 .ppEndpoints = audio_iface_1_ep,
273 .ppRawDesc = audio_raw_iface_1_desc,
274 .bInterfaceClass = 1,
275 .bInterfaceSubClass = 2,
276 .bInterfaceProtocol = 0,
277 .iInterface = INDEX_AUDIO_PLAYBACK,
278 .isAltInterface = 1, /* this is an alternate setting */
279};
280
281static const uint8_t audio_raw_desc_30[] = {
282 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00
283
284};
285
286static const uint8_t audio_raw_desc_31[] = {
287 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01,
288 /* 48kHz */
289 0x80, 0xbb, 0x00
290};
291
292static const uint8_t audio_raw_desc_32[] = {
293 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00
294};
295
296static const void *audio_raw_iface_2_desc[] = {
297 audio_raw_desc_30,
298 audio_raw_desc_31,
299 NULL,
300};
301
302static const void *audio_raw_ep_2_desc[] = {
303 audio_raw_desc_32,
304 NULL,
305};
306
307static const struct usb_temp_endpoint_desc audio_isoc_in_ep = {
308 .ppRawDesc = audio_raw_ep_2_desc,
309 .pPacketSize = &audio_isoc_mps,
310 .pIntervals = &audio_isoc_interval,
311 .bEndpointAddress = UE_DIR_IN,
312 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT,
313};
314
315static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = {
316 &audio_isoc_in_ep,
317 NULL,
318};
319
320static const struct usb_temp_interface_desc audio_iface_2_alt_0 = {
321 .ppEndpoints = NULL, /* no endpoints */
322 .ppRawDesc = NULL, /* no raw descriptors */
323 .bInterfaceClass = 1,
324 .bInterfaceSubClass = 2,
325 .bInterfaceProtocol = 0,
326 .iInterface = INDEX_AUDIO_RECORD,
327};
328
329static const struct usb_temp_interface_desc audio_iface_2_alt_1 = {
330 .ppEndpoints = audio_iface_2_ep,
331 .ppRawDesc = audio_raw_iface_2_desc,
332 .bInterfaceClass = 1,
333 .bInterfaceSubClass = 2,
334 .bInterfaceProtocol = 0,
335 .iInterface = INDEX_AUDIO_RECORD,
336 .isAltInterface = 1, /* this is an alternate setting */
337};
338
339static const struct usb_temp_interface_desc *audio_interfaces[] = {
340 &audio_iface_0,
341 &audio_iface_1_alt_0,
342 &audio_iface_1_alt_1,
343 &audio_iface_2_alt_0,
344 &audio_iface_2_alt_1,
345 NULL,
346};
347
348static const struct usb_temp_config_desc audio_config_desc = {
349 .ppIfaceDesc = audio_interfaces,
350 .bmAttributes = UC_BUS_POWERED,
351 .bMaxPower = 25, /* 50 mA */
352 .iConfiguration = INDEX_AUDIO_PRODUCT,
353};
354
355static const struct usb_temp_config_desc *audio_configs[] = {
356 &audio_config_desc,
357 NULL,
358};
359
360static usb_temp_get_string_desc_t audio_get_string_desc;
361
362const struct usb_temp_device_desc usb_template_audio = {
363 .getStringDesc = &audio_get_string_desc,
364 .ppConfigDesc = audio_configs,
365 .idVendor = USB_TEMPLATE_VENDOR,
366 .idProduct = 0x000A,
367 .bcdDevice = 0x0100,
368 .bDeviceClass = UDCLASS_COMM,
369 .bDeviceSubClass = 0,
370 .bDeviceProtocol = 0,
371 .iManufacturer = 0,
372 .iProduct = INDEX_AUDIO_PRODUCT,
373 .iSerialNumber = 0,
374};
375
376/*------------------------------------------------------------------------*
377 * audio_get_string_desc
378 *
379 * Return values:
380 * NULL: Failure. No such string.
381 * Else: Success. Pointer to string descriptor is returned.
382 *------------------------------------------------------------------------*/
383static const void *
384audio_get_string_desc(uint16_t lang_id, uint8_t string_index)
385{
386 static const void *ptr[INDEX_AUDIO_MAX] = {
390 [INDEX_AUDIO_LANG] = &string_lang,
387 [INDEX_AUDIO_LANG] = &usb_string_lang_en,
391 [INDEX_AUDIO_MIXER] = &string_audio_mixer,
392 [INDEX_AUDIO_RECORD] = &string_audio_record,
393 [INDEX_AUDIO_PLAYBACK] = &string_audio_playback,
394 [INDEX_AUDIO_PRODUCT] = &string_audio_product,
395 };
396
397 if (string_index == 0) {
388 [INDEX_AUDIO_MIXER] = &string_audio_mixer,
389 [INDEX_AUDIO_RECORD] = &string_audio_record,
390 [INDEX_AUDIO_PLAYBACK] = &string_audio_playback,
391 [INDEX_AUDIO_PRODUCT] = &string_audio_product,
392 };
393
394 if (string_index == 0) {
398 return (&string_lang);
395 return (&usb_string_lang_en);
399 }
400 if (lang_id != 0x0409) {
401 return (NULL);
402 }
403 if (string_index < INDEX_AUDIO_MAX) {
404 return (ptr[string_index]);
405 }
406 return (NULL);
407}
396 }
397 if (lang_id != 0x0409) {
398 return (NULL);
399 }
400 if (string_index < INDEX_AUDIO_MAX) {
401 return (ptr[string_index]);
402 }
403 return (NULL);
404}