1d2b99310SHans Petter Selasky /* $FreeBSD$ */ 2399e6543SHans Petter Selasky /*- 3*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4*718cf2ccSPedro F. Giffuni * 5399e6543SHans Petter Selasky * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. 6399e6543SHans Petter Selasky * 7399e6543SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 8399e6543SHans Petter Selasky * modification, are permitted provided that the following conditions 9399e6543SHans Petter Selasky * are met: 10399e6543SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 11399e6543SHans Petter Selasky * notice, this list of conditions and the following disclaimer. 12399e6543SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 13399e6543SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 14399e6543SHans Petter Selasky * documentation and/or other materials provided with the distribution. 15399e6543SHans Petter Selasky * 16399e6543SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17399e6543SHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18399e6543SHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19399e6543SHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20399e6543SHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21399e6543SHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22399e6543SHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23399e6543SHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24399e6543SHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25399e6543SHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26399e6543SHans Petter Selasky * SUCH DAMAGE. 27399e6543SHans Petter Selasky */ 28399e6543SHans Petter Selasky 29399e6543SHans Petter Selasky /* 30399e6543SHans Petter Selasky * This file contains the USB template for an USB Audio Device. 31399e6543SHans Petter Selasky */ 32399e6543SHans Petter Selasky 33d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE 34d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE 35d2b99310SHans Petter Selasky #else 36399e6543SHans Petter Selasky #include <sys/stdint.h> 37399e6543SHans Petter Selasky #include <sys/stddef.h> 38399e6543SHans Petter Selasky #include <sys/param.h> 39399e6543SHans Petter Selasky #include <sys/queue.h> 40399e6543SHans Petter Selasky #include <sys/types.h> 41399e6543SHans Petter Selasky #include <sys/systm.h> 42399e6543SHans Petter Selasky #include <sys/kernel.h> 43399e6543SHans Petter Selasky #include <sys/bus.h> 44399e6543SHans Petter Selasky #include <sys/module.h> 45399e6543SHans Petter Selasky #include <sys/lock.h> 46399e6543SHans Petter Selasky #include <sys/mutex.h> 47399e6543SHans Petter Selasky #include <sys/condvar.h> 48399e6543SHans Petter Selasky #include <sys/sysctl.h> 49399e6543SHans Petter Selasky #include <sys/sx.h> 50399e6543SHans Petter Selasky #include <sys/unistd.h> 51399e6543SHans Petter Selasky #include <sys/callout.h> 52399e6543SHans Petter Selasky #include <sys/malloc.h> 53399e6543SHans Petter Selasky #include <sys/priv.h> 54399e6543SHans Petter Selasky 55399e6543SHans Petter Selasky #include <dev/usb/usb.h> 56399e6543SHans Petter Selasky #include <dev/usb/usbdi.h> 5723ab0871SHans Petter Selasky #include <dev/usb/usb_core.h> 58399e6543SHans Petter Selasky #include <dev/usb/usb_cdc.h> 59399e6543SHans Petter Selasky 60399e6543SHans Petter Selasky #include <dev/usb/template/usb_template.h> 61d2b99310SHans Petter Selasky #endif /* USB_GLOBAL_INCLUDE_FILE */ 62399e6543SHans Petter Selasky 63399e6543SHans Petter Selasky enum { 64399e6543SHans Petter Selasky INDEX_AUDIO_LANG, 65399e6543SHans Petter Selasky INDEX_AUDIO_MIXER, 66399e6543SHans Petter Selasky INDEX_AUDIO_RECORD, 67399e6543SHans Petter Selasky INDEX_AUDIO_PLAYBACK, 68399e6543SHans Petter Selasky INDEX_AUDIO_PRODUCT, 69399e6543SHans Petter Selasky INDEX_AUDIO_MAX, 70399e6543SHans Petter Selasky }; 71399e6543SHans Petter Selasky 72399e6543SHans Petter Selasky #define STRING_AUDIO_PRODUCT \ 73b51875c9SHans Petter Selasky "A\0u\0d\0i\0o\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" 74399e6543SHans Petter Selasky 75399e6543SHans Petter Selasky #define STRING_AUDIO_MIXER \ 76b51875c9SHans Petter Selasky "M\0i\0x\0e\0r\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 77399e6543SHans Petter Selasky 78399e6543SHans Petter Selasky #define STRING_AUDIO_RECORD \ 79b51875c9SHans Petter Selasky "R\0e\0c\0o\0r\0d\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 80399e6543SHans Petter Selasky 81399e6543SHans Petter Selasky #define STRING_AUDIO_PLAYBACK \ 82b51875c9SHans Petter Selasky "P\0l\0a\0y\0b\0a\0c\0k\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 83399e6543SHans Petter Selasky 84399e6543SHans Petter Selasky 85399e6543SHans Petter Selasky /* make the real string descriptors */ 86399e6543SHans Petter Selasky 87399e6543SHans Petter Selasky USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer); 88399e6543SHans Petter Selasky USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record); 89399e6543SHans Petter Selasky USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback); 90399e6543SHans Petter Selasky USB_MAKE_STRING_DESC(STRING_AUDIO_PRODUCT, string_audio_product); 91399e6543SHans Petter Selasky 92399e6543SHans Petter Selasky /* prototypes */ 93399e6543SHans Petter Selasky 94df142785SHans Petter Selasky /* 95df142785SHans Petter Selasky * Audio Mixer description structures 96df142785SHans Petter Selasky * 97df142785SHans Petter Selasky * Some of the audio descriptors were dumped 98df142785SHans Petter Selasky * from a Creative Labs USB audio device. 99df142785SHans Petter Selasky */ 100399e6543SHans Petter Selasky 101399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_0[] = { 102399e6543SHans Petter Selasky 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02, 103399e6543SHans Petter Selasky 0x01, 0x02 104399e6543SHans Petter Selasky }; 105399e6543SHans Petter Selasky 106399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_1[] = { 107399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 108399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 109399e6543SHans Petter Selasky }; 110399e6543SHans Petter Selasky 111399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_2[] = { 112399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 113399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 114399e6543SHans Petter Selasky }; 115399e6543SHans Petter Selasky 116399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_3[] = { 117399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02, 118399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 119399e6543SHans Petter Selasky }; 120399e6543SHans Petter Selasky 121399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_4[] = { 122399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02, 123399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 124399e6543SHans Petter Selasky }; 125399e6543SHans Petter Selasky 126399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_5[] = { 127399e6543SHans Petter Selasky 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01, 128399e6543SHans Petter Selasky 0x00 129399e6543SHans Petter Selasky }; 130399e6543SHans Petter Selasky 131399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_6[] = { 132399e6543SHans Petter Selasky 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09, 133399e6543SHans Petter Selasky 0x00 134399e6543SHans Petter Selasky }; 135399e6543SHans Petter Selasky 136399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_7[] = { 137399e6543SHans Petter Selasky 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08, 138399e6543SHans Petter Selasky 0x00 139399e6543SHans Petter Selasky }; 140399e6543SHans Petter Selasky 141399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_8[] = { 142399e6543SHans Petter Selasky 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c, 143399e6543SHans Petter Selasky 0x00 144399e6543SHans Petter Selasky }; 145399e6543SHans Petter Selasky 146399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_9[] = { 147399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02, 148399e6543SHans Petter Selasky 0x02, 0x00 149399e6543SHans Petter Selasky }; 150399e6543SHans Petter Selasky 151399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_10[] = { 152399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00, 153399e6543SHans Petter Selasky 0x00, 0x00 154399e6543SHans Petter Selasky }; 155399e6543SHans Petter Selasky 156399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_11[] = { 157399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02, 158399e6543SHans Petter Selasky 0x02, 0x00 159399e6543SHans Petter Selasky }; 160399e6543SHans Petter Selasky 161399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_12[] = { 162399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00, 163399e6543SHans Petter Selasky 0x00, 0x00 164399e6543SHans Petter Selasky }; 165399e6543SHans Petter Selasky 166399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_13[] = { 167399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00, 168399e6543SHans Petter Selasky 0x00, 0x00 169399e6543SHans Petter Selasky }; 170399e6543SHans Petter Selasky 171399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_14[] = { 172399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02, 173399e6543SHans Petter Selasky 0x02, 0x00 174399e6543SHans Petter Selasky }; 175399e6543SHans Petter Selasky 176399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_15[] = { 177399e6543SHans Petter Selasky 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e, 178399e6543SHans Petter Selasky 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 179399e6543SHans Petter Selasky }; 180399e6543SHans Petter Selasky 181399e6543SHans Petter Selasky static const void *audio_raw_iface_0_desc[] = { 182399e6543SHans Petter Selasky audio_raw_desc_0, 183399e6543SHans Petter Selasky audio_raw_desc_1, 184399e6543SHans Petter Selasky audio_raw_desc_2, 185399e6543SHans Petter Selasky audio_raw_desc_3, 186399e6543SHans Petter Selasky audio_raw_desc_4, 187399e6543SHans Petter Selasky audio_raw_desc_5, 188399e6543SHans Petter Selasky audio_raw_desc_6, 189399e6543SHans Petter Selasky audio_raw_desc_7, 190399e6543SHans Petter Selasky audio_raw_desc_8, 191399e6543SHans Petter Selasky audio_raw_desc_9, 192399e6543SHans Petter Selasky audio_raw_desc_10, 193399e6543SHans Petter Selasky audio_raw_desc_11, 194399e6543SHans Petter Selasky audio_raw_desc_12, 195399e6543SHans Petter Selasky audio_raw_desc_13, 196399e6543SHans Petter Selasky audio_raw_desc_14, 197399e6543SHans Petter Selasky audio_raw_desc_15, 198399e6543SHans Petter Selasky NULL, 199399e6543SHans Petter Selasky }; 200399e6543SHans Petter Selasky 201399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_0 = { 202399e6543SHans Petter Selasky .ppEndpoints = NULL, /* no endpoints */ 203399e6543SHans Petter Selasky .ppRawDesc = audio_raw_iface_0_desc, 2044ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 2054ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL, 206399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 207399e6543SHans Petter Selasky .iInterface = INDEX_AUDIO_MIXER, 208399e6543SHans Petter Selasky }; 209399e6543SHans Petter Selasky 210399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_20[] = { 211399e6543SHans Petter Selasky 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00 212399e6543SHans Petter Selasky 213399e6543SHans Petter Selasky }; 214399e6543SHans Petter Selasky 215399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_21[] = { 216399e6543SHans Petter Selasky 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 217399e6543SHans Petter Selasky /* 48kHz */ 218399e6543SHans Petter Selasky 0x80, 0xbb, 0x00 219399e6543SHans Petter Selasky }; 220399e6543SHans Petter Selasky 221399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_22[] = { 222399e6543SHans Petter Selasky 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00 223399e6543SHans Petter Selasky }; 224399e6543SHans Petter Selasky 225399e6543SHans Petter Selasky static const void *audio_raw_iface_1_desc[] = { 226399e6543SHans Petter Selasky audio_raw_desc_20, 227399e6543SHans Petter Selasky audio_raw_desc_21, 228399e6543SHans Petter Selasky NULL, 229399e6543SHans Petter Selasky }; 230399e6543SHans Petter Selasky 231399e6543SHans Petter Selasky static const void *audio_raw_ep_1_desc[] = { 232399e6543SHans Petter Selasky audio_raw_desc_22, 233399e6543SHans Petter Selasky NULL, 234399e6543SHans Petter Selasky }; 235399e6543SHans Petter Selasky 236399e6543SHans Petter Selasky static const struct usb_temp_packet_size audio_isoc_mps = { 237399e6543SHans Petter Selasky .mps[USB_SPEED_FULL] = 0xC8, 238399e6543SHans Petter Selasky .mps[USB_SPEED_HIGH] = 0xC8, 239399e6543SHans Petter Selasky }; 240399e6543SHans Petter Selasky 241399e6543SHans Petter Selasky static const struct usb_temp_interval audio_isoc_interval = { 242399e6543SHans Petter Selasky .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ 243399e6543SHans Petter Selasky .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ 244399e6543SHans Petter Selasky }; 245399e6543SHans Petter Selasky 246399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc audio_isoc_out_ep = { 247399e6543SHans Petter Selasky .ppRawDesc = audio_raw_ep_1_desc, 248399e6543SHans Petter Selasky .pPacketSize = &audio_isoc_mps, 249399e6543SHans Petter Selasky .pIntervals = &audio_isoc_interval, 250399e6543SHans Petter Selasky .bEndpointAddress = UE_DIR_OUT, 251399e6543SHans Petter Selasky .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 252399e6543SHans Petter Selasky }; 253399e6543SHans Petter Selasky 254399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = { 255399e6543SHans Petter Selasky &audio_isoc_out_ep, 256399e6543SHans Petter Selasky NULL, 257399e6543SHans Petter Selasky }; 258399e6543SHans Petter Selasky 259399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_1_alt_0 = { 260399e6543SHans Petter Selasky .ppEndpoints = NULL, /* no endpoints */ 261399e6543SHans Petter Selasky .ppRawDesc = NULL, /* no raw descriptors */ 2624ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 2634ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 264399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 265399e6543SHans Petter Selasky .iInterface = INDEX_AUDIO_PLAYBACK, 266399e6543SHans Petter Selasky }; 267399e6543SHans Petter Selasky 268399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_1_alt_1 = { 269399e6543SHans Petter Selasky .ppEndpoints = audio_iface_1_ep, 270399e6543SHans Petter Selasky .ppRawDesc = audio_raw_iface_1_desc, 2714ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 2724ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 273399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 274399e6543SHans Petter Selasky .iInterface = INDEX_AUDIO_PLAYBACK, 275399e6543SHans Petter Selasky .isAltInterface = 1, /* this is an alternate setting */ 276399e6543SHans Petter Selasky }; 277399e6543SHans Petter Selasky 278399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_30[] = { 279399e6543SHans Petter Selasky 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00 280399e6543SHans Petter Selasky 281399e6543SHans Petter Selasky }; 282399e6543SHans Petter Selasky 283399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_31[] = { 284399e6543SHans Petter Selasky 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 285399e6543SHans Petter Selasky /* 48kHz */ 286399e6543SHans Petter Selasky 0x80, 0xbb, 0x00 287399e6543SHans Petter Selasky }; 288399e6543SHans Petter Selasky 289399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_32[] = { 290399e6543SHans Petter Selasky 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00 291399e6543SHans Petter Selasky }; 292399e6543SHans Petter Selasky 293399e6543SHans Petter Selasky static const void *audio_raw_iface_2_desc[] = { 294399e6543SHans Petter Selasky audio_raw_desc_30, 295399e6543SHans Petter Selasky audio_raw_desc_31, 296399e6543SHans Petter Selasky NULL, 297399e6543SHans Petter Selasky }; 298399e6543SHans Petter Selasky 299399e6543SHans Petter Selasky static const void *audio_raw_ep_2_desc[] = { 300399e6543SHans Petter Selasky audio_raw_desc_32, 301399e6543SHans Petter Selasky NULL, 302399e6543SHans Petter Selasky }; 303399e6543SHans Petter Selasky 304399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc audio_isoc_in_ep = { 305399e6543SHans Petter Selasky .ppRawDesc = audio_raw_ep_2_desc, 306399e6543SHans Petter Selasky .pPacketSize = &audio_isoc_mps, 307399e6543SHans Petter Selasky .pIntervals = &audio_isoc_interval, 308399e6543SHans Petter Selasky .bEndpointAddress = UE_DIR_IN, 309399e6543SHans Petter Selasky .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 310399e6543SHans Petter Selasky }; 311399e6543SHans Petter Selasky 312399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = { 313399e6543SHans Petter Selasky &audio_isoc_in_ep, 314399e6543SHans Petter Selasky NULL, 315399e6543SHans Petter Selasky }; 316399e6543SHans Petter Selasky 317399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_2_alt_0 = { 318399e6543SHans Petter Selasky .ppEndpoints = NULL, /* no endpoints */ 319399e6543SHans Petter Selasky .ppRawDesc = NULL, /* no raw descriptors */ 3204ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 3214ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 322399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 323399e6543SHans Petter Selasky .iInterface = INDEX_AUDIO_RECORD, 324399e6543SHans Petter Selasky }; 325399e6543SHans Petter Selasky 326399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_2_alt_1 = { 327399e6543SHans Petter Selasky .ppEndpoints = audio_iface_2_ep, 328399e6543SHans Petter Selasky .ppRawDesc = audio_raw_iface_2_desc, 3294ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 3304ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 331399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 332399e6543SHans Petter Selasky .iInterface = INDEX_AUDIO_RECORD, 333399e6543SHans Petter Selasky .isAltInterface = 1, /* this is an alternate setting */ 334399e6543SHans Petter Selasky }; 335399e6543SHans Petter Selasky 336399e6543SHans Petter Selasky static const struct usb_temp_interface_desc *audio_interfaces[] = { 337399e6543SHans Petter Selasky &audio_iface_0, 338399e6543SHans Petter Selasky &audio_iface_1_alt_0, 339399e6543SHans Petter Selasky &audio_iface_1_alt_1, 340399e6543SHans Petter Selasky &audio_iface_2_alt_0, 341399e6543SHans Petter Selasky &audio_iface_2_alt_1, 342399e6543SHans Petter Selasky NULL, 343399e6543SHans Petter Selasky }; 344399e6543SHans Petter Selasky 345399e6543SHans Petter Selasky static const struct usb_temp_config_desc audio_config_desc = { 346399e6543SHans Petter Selasky .ppIfaceDesc = audio_interfaces, 347399e6543SHans Petter Selasky .bmAttributes = UC_BUS_POWERED, 348399e6543SHans Petter Selasky .bMaxPower = 25, /* 50 mA */ 349399e6543SHans Petter Selasky .iConfiguration = INDEX_AUDIO_PRODUCT, 350399e6543SHans Petter Selasky }; 351399e6543SHans Petter Selasky 352399e6543SHans Petter Selasky static const struct usb_temp_config_desc *audio_configs[] = { 353399e6543SHans Petter Selasky &audio_config_desc, 354399e6543SHans Petter Selasky NULL, 355399e6543SHans Petter Selasky }; 356399e6543SHans Petter Selasky 357399e6543SHans Petter Selasky static usb_temp_get_string_desc_t audio_get_string_desc; 358399e6543SHans Petter Selasky 359399e6543SHans Petter Selasky const struct usb_temp_device_desc usb_template_audio = { 360399e6543SHans Petter Selasky .getStringDesc = &audio_get_string_desc, 361399e6543SHans Petter Selasky .ppConfigDesc = audio_configs, 362399e6543SHans Petter Selasky .idVendor = USB_TEMPLATE_VENDOR, 363399e6543SHans Petter Selasky .idProduct = 0x000A, 364399e6543SHans Petter Selasky .bcdDevice = 0x0100, 365399e6543SHans Petter Selasky .bDeviceClass = UDCLASS_COMM, 366399e6543SHans Petter Selasky .bDeviceSubClass = 0, 367399e6543SHans Petter Selasky .bDeviceProtocol = 0, 368399e6543SHans Petter Selasky .iManufacturer = 0, 369399e6543SHans Petter Selasky .iProduct = INDEX_AUDIO_PRODUCT, 370399e6543SHans Petter Selasky .iSerialNumber = 0, 371399e6543SHans Petter Selasky }; 372399e6543SHans Petter Selasky 373399e6543SHans Petter Selasky /*------------------------------------------------------------------------* 374399e6543SHans Petter Selasky * audio_get_string_desc 375399e6543SHans Petter Selasky * 376399e6543SHans Petter Selasky * Return values: 377399e6543SHans Petter Selasky * NULL: Failure. No such string. 378399e6543SHans Petter Selasky * Else: Success. Pointer to string descriptor is returned. 379399e6543SHans Petter Selasky *------------------------------------------------------------------------*/ 380399e6543SHans Petter Selasky static const void * 381399e6543SHans Petter Selasky audio_get_string_desc(uint16_t lang_id, uint8_t string_index) 382399e6543SHans Petter Selasky { 383399e6543SHans Petter Selasky static const void *ptr[INDEX_AUDIO_MAX] = { 38423ab0871SHans Petter Selasky [INDEX_AUDIO_LANG] = &usb_string_lang_en, 385399e6543SHans Petter Selasky [INDEX_AUDIO_MIXER] = &string_audio_mixer, 386399e6543SHans Petter Selasky [INDEX_AUDIO_RECORD] = &string_audio_record, 387399e6543SHans Petter Selasky [INDEX_AUDIO_PLAYBACK] = &string_audio_playback, 388399e6543SHans Petter Selasky [INDEX_AUDIO_PRODUCT] = &string_audio_product, 389399e6543SHans Petter Selasky }; 390399e6543SHans Petter Selasky 391399e6543SHans Petter Selasky if (string_index == 0) { 39223ab0871SHans Petter Selasky return (&usb_string_lang_en); 393399e6543SHans Petter Selasky } 394399e6543SHans Petter Selasky if (lang_id != 0x0409) { 395399e6543SHans Petter Selasky return (NULL); 396399e6543SHans Petter Selasky } 397399e6543SHans Petter Selasky if (string_index < INDEX_AUDIO_MAX) { 398399e6543SHans Petter Selasky return (ptr[string_index]); 399399e6543SHans Petter Selasky } 400399e6543SHans Petter Selasky return (NULL); 401399e6543SHans Petter Selasky } 402