1d2b99310SHans Petter Selasky /* $FreeBSD$ */ 2399e6543SHans Petter Selasky /*- 3718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4718cf2ccSPedro F. Giffuni * 58e06491aSEdward Tomasz Napierala * Copyright (c) 2010 Hans Petter Selasky 68e06491aSEdward Tomasz Napierala * Copyright (c) 2018 The FreeBSD Foundation 78e06491aSEdward Tomasz Napierala * All rights reserved. 88e06491aSEdward Tomasz Napierala * 98e06491aSEdward Tomasz Napierala * Portions of this software were developed by Edward Tomasz Napierala 108e06491aSEdward Tomasz Napierala * under sponsorship from the FreeBSD Foundation. 11399e6543SHans Petter Selasky * 12399e6543SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 13399e6543SHans Petter Selasky * modification, are permitted provided that the following conditions 14399e6543SHans Petter Selasky * are met: 15399e6543SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 16399e6543SHans Petter Selasky * notice, this list of conditions and the following disclaimer. 17399e6543SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 18399e6543SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 19399e6543SHans Petter Selasky * documentation and/or other materials provided with the distribution. 20399e6543SHans Petter Selasky * 21399e6543SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22399e6543SHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23399e6543SHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24399e6543SHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25399e6543SHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26399e6543SHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27399e6543SHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28399e6543SHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29399e6543SHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30399e6543SHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31399e6543SHans Petter Selasky * SUCH DAMAGE. 32399e6543SHans Petter Selasky */ 33399e6543SHans Petter Selasky 34399e6543SHans Petter Selasky /* 35399e6543SHans Petter Selasky * This file contains the USB template for an USB Audio Device. 36399e6543SHans Petter Selasky */ 37399e6543SHans Petter Selasky 38d2b99310SHans Petter Selasky #ifdef USB_GLOBAL_INCLUDE_FILE 39d2b99310SHans Petter Selasky #include USB_GLOBAL_INCLUDE_FILE 40d2b99310SHans Petter Selasky #else 41399e6543SHans Petter Selasky #include <sys/stdint.h> 42399e6543SHans Petter Selasky #include <sys/stddef.h> 43399e6543SHans Petter Selasky #include <sys/param.h> 44399e6543SHans Petter Selasky #include <sys/queue.h> 45399e6543SHans Petter Selasky #include <sys/types.h> 46399e6543SHans Petter Selasky #include <sys/systm.h> 47399e6543SHans Petter Selasky #include <sys/kernel.h> 48399e6543SHans Petter Selasky #include <sys/bus.h> 49399e6543SHans Petter Selasky #include <sys/module.h> 50399e6543SHans Petter Selasky #include <sys/lock.h> 51399e6543SHans Petter Selasky #include <sys/mutex.h> 52399e6543SHans Petter Selasky #include <sys/condvar.h> 53399e6543SHans Petter Selasky #include <sys/sysctl.h> 54399e6543SHans Petter Selasky #include <sys/sx.h> 55399e6543SHans Petter Selasky #include <sys/unistd.h> 56399e6543SHans Petter Selasky #include <sys/callout.h> 57399e6543SHans Petter Selasky #include <sys/malloc.h> 58399e6543SHans Petter Selasky #include <sys/priv.h> 59399e6543SHans Petter Selasky 60399e6543SHans Petter Selasky #include <dev/usb/usb.h> 61399e6543SHans Petter Selasky #include <dev/usb/usbdi.h> 6223ab0871SHans Petter Selasky #include <dev/usb/usb_core.h> 63399e6543SHans Petter Selasky #include <dev/usb/usb_cdc.h> 648e06491aSEdward Tomasz Napierala #include <dev/usb/usb_ioctl.h> 658e06491aSEdward Tomasz Napierala #include <dev/usb/usb_util.h> 66399e6543SHans Petter Selasky 67399e6543SHans Petter Selasky #include <dev/usb/template/usb_template.h> 68d2b99310SHans Petter Selasky #endif /* USB_GLOBAL_INCLUDE_FILE */ 69399e6543SHans Petter Selasky 70399e6543SHans Petter Selasky enum { 718e06491aSEdward Tomasz Napierala AUDIO_LANG_INDEX, 728e06491aSEdward Tomasz Napierala AUDIO_MIXER_INDEX, 738e06491aSEdward Tomasz Napierala AUDIO_RECORD_INDEX, 748e06491aSEdward Tomasz Napierala AUDIO_PLAYBACK_INDEX, 751ee5bed7SEdward Tomasz Napierala AUDIO_MANUFACTURER_INDEX, 768e06491aSEdward Tomasz Napierala AUDIO_PRODUCT_INDEX, 771ee5bed7SEdward Tomasz Napierala AUDIO_SERIAL_NUMBER_INDEX, 788e06491aSEdward Tomasz Napierala AUDIO_MAX_INDEX, 79399e6543SHans Petter Selasky }; 80399e6543SHans Petter Selasky 811558eec6SEdward Tomasz Napierala #define AUDIO_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR 82*d01c1c8bSEdward Tomasz Napierala #define AUDIO_DEFAULT_PRODUCT_ID 0x05dc 838e06491aSEdward Tomasz Napierala #define AUDIO_DEFAULT_MIXER "Mixer interface" 848e06491aSEdward Tomasz Napierala #define AUDIO_DEFAULT_RECORD "Record interface" 858e06491aSEdward Tomasz Napierala #define AUDIO_DEFAULT_PLAYBACK "Playback interface" 86*d01c1c8bSEdward Tomasz Napierala #define AUDIO_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER 871ee5bed7SEdward Tomasz Napierala #define AUDIO_DEFAULT_PRODUCT "Audio Test Device" 881ee5bed7SEdward Tomasz Napierala #define AUDIO_DEFAULT_SERIAL_NUMBER "March 2008" 89399e6543SHans Petter Selasky 908e06491aSEdward Tomasz Napierala static struct usb_string_descriptor audio_mixer; 918e06491aSEdward Tomasz Napierala static struct usb_string_descriptor audio_record; 928e06491aSEdward Tomasz Napierala static struct usb_string_descriptor audio_playback; 931ee5bed7SEdward Tomasz Napierala static struct usb_string_descriptor audio_manufacturer; 948e06491aSEdward Tomasz Napierala static struct usb_string_descriptor audio_product; 951ee5bed7SEdward Tomasz Napierala static struct usb_string_descriptor audio_serial_number; 96399e6543SHans Petter Selasky 978e06491aSEdward Tomasz Napierala static struct sysctl_ctx_list audio_ctx_list; 98399e6543SHans Petter Selasky 99399e6543SHans Petter Selasky /* prototypes */ 100399e6543SHans Petter Selasky 101df142785SHans Petter Selasky /* 102df142785SHans Petter Selasky * Audio Mixer description structures 103df142785SHans Petter Selasky * 104df142785SHans Petter Selasky * Some of the audio descriptors were dumped 105df142785SHans Petter Selasky * from a Creative Labs USB audio device. 106df142785SHans Petter Selasky */ 107399e6543SHans Petter Selasky 108399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_0[] = { 109399e6543SHans Petter Selasky 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02, 110399e6543SHans Petter Selasky 0x01, 0x02 111399e6543SHans Petter Selasky }; 112399e6543SHans Petter Selasky 113399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_1[] = { 114399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 115399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 116399e6543SHans Petter Selasky }; 117399e6543SHans Petter Selasky 118399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_2[] = { 119399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 120399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 121399e6543SHans Petter Selasky }; 122399e6543SHans Petter Selasky 123399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_3[] = { 124399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02, 125399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 126399e6543SHans Petter Selasky }; 127399e6543SHans Petter Selasky 128399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_4[] = { 129399e6543SHans Petter Selasky 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02, 130399e6543SHans Petter Selasky 0x03, 0x00, 0x00, 0x00 131399e6543SHans Petter Selasky }; 132399e6543SHans Petter Selasky 133399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_5[] = { 134399e6543SHans Petter Selasky 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01, 135399e6543SHans Petter Selasky 0x00 136399e6543SHans Petter Selasky }; 137399e6543SHans Petter Selasky 138399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_6[] = { 139399e6543SHans Petter Selasky 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09, 140399e6543SHans Petter Selasky 0x00 141399e6543SHans Petter Selasky }; 142399e6543SHans Petter Selasky 143399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_7[] = { 144399e6543SHans Petter Selasky 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08, 145399e6543SHans Petter Selasky 0x00 146399e6543SHans Petter Selasky }; 147399e6543SHans Petter Selasky 148399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_8[] = { 149399e6543SHans Petter Selasky 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c, 150399e6543SHans Petter Selasky 0x00 151399e6543SHans Petter Selasky }; 152399e6543SHans Petter Selasky 153399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_9[] = { 154399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02, 155399e6543SHans Petter Selasky 0x02, 0x00 156399e6543SHans Petter Selasky }; 157399e6543SHans Petter Selasky 158399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_10[] = { 159399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00, 160399e6543SHans Petter Selasky 0x00, 0x00 161399e6543SHans Petter Selasky }; 162399e6543SHans Petter Selasky 163399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_11[] = { 164399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02, 165399e6543SHans Petter Selasky 0x02, 0x00 166399e6543SHans Petter Selasky }; 167399e6543SHans Petter Selasky 168399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_12[] = { 169399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00, 170399e6543SHans Petter Selasky 0x00, 0x00 171399e6543SHans Petter Selasky }; 172399e6543SHans Petter Selasky 173399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_13[] = { 174399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00, 175399e6543SHans Petter Selasky 0x00, 0x00 176399e6543SHans Petter Selasky }; 177399e6543SHans Petter Selasky 178399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_14[] = { 179399e6543SHans Petter Selasky 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02, 180399e6543SHans Petter Selasky 0x02, 0x00 181399e6543SHans Petter Selasky }; 182399e6543SHans Petter Selasky 183399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_15[] = { 184399e6543SHans Petter Selasky 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e, 185399e6543SHans Petter Selasky 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 186399e6543SHans Petter Selasky }; 187399e6543SHans Petter Selasky 188399e6543SHans Petter Selasky static const void *audio_raw_iface_0_desc[] = { 189399e6543SHans Petter Selasky audio_raw_desc_0, 190399e6543SHans Petter Selasky audio_raw_desc_1, 191399e6543SHans Petter Selasky audio_raw_desc_2, 192399e6543SHans Petter Selasky audio_raw_desc_3, 193399e6543SHans Petter Selasky audio_raw_desc_4, 194399e6543SHans Petter Selasky audio_raw_desc_5, 195399e6543SHans Petter Selasky audio_raw_desc_6, 196399e6543SHans Petter Selasky audio_raw_desc_7, 197399e6543SHans Petter Selasky audio_raw_desc_8, 198399e6543SHans Petter Selasky audio_raw_desc_9, 199399e6543SHans Petter Selasky audio_raw_desc_10, 200399e6543SHans Petter Selasky audio_raw_desc_11, 201399e6543SHans Petter Selasky audio_raw_desc_12, 202399e6543SHans Petter Selasky audio_raw_desc_13, 203399e6543SHans Petter Selasky audio_raw_desc_14, 204399e6543SHans Petter Selasky audio_raw_desc_15, 205399e6543SHans Petter Selasky NULL, 206399e6543SHans Petter Selasky }; 207399e6543SHans Petter Selasky 208399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_0 = { 209399e6543SHans Petter Selasky .ppEndpoints = NULL, /* no endpoints */ 210399e6543SHans Petter Selasky .ppRawDesc = audio_raw_iface_0_desc, 2114ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 2124ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL, 213399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 2148e06491aSEdward Tomasz Napierala .iInterface = AUDIO_MIXER_INDEX, 215399e6543SHans Petter Selasky }; 216399e6543SHans Petter Selasky 217399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_20[] = { 218399e6543SHans Petter Selasky 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00 219399e6543SHans Petter Selasky 220399e6543SHans Petter Selasky }; 221399e6543SHans Petter Selasky 222399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_21[] = { 223399e6543SHans Petter Selasky 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 224399e6543SHans Petter Selasky /* 48kHz */ 225399e6543SHans Petter Selasky 0x80, 0xbb, 0x00 226399e6543SHans Petter Selasky }; 227399e6543SHans Petter Selasky 228399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_22[] = { 229399e6543SHans Petter Selasky 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00 230399e6543SHans Petter Selasky }; 231399e6543SHans Petter Selasky 232399e6543SHans Petter Selasky static const void *audio_raw_iface_1_desc[] = { 233399e6543SHans Petter Selasky audio_raw_desc_20, 234399e6543SHans Petter Selasky audio_raw_desc_21, 235399e6543SHans Petter Selasky NULL, 236399e6543SHans Petter Selasky }; 237399e6543SHans Petter Selasky 238399e6543SHans Petter Selasky static const void *audio_raw_ep_1_desc[] = { 239399e6543SHans Petter Selasky audio_raw_desc_22, 240399e6543SHans Petter Selasky NULL, 241399e6543SHans Petter Selasky }; 242399e6543SHans Petter Selasky 243399e6543SHans Petter Selasky static const struct usb_temp_packet_size audio_isoc_mps = { 244399e6543SHans Petter Selasky .mps[USB_SPEED_FULL] = 0xC8, 245399e6543SHans Petter Selasky .mps[USB_SPEED_HIGH] = 0xC8, 246399e6543SHans Petter Selasky }; 247399e6543SHans Petter Selasky 248399e6543SHans Petter Selasky static const struct usb_temp_interval audio_isoc_interval = { 249399e6543SHans Petter Selasky .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ 250399e6543SHans Petter Selasky .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ 251399e6543SHans Petter Selasky }; 252399e6543SHans Petter Selasky 253399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc audio_isoc_out_ep = { 254399e6543SHans Petter Selasky .ppRawDesc = audio_raw_ep_1_desc, 255399e6543SHans Petter Selasky .pPacketSize = &audio_isoc_mps, 256399e6543SHans Petter Selasky .pIntervals = &audio_isoc_interval, 257399e6543SHans Petter Selasky .bEndpointAddress = UE_DIR_OUT, 258399e6543SHans Petter Selasky .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 259399e6543SHans Petter Selasky }; 260399e6543SHans Petter Selasky 261399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = { 262399e6543SHans Petter Selasky &audio_isoc_out_ep, 263399e6543SHans Petter Selasky NULL, 264399e6543SHans Petter Selasky }; 265399e6543SHans Petter Selasky 266399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_1_alt_0 = { 267399e6543SHans Petter Selasky .ppEndpoints = NULL, /* no endpoints */ 268399e6543SHans Petter Selasky .ppRawDesc = NULL, /* no raw descriptors */ 2694ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 2704ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 271399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 2728e06491aSEdward Tomasz Napierala .iInterface = AUDIO_PLAYBACK_INDEX, 273399e6543SHans Petter Selasky }; 274399e6543SHans Petter Selasky 275399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_1_alt_1 = { 276399e6543SHans Petter Selasky .ppEndpoints = audio_iface_1_ep, 277399e6543SHans Petter Selasky .ppRawDesc = audio_raw_iface_1_desc, 2784ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 2794ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 280399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 2818e06491aSEdward Tomasz Napierala .iInterface = AUDIO_PLAYBACK_INDEX, 282399e6543SHans Petter Selasky .isAltInterface = 1, /* this is an alternate setting */ 283399e6543SHans Petter Selasky }; 284399e6543SHans Petter Selasky 285399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_30[] = { 286399e6543SHans Petter Selasky 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00 287399e6543SHans Petter Selasky 288399e6543SHans Petter Selasky }; 289399e6543SHans Petter Selasky 290399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_31[] = { 291399e6543SHans Petter Selasky 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 292399e6543SHans Petter Selasky /* 48kHz */ 293399e6543SHans Petter Selasky 0x80, 0xbb, 0x00 294399e6543SHans Petter Selasky }; 295399e6543SHans Petter Selasky 296399e6543SHans Petter Selasky static const uint8_t audio_raw_desc_32[] = { 297399e6543SHans Petter Selasky 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00 298399e6543SHans Petter Selasky }; 299399e6543SHans Petter Selasky 300399e6543SHans Petter Selasky static const void *audio_raw_iface_2_desc[] = { 301399e6543SHans Petter Selasky audio_raw_desc_30, 302399e6543SHans Petter Selasky audio_raw_desc_31, 303399e6543SHans Petter Selasky NULL, 304399e6543SHans Petter Selasky }; 305399e6543SHans Petter Selasky 306399e6543SHans Petter Selasky static const void *audio_raw_ep_2_desc[] = { 307399e6543SHans Petter Selasky audio_raw_desc_32, 308399e6543SHans Petter Selasky NULL, 309399e6543SHans Petter Selasky }; 310399e6543SHans Petter Selasky 311399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc audio_isoc_in_ep = { 312399e6543SHans Petter Selasky .ppRawDesc = audio_raw_ep_2_desc, 313399e6543SHans Petter Selasky .pPacketSize = &audio_isoc_mps, 314399e6543SHans Petter Selasky .pIntervals = &audio_isoc_interval, 315399e6543SHans Petter Selasky .bEndpointAddress = UE_DIR_IN, 316399e6543SHans Petter Selasky .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 317399e6543SHans Petter Selasky }; 318399e6543SHans Petter Selasky 319399e6543SHans Petter Selasky static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = { 320399e6543SHans Petter Selasky &audio_isoc_in_ep, 321399e6543SHans Petter Selasky NULL, 322399e6543SHans Petter Selasky }; 323399e6543SHans Petter Selasky 324399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_2_alt_0 = { 325399e6543SHans Petter Selasky .ppEndpoints = NULL, /* no endpoints */ 326399e6543SHans Petter Selasky .ppRawDesc = NULL, /* no raw descriptors */ 3274ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 3284ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 329399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 3308e06491aSEdward Tomasz Napierala .iInterface = AUDIO_RECORD_INDEX, 331399e6543SHans Petter Selasky }; 332399e6543SHans Petter Selasky 333399e6543SHans Petter Selasky static const struct usb_temp_interface_desc audio_iface_2_alt_1 = { 334399e6543SHans Petter Selasky .ppEndpoints = audio_iface_2_ep, 335399e6543SHans Petter Selasky .ppRawDesc = audio_raw_iface_2_desc, 3364ffeccf1SEdward Tomasz Napierala .bInterfaceClass = UICLASS_AUDIO, 3374ffeccf1SEdward Tomasz Napierala .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 338399e6543SHans Petter Selasky .bInterfaceProtocol = 0, 3398e06491aSEdward Tomasz Napierala .iInterface = AUDIO_RECORD_INDEX, 340399e6543SHans Petter Selasky .isAltInterface = 1, /* this is an alternate setting */ 341399e6543SHans Petter Selasky }; 342399e6543SHans Petter Selasky 343399e6543SHans Petter Selasky static const struct usb_temp_interface_desc *audio_interfaces[] = { 344399e6543SHans Petter Selasky &audio_iface_0, 345399e6543SHans Petter Selasky &audio_iface_1_alt_0, 346399e6543SHans Petter Selasky &audio_iface_1_alt_1, 347399e6543SHans Petter Selasky &audio_iface_2_alt_0, 348399e6543SHans Petter Selasky &audio_iface_2_alt_1, 349399e6543SHans Petter Selasky NULL, 350399e6543SHans Petter Selasky }; 351399e6543SHans Petter Selasky 352399e6543SHans Petter Selasky static const struct usb_temp_config_desc audio_config_desc = { 353399e6543SHans Petter Selasky .ppIfaceDesc = audio_interfaces, 354399e6543SHans Petter Selasky .bmAttributes = UC_BUS_POWERED, 355399e6543SHans Petter Selasky .bMaxPower = 25, /* 50 mA */ 3568e06491aSEdward Tomasz Napierala .iConfiguration = AUDIO_PRODUCT_INDEX, 357399e6543SHans Petter Selasky }; 358399e6543SHans Petter Selasky 359399e6543SHans Petter Selasky static const struct usb_temp_config_desc *audio_configs[] = { 360399e6543SHans Petter Selasky &audio_config_desc, 361399e6543SHans Petter Selasky NULL, 362399e6543SHans Petter Selasky }; 363399e6543SHans Petter Selasky 364399e6543SHans Petter Selasky static usb_temp_get_string_desc_t audio_get_string_desc; 365399e6543SHans Petter Selasky 3668e06491aSEdward Tomasz Napierala struct usb_temp_device_desc usb_template_audio = { 367399e6543SHans Petter Selasky .getStringDesc = &audio_get_string_desc, 368399e6543SHans Petter Selasky .ppConfigDesc = audio_configs, 3691558eec6SEdward Tomasz Napierala .idVendor = AUDIO_DEFAULT_VENDOR_ID, 3701558eec6SEdward Tomasz Napierala .idProduct = AUDIO_DEFAULT_PRODUCT_ID, 371399e6543SHans Petter Selasky .bcdDevice = 0x0100, 372399e6543SHans Petter Selasky .bDeviceClass = UDCLASS_COMM, 373399e6543SHans Petter Selasky .bDeviceSubClass = 0, 374399e6543SHans Petter Selasky .bDeviceProtocol = 0, 3751ee5bed7SEdward Tomasz Napierala .iManufacturer = AUDIO_MANUFACTURER_INDEX, 3768e06491aSEdward Tomasz Napierala .iProduct = AUDIO_PRODUCT_INDEX, 3771ee5bed7SEdward Tomasz Napierala .iSerialNumber = AUDIO_SERIAL_NUMBER_INDEX, 378399e6543SHans Petter Selasky }; 379399e6543SHans Petter Selasky 380399e6543SHans Petter Selasky /*------------------------------------------------------------------------* 381399e6543SHans Petter Selasky * audio_get_string_desc 382399e6543SHans Petter Selasky * 383399e6543SHans Petter Selasky * Return values: 384399e6543SHans Petter Selasky * NULL: Failure. No such string. 385399e6543SHans Petter Selasky * Else: Success. Pointer to string descriptor is returned. 386399e6543SHans Petter Selasky *------------------------------------------------------------------------*/ 387399e6543SHans Petter Selasky static const void * 388399e6543SHans Petter Selasky audio_get_string_desc(uint16_t lang_id, uint8_t string_index) 389399e6543SHans Petter Selasky { 3908e06491aSEdward Tomasz Napierala static const void *ptr[AUDIO_MAX_INDEX] = { 3918e06491aSEdward Tomasz Napierala [AUDIO_LANG_INDEX] = &usb_string_lang_en, 3928e06491aSEdward Tomasz Napierala [AUDIO_MIXER_INDEX] = &audio_mixer, 3938e06491aSEdward Tomasz Napierala [AUDIO_RECORD_INDEX] = &audio_record, 3948e06491aSEdward Tomasz Napierala [AUDIO_PLAYBACK_INDEX] = &audio_playback, 3951ee5bed7SEdward Tomasz Napierala [AUDIO_MANUFACTURER_INDEX] = &audio_manufacturer, 3968e06491aSEdward Tomasz Napierala [AUDIO_PRODUCT_INDEX] = &audio_product, 3971ee5bed7SEdward Tomasz Napierala [AUDIO_SERIAL_NUMBER_INDEX] = &audio_serial_number, 398399e6543SHans Petter Selasky }; 399399e6543SHans Petter Selasky 400399e6543SHans Petter Selasky if (string_index == 0) { 40123ab0871SHans Petter Selasky return (&usb_string_lang_en); 402399e6543SHans Petter Selasky } 403399e6543SHans Petter Selasky if (lang_id != 0x0409) { 404399e6543SHans Petter Selasky return (NULL); 405399e6543SHans Petter Selasky } 4068e06491aSEdward Tomasz Napierala if (string_index < AUDIO_MAX_INDEX) { 407399e6543SHans Petter Selasky return (ptr[string_index]); 408399e6543SHans Petter Selasky } 409399e6543SHans Petter Selasky return (NULL); 410399e6543SHans Petter Selasky } 4118e06491aSEdward Tomasz Napierala 4128e06491aSEdward Tomasz Napierala static void 4138e06491aSEdward Tomasz Napierala audio_init(void *arg __unused) 4148e06491aSEdward Tomasz Napierala { 4158e06491aSEdward Tomasz Napierala struct sysctl_oid *parent; 4168e06491aSEdward Tomasz Napierala char parent_name[3]; 4178e06491aSEdward Tomasz Napierala 4188e06491aSEdward Tomasz Napierala usb_make_str_desc(&audio_mixer, sizeof(audio_mixer), 4198e06491aSEdward Tomasz Napierala AUDIO_DEFAULT_MIXER); 4208e06491aSEdward Tomasz Napierala usb_make_str_desc(&audio_record, sizeof(audio_record), 4218e06491aSEdward Tomasz Napierala AUDIO_DEFAULT_RECORD); 4228e06491aSEdward Tomasz Napierala usb_make_str_desc(&audio_playback, sizeof(audio_playback), 4238e06491aSEdward Tomasz Napierala AUDIO_DEFAULT_PLAYBACK); 4241ee5bed7SEdward Tomasz Napierala usb_make_str_desc(&audio_manufacturer, sizeof(audio_manufacturer), 4251ee5bed7SEdward Tomasz Napierala AUDIO_DEFAULT_MANUFACTURER); 4268e06491aSEdward Tomasz Napierala usb_make_str_desc(&audio_product, sizeof(audio_product), 4278e06491aSEdward Tomasz Napierala AUDIO_DEFAULT_PRODUCT); 4281ee5bed7SEdward Tomasz Napierala usb_make_str_desc(&audio_serial_number, sizeof(audio_serial_number), 4291ee5bed7SEdward Tomasz Napierala AUDIO_DEFAULT_SERIAL_NUMBER); 4308e06491aSEdward Tomasz Napierala 4318e06491aSEdward Tomasz Napierala snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_AUDIO); 4328e06491aSEdward Tomasz Napierala sysctl_ctx_init(&audio_ctx_list); 4338e06491aSEdward Tomasz Napierala 4348e06491aSEdward Tomasz Napierala parent = SYSCTL_ADD_NODE(&audio_ctx_list, 4358e06491aSEdward Tomasz Napierala SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO, 4368e06491aSEdward Tomasz Napierala parent_name, CTLFLAG_RW, 4378e06491aSEdward Tomasz Napierala 0, "USB Audio Interface device side template"); 4388e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4398e06491aSEdward Tomasz Napierala "vendor_id", CTLFLAG_RWTUN, &usb_template_audio.idVendor, 4408e06491aSEdward Tomasz Napierala 1, "Vendor identifier"); 4418e06491aSEdward Tomasz Napierala SYSCTL_ADD_U16(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4428e06491aSEdward Tomasz Napierala "product_id", CTLFLAG_RWTUN, &usb_template_audio.idProduct, 4438e06491aSEdward Tomasz Napierala 1, "Product identifier"); 4448e06491aSEdward Tomasz Napierala #if 0 4458e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4468e06491aSEdward Tomasz Napierala "mixer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4478e06491aSEdward Tomasz Napierala &audio_mixer, sizeof(audio_mixer), usb_temp_sysctl, 4488e06491aSEdward Tomasz Napierala "A", "Mixer interface string"); 4498e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4508e06491aSEdward Tomasz Napierala "record", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4518e06491aSEdward Tomasz Napierala &audio_record, sizeof(audio_record), usb_temp_sysctl, 4528e06491aSEdward Tomasz Napierala "A", "Record interface string"); 4538e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4548e06491aSEdward Tomasz Napierala "playback", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4558e06491aSEdward Tomasz Napierala &audio_playback, sizeof(audio_playback), usb_temp_sysctl, 4568e06491aSEdward Tomasz Napierala "A", "Playback interface string"); 4578e06491aSEdward Tomasz Napierala #endif 4588e06491aSEdward Tomasz Napierala SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4591ee5bed7SEdward Tomasz Napierala "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4601ee5bed7SEdward Tomasz Napierala &audio_manufacturer, sizeof(audio_manufacturer), usb_temp_sysctl, 4611ee5bed7SEdward Tomasz Napierala "A", "Manufacturer string"); 4621ee5bed7SEdward Tomasz Napierala SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4638e06491aSEdward Tomasz Napierala "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4648e06491aSEdward Tomasz Napierala &audio_product, sizeof(audio_product), usb_temp_sysctl, 4658e06491aSEdward Tomasz Napierala "A", "Product string"); 4661ee5bed7SEdward Tomasz Napierala SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 4671ee5bed7SEdward Tomasz Napierala "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 4681ee5bed7SEdward Tomasz Napierala &audio_serial_number, sizeof(audio_serial_number), usb_temp_sysctl, 4691ee5bed7SEdward Tomasz Napierala "A", "Serial number string"); 4708e06491aSEdward Tomasz Napierala } 4718e06491aSEdward Tomasz Napierala 4728e06491aSEdward Tomasz Napierala static void 4738e06491aSEdward Tomasz Napierala audio_uninit(void *arg __unused) 4748e06491aSEdward Tomasz Napierala { 4758e06491aSEdward Tomasz Napierala 4768e06491aSEdward Tomasz Napierala sysctl_ctx_free(&audio_ctx_list); 4778e06491aSEdward Tomasz Napierala } 4788e06491aSEdward Tomasz Napierala 4798e06491aSEdward Tomasz Napierala SYSINIT(audio_init, SI_SUB_LOCK, SI_ORDER_FIRST, audio_init, NULL); 480c70e38e4SHans Petter Selasky SYSUNINIT(audio_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, audio_uninit, NULL); 481