1 /* $FreeBSD$ */ 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> 56 #include <dev/usb/usb_cdc.h> 57 58 #include <dev/usb/template/usb_template.h> 59 #endif /* USB_GLOBAL_INCLUDE_FILE */ 60 61 enum { 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 70 #define STRING_AUDIO_PRODUCT \ 71 "A\0u\0d\0i\0o\0 \0T\0e\0s\0t\0 \0D\0e\0v\0i\0c\0e" 72 73 #define STRING_AUDIO_MIXER \ 74 "M\0i\0x\0e\0r\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 75 76 #define STRING_AUDIO_RECORD \ 77 "R\0e\0c\0o\0r\0d\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 78 79 #define STRING_AUDIO_PLAYBACK \ 80 "P\0l\0a\0y\0b\0a\0c\0k\0 \0i\0n\0t\0e\0r\0f\0a\0c\0e" 81 82 83 /* make the real string descriptors */ 84 85 USB_MAKE_STRING_DESC(STRING_AUDIO_MIXER, string_audio_mixer); 86 USB_MAKE_STRING_DESC(STRING_AUDIO_RECORD, string_audio_record); 87 USB_MAKE_STRING_DESC(STRING_AUDIO_PLAYBACK, string_audio_playback); 88 USB_MAKE_STRING_DESC(STRING_AUDIO_PRODUCT, string_audio_product); 89 90 /* prototypes */ 91 92 /* 93 * Audio Mixer description structures 94 * 95 * Some of the audio descriptors were dumped 96 * from a Creative Labs USB audio device. 97 */ 98 99 static const uint8_t audio_raw_desc_0[] = { 100 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02, 101 0x01, 0x02 102 }; 103 104 static const uint8_t audio_raw_desc_1[] = { 105 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 106 0x03, 0x00, 0x00, 0x00 107 }; 108 109 static const uint8_t audio_raw_desc_2[] = { 110 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 111 0x03, 0x00, 0x00, 0x00 112 }; 113 114 static const uint8_t audio_raw_desc_3[] = { 115 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02, 116 0x03, 0x00, 0x00, 0x00 117 }; 118 119 static const uint8_t audio_raw_desc_4[] = { 120 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02, 121 0x03, 0x00, 0x00, 0x00 122 }; 123 124 static const uint8_t audio_raw_desc_5[] = { 125 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01, 126 0x00 127 }; 128 129 static const uint8_t audio_raw_desc_6[] = { 130 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09, 131 0x00 132 }; 133 134 static const uint8_t audio_raw_desc_7[] = { 135 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08, 136 0x00 137 }; 138 139 static const uint8_t audio_raw_desc_8[] = { 140 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c, 141 0x00 142 }; 143 144 static const uint8_t audio_raw_desc_9[] = { 145 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02, 146 0x02, 0x00 147 }; 148 149 static const uint8_t audio_raw_desc_10[] = { 150 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00, 151 0x00, 0x00 152 }; 153 154 static const uint8_t audio_raw_desc_11[] = { 155 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02, 156 0x02, 0x00 157 }; 158 159 static const uint8_t audio_raw_desc_12[] = { 160 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00, 161 0x00, 0x00 162 }; 163 164 static const uint8_t audio_raw_desc_13[] = { 165 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00, 166 0x00, 0x00 167 }; 168 169 static const uint8_t audio_raw_desc_14[] = { 170 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02, 171 0x02, 0x00 172 }; 173 174 static const uint8_t audio_raw_desc_15[] = { 175 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e, 176 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 177 }; 178 179 static const void *audio_raw_iface_0_desc[] = { 180 audio_raw_desc_0, 181 audio_raw_desc_1, 182 audio_raw_desc_2, 183 audio_raw_desc_3, 184 audio_raw_desc_4, 185 audio_raw_desc_5, 186 audio_raw_desc_6, 187 audio_raw_desc_7, 188 audio_raw_desc_8, 189 audio_raw_desc_9, 190 audio_raw_desc_10, 191 audio_raw_desc_11, 192 audio_raw_desc_12, 193 audio_raw_desc_13, 194 audio_raw_desc_14, 195 audio_raw_desc_15, 196 NULL, 197 }; 198 199 static const struct usb_temp_interface_desc audio_iface_0 = { 200 .ppEndpoints = NULL, /* no endpoints */ 201 .ppRawDesc = audio_raw_iface_0_desc, 202 .bInterfaceClass = 1, 203 .bInterfaceSubClass = 1, 204 .bInterfaceProtocol = 0, 205 .iInterface = INDEX_AUDIO_MIXER, 206 }; 207 208 static const uint8_t audio_raw_desc_20[] = { 209 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00 210 211 }; 212 213 static const uint8_t audio_raw_desc_21[] = { 214 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 215 /* 48kHz */ 216 0x80, 0xbb, 0x00 217 }; 218 219 static const uint8_t audio_raw_desc_22[] = { 220 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00 221 }; 222 223 static const void *audio_raw_iface_1_desc[] = { 224 audio_raw_desc_20, 225 audio_raw_desc_21, 226 NULL, 227 }; 228 229 static const void *audio_raw_ep_1_desc[] = { 230 audio_raw_desc_22, 231 NULL, 232 }; 233 234 static const struct usb_temp_packet_size audio_isoc_mps = { 235 .mps[USB_SPEED_FULL] = 0xC8, 236 .mps[USB_SPEED_HIGH] = 0xC8, 237 }; 238 239 static const struct usb_temp_interval audio_isoc_interval = { 240 .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ 241 .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ 242 }; 243 244 static const struct usb_temp_endpoint_desc audio_isoc_out_ep = { 245 .ppRawDesc = audio_raw_ep_1_desc, 246 .pPacketSize = &audio_isoc_mps, 247 .pIntervals = &audio_isoc_interval, 248 .bEndpointAddress = UE_DIR_OUT, 249 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 250 }; 251 252 static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = { 253 &audio_isoc_out_ep, 254 NULL, 255 }; 256 257 static const struct usb_temp_interface_desc audio_iface_1_alt_0 = { 258 .ppEndpoints = NULL, /* no endpoints */ 259 .ppRawDesc = NULL, /* no raw descriptors */ 260 .bInterfaceClass = 1, 261 .bInterfaceSubClass = 2, 262 .bInterfaceProtocol = 0, 263 .iInterface = INDEX_AUDIO_PLAYBACK, 264 }; 265 266 static const struct usb_temp_interface_desc audio_iface_1_alt_1 = { 267 .ppEndpoints = audio_iface_1_ep, 268 .ppRawDesc = audio_raw_iface_1_desc, 269 .bInterfaceClass = 1, 270 .bInterfaceSubClass = 2, 271 .bInterfaceProtocol = 0, 272 .iInterface = INDEX_AUDIO_PLAYBACK, 273 .isAltInterface = 1, /* this is an alternate setting */ 274 }; 275 276 static const uint8_t audio_raw_desc_30[] = { 277 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00 278 279 }; 280 281 static const uint8_t audio_raw_desc_31[] = { 282 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 283 /* 48kHz */ 284 0x80, 0xbb, 0x00 285 }; 286 287 static const uint8_t audio_raw_desc_32[] = { 288 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00 289 }; 290 291 static const void *audio_raw_iface_2_desc[] = { 292 audio_raw_desc_30, 293 audio_raw_desc_31, 294 NULL, 295 }; 296 297 static const void *audio_raw_ep_2_desc[] = { 298 audio_raw_desc_32, 299 NULL, 300 }; 301 302 static const struct usb_temp_endpoint_desc audio_isoc_in_ep = { 303 .ppRawDesc = audio_raw_ep_2_desc, 304 .pPacketSize = &audio_isoc_mps, 305 .pIntervals = &audio_isoc_interval, 306 .bEndpointAddress = UE_DIR_IN, 307 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 308 }; 309 310 static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = { 311 &audio_isoc_in_ep, 312 NULL, 313 }; 314 315 static const struct usb_temp_interface_desc audio_iface_2_alt_0 = { 316 .ppEndpoints = NULL, /* no endpoints */ 317 .ppRawDesc = NULL, /* no raw descriptors */ 318 .bInterfaceClass = 1, 319 .bInterfaceSubClass = 2, 320 .bInterfaceProtocol = 0, 321 .iInterface = INDEX_AUDIO_RECORD, 322 }; 323 324 static const struct usb_temp_interface_desc audio_iface_2_alt_1 = { 325 .ppEndpoints = audio_iface_2_ep, 326 .ppRawDesc = audio_raw_iface_2_desc, 327 .bInterfaceClass = 1, 328 .bInterfaceSubClass = 2, 329 .bInterfaceProtocol = 0, 330 .iInterface = INDEX_AUDIO_RECORD, 331 .isAltInterface = 1, /* this is an alternate setting */ 332 }; 333 334 static const struct usb_temp_interface_desc *audio_interfaces[] = { 335 &audio_iface_0, 336 &audio_iface_1_alt_0, 337 &audio_iface_1_alt_1, 338 &audio_iface_2_alt_0, 339 &audio_iface_2_alt_1, 340 NULL, 341 }; 342 343 static const struct usb_temp_config_desc audio_config_desc = { 344 .ppIfaceDesc = audio_interfaces, 345 .bmAttributes = UC_BUS_POWERED, 346 .bMaxPower = 25, /* 50 mA */ 347 .iConfiguration = INDEX_AUDIO_PRODUCT, 348 }; 349 350 static const struct usb_temp_config_desc *audio_configs[] = { 351 &audio_config_desc, 352 NULL, 353 }; 354 355 static usb_temp_get_string_desc_t audio_get_string_desc; 356 357 const struct usb_temp_device_desc usb_template_audio = { 358 .getStringDesc = &audio_get_string_desc, 359 .ppConfigDesc = audio_configs, 360 .idVendor = USB_TEMPLATE_VENDOR, 361 .idProduct = 0x000A, 362 .bcdDevice = 0x0100, 363 .bDeviceClass = UDCLASS_COMM, 364 .bDeviceSubClass = 0, 365 .bDeviceProtocol = 0, 366 .iManufacturer = 0, 367 .iProduct = INDEX_AUDIO_PRODUCT, 368 .iSerialNumber = 0, 369 }; 370 371 /*------------------------------------------------------------------------* 372 * audio_get_string_desc 373 * 374 * Return values: 375 * NULL: Failure. No such string. 376 * Else: Success. Pointer to string descriptor is returned. 377 *------------------------------------------------------------------------*/ 378 static const void * 379 audio_get_string_desc(uint16_t lang_id, uint8_t string_index) 380 { 381 static const void *ptr[INDEX_AUDIO_MAX] = { 382 [INDEX_AUDIO_LANG] = &usb_string_lang_en, 383 [INDEX_AUDIO_MIXER] = &string_audio_mixer, 384 [INDEX_AUDIO_RECORD] = &string_audio_record, 385 [INDEX_AUDIO_PLAYBACK] = &string_audio_playback, 386 [INDEX_AUDIO_PRODUCT] = &string_audio_product, 387 }; 388 389 if (string_index == 0) { 390 return (&usb_string_lang_en); 391 } 392 if (lang_id != 0x0409) { 393 return (NULL); 394 } 395 if (string_index < INDEX_AUDIO_MAX) { 396 return (ptr[string_index]); 397 } 398 return (NULL); 399 } 400