1 /* $FreeBSD$ */ 2 /*- 3 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 4 * 5 * Copyright (c) 2010 Hans Petter Selasky 6 * Copyright (c) 2018 The FreeBSD Foundation 7 * All rights reserved. 8 * 9 * Portions of this software were developed by Edward Tomasz Napierala 10 * under sponsorship from the FreeBSD Foundation. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 /* 35 * This file contains the USB template for an USB Audio Device. 36 */ 37 38 #ifdef USB_GLOBAL_INCLUDE_FILE 39 #include USB_GLOBAL_INCLUDE_FILE 40 #else 41 #include <sys/stdint.h> 42 #include <sys/stddef.h> 43 #include <sys/param.h> 44 #include <sys/queue.h> 45 #include <sys/types.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/bus.h> 49 #include <sys/module.h> 50 #include <sys/lock.h> 51 #include <sys/mutex.h> 52 #include <sys/condvar.h> 53 #include <sys/sysctl.h> 54 #include <sys/sx.h> 55 #include <sys/unistd.h> 56 #include <sys/callout.h> 57 #include <sys/malloc.h> 58 #include <sys/priv.h> 59 60 #include <dev/usb/usb.h> 61 #include <dev/usb/usbdi.h> 62 #include <dev/usb/usb_core.h> 63 #include <dev/usb/usb_cdc.h> 64 #include <dev/usb/usb_ioctl.h> 65 #include <dev/usb/usb_util.h> 66 67 #include <dev/usb/template/usb_template.h> 68 #endif /* USB_GLOBAL_INCLUDE_FILE */ 69 70 enum { 71 AUDIO_LANG_INDEX, 72 AUDIO_MIXER_INDEX, 73 AUDIO_RECORD_INDEX, 74 AUDIO_PLAYBACK_INDEX, 75 AUDIO_MANUFACTURER_INDEX, 76 AUDIO_PRODUCT_INDEX, 77 AUDIO_SERIAL_NUMBER_INDEX, 78 AUDIO_MAX_INDEX, 79 }; 80 81 #define AUDIO_DEFAULT_VENDOR_ID USB_TEMPLATE_VENDOR 82 #define AUDIO_DEFAULT_PRODUCT_ID 0x27e0 83 #define AUDIO_DEFAULT_MIXER "Mixer interface" 84 #define AUDIO_DEFAULT_RECORD "Record interface" 85 #define AUDIO_DEFAULT_PLAYBACK "Playback interface" 86 #define AUDIO_DEFAULT_MANUFACTURER USB_TEMPLATE_MANUFACTURER 87 #define AUDIO_DEFAULT_PRODUCT "Audio Test Device" 88 #define AUDIO_DEFAULT_SERIAL_NUMBER "March 2008" 89 90 static struct usb_string_descriptor audio_mixer; 91 static struct usb_string_descriptor audio_record; 92 static struct usb_string_descriptor audio_playback; 93 static struct usb_string_descriptor audio_manufacturer; 94 static struct usb_string_descriptor audio_product; 95 static struct usb_string_descriptor audio_serial_number; 96 97 static struct sysctl_ctx_list audio_ctx_list; 98 99 /* prototypes */ 100 101 /* 102 * Audio Mixer description structures 103 * 104 * Some of the audio descriptors were dumped 105 * from a Creative Labs USB audio device. 106 */ 107 108 static const uint8_t audio_raw_desc_0[] = { 109 0x0a, 0x24, 0x01, 0x00, 0x01, 0xa9, 0x00, 0x02, 110 0x01, 0x02 111 }; 112 113 static const uint8_t audio_raw_desc_1[] = { 114 0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 115 0x03, 0x00, 0x00, 0x00 116 }; 117 118 static const uint8_t audio_raw_desc_2[] = { 119 0x0c, 0x24, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 120 0x03, 0x00, 0x00, 0x00 121 }; 122 123 static const uint8_t audio_raw_desc_3[] = { 124 0x0c, 0x24, 0x02, 0x03, 0x03, 0x06, 0x00, 0x02, 125 0x03, 0x00, 0x00, 0x00 126 }; 127 128 static const uint8_t audio_raw_desc_4[] = { 129 0x0c, 0x24, 0x02, 0x04, 0x05, 0x06, 0x00, 0x02, 130 0x03, 0x00, 0x00, 0x00 131 }; 132 133 static const uint8_t audio_raw_desc_5[] = { 134 0x09, 0x24, 0x03, 0x05, 0x05, 0x06, 0x00, 0x01, 135 0x00 136 }; 137 138 static const uint8_t audio_raw_desc_6[] = { 139 0x09, 0x24, 0x03, 0x06, 0x01, 0x03, 0x00, 0x09, 140 0x00 141 }; 142 143 static const uint8_t audio_raw_desc_7[] = { 144 0x09, 0x24, 0x03, 0x07, 0x01, 0x01, 0x00, 0x08, 145 0x00 146 }; 147 148 static const uint8_t audio_raw_desc_8[] = { 149 0x09, 0x24, 0x05, 0x08, 0x03, 0x0a, 0x0b, 0x0c, 150 0x00 151 }; 152 153 static const uint8_t audio_raw_desc_9[] = { 154 0x0a, 0x24, 0x06, 0x09, 0x0f, 0x01, 0x01, 0x02, 155 0x02, 0x00 156 }; 157 158 static const uint8_t audio_raw_desc_10[] = { 159 0x0a, 0x24, 0x06, 0x0a, 0x02, 0x01, 0x43, 0x00, 160 0x00, 0x00 161 }; 162 163 static const uint8_t audio_raw_desc_11[] = { 164 0x0a, 0x24, 0x06, 0x0b, 0x03, 0x01, 0x01, 0x02, 165 0x02, 0x00 166 }; 167 168 static const uint8_t audio_raw_desc_12[] = { 169 0x0a, 0x24, 0x06, 0x0c, 0x04, 0x01, 0x01, 0x00, 170 0x00, 0x00 171 }; 172 173 static const uint8_t audio_raw_desc_13[] = { 174 0x0a, 0x24, 0x06, 0x0d, 0x02, 0x01, 0x03, 0x00, 175 0x00, 0x00 176 }; 177 178 static const uint8_t audio_raw_desc_14[] = { 179 0x0a, 0x24, 0x06, 0x0e, 0x03, 0x01, 0x01, 0x02, 180 0x02, 0x00 181 }; 182 183 static const uint8_t audio_raw_desc_15[] = { 184 0x0f, 0x24, 0x04, 0x0f, 0x03, 0x01, 0x0d, 0x0e, 185 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 186 }; 187 188 static const void *audio_raw_iface_0_desc[] = { 189 audio_raw_desc_0, 190 audio_raw_desc_1, 191 audio_raw_desc_2, 192 audio_raw_desc_3, 193 audio_raw_desc_4, 194 audio_raw_desc_5, 195 audio_raw_desc_6, 196 audio_raw_desc_7, 197 audio_raw_desc_8, 198 audio_raw_desc_9, 199 audio_raw_desc_10, 200 audio_raw_desc_11, 201 audio_raw_desc_12, 202 audio_raw_desc_13, 203 audio_raw_desc_14, 204 audio_raw_desc_15, 205 NULL, 206 }; 207 208 static const struct usb_temp_interface_desc audio_iface_0 = { 209 .ppEndpoints = NULL, /* no endpoints */ 210 .ppRawDesc = audio_raw_iface_0_desc, 211 .bInterfaceClass = UICLASS_AUDIO, 212 .bInterfaceSubClass = UISUBCLASS_AUDIOCONTROL, 213 .bInterfaceProtocol = 0, 214 .iInterface = AUDIO_MIXER_INDEX, 215 }; 216 217 static const uint8_t audio_raw_desc_20[] = { 218 0x07, 0x24, 0x01, 0x01, 0x03, 0x01, 0x00 219 220 }; 221 222 static const uint8_t audio_raw_desc_21[] = { 223 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 224 /* 48kHz */ 225 0x80, 0xbb, 0x00 226 }; 227 228 static const uint8_t audio_raw_desc_22[] = { 229 0x07, 0x25, 0x01, 0x00, 0x01, 0x04, 0x00 230 }; 231 232 static const void *audio_raw_iface_1_desc[] = { 233 audio_raw_desc_20, 234 audio_raw_desc_21, 235 NULL, 236 }; 237 238 static const void *audio_raw_ep_1_desc[] = { 239 audio_raw_desc_22, 240 NULL, 241 }; 242 243 static const struct usb_temp_packet_size audio_isoc_mps = { 244 .mps[USB_SPEED_FULL] = 0xC8, 245 .mps[USB_SPEED_HIGH] = 0xC8, 246 }; 247 248 static const struct usb_temp_interval audio_isoc_interval = { 249 .bInterval[USB_SPEED_FULL] = 1, /* 1:1 */ 250 .bInterval[USB_SPEED_HIGH] = 4, /* 1:8 */ 251 }; 252 253 static const struct usb_temp_endpoint_desc audio_isoc_out_ep = { 254 .ppRawDesc = audio_raw_ep_1_desc, 255 .pPacketSize = &audio_isoc_mps, 256 .pIntervals = &audio_isoc_interval, 257 .bEndpointAddress = UE_DIR_OUT, 258 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 259 }; 260 261 static const struct usb_temp_endpoint_desc *audio_iface_1_ep[] = { 262 &audio_isoc_out_ep, 263 NULL, 264 }; 265 266 static const struct usb_temp_interface_desc audio_iface_1_alt_0 = { 267 .ppEndpoints = NULL, /* no endpoints */ 268 .ppRawDesc = NULL, /* no raw descriptors */ 269 .bInterfaceClass = UICLASS_AUDIO, 270 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 271 .bInterfaceProtocol = 0, 272 .iInterface = AUDIO_PLAYBACK_INDEX, 273 }; 274 275 static const struct usb_temp_interface_desc audio_iface_1_alt_1 = { 276 .ppEndpoints = audio_iface_1_ep, 277 .ppRawDesc = audio_raw_iface_1_desc, 278 .bInterfaceClass = UICLASS_AUDIO, 279 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 280 .bInterfaceProtocol = 0, 281 .iInterface = AUDIO_PLAYBACK_INDEX, 282 .isAltInterface = 1, /* this is an alternate setting */ 283 }; 284 285 static const uint8_t audio_raw_desc_30[] = { 286 0x07, 0x24, 0x01, 0x07, 0x01, 0x01, 0x00 287 288 }; 289 290 static const uint8_t audio_raw_desc_31[] = { 291 0x0b, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x01, 292 /* 48kHz */ 293 0x80, 0xbb, 0x00 294 }; 295 296 static const uint8_t audio_raw_desc_32[] = { 297 0x07, 0x25, 0x01, 0x01, 0x00, 0x00, 0x00 298 }; 299 300 static const void *audio_raw_iface_2_desc[] = { 301 audio_raw_desc_30, 302 audio_raw_desc_31, 303 NULL, 304 }; 305 306 static const void *audio_raw_ep_2_desc[] = { 307 audio_raw_desc_32, 308 NULL, 309 }; 310 311 static const struct usb_temp_endpoint_desc audio_isoc_in_ep = { 312 .ppRawDesc = audio_raw_ep_2_desc, 313 .pPacketSize = &audio_isoc_mps, 314 .pIntervals = &audio_isoc_interval, 315 .bEndpointAddress = UE_DIR_IN, 316 .bmAttributes = UE_ISOCHRONOUS | UE_ISO_ADAPT, 317 }; 318 319 static const struct usb_temp_endpoint_desc *audio_iface_2_ep[] = { 320 &audio_isoc_in_ep, 321 NULL, 322 }; 323 324 static const struct usb_temp_interface_desc audio_iface_2_alt_0 = { 325 .ppEndpoints = NULL, /* no endpoints */ 326 .ppRawDesc = NULL, /* no raw descriptors */ 327 .bInterfaceClass = UICLASS_AUDIO, 328 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 329 .bInterfaceProtocol = 0, 330 .iInterface = AUDIO_RECORD_INDEX, 331 }; 332 333 static const struct usb_temp_interface_desc audio_iface_2_alt_1 = { 334 .ppEndpoints = audio_iface_2_ep, 335 .ppRawDesc = audio_raw_iface_2_desc, 336 .bInterfaceClass = UICLASS_AUDIO, 337 .bInterfaceSubClass = UISUBCLASS_AUDIOSTREAM, 338 .bInterfaceProtocol = 0, 339 .iInterface = AUDIO_RECORD_INDEX, 340 .isAltInterface = 1, /* this is an alternate setting */ 341 }; 342 343 static const struct usb_temp_interface_desc *audio_interfaces[] = { 344 &audio_iface_0, 345 &audio_iface_1_alt_0, 346 &audio_iface_1_alt_1, 347 &audio_iface_2_alt_0, 348 &audio_iface_2_alt_1, 349 NULL, 350 }; 351 352 static const struct usb_temp_config_desc audio_config_desc = { 353 .ppIfaceDesc = audio_interfaces, 354 .bmAttributes = 0, 355 .bMaxPower = 0, 356 .iConfiguration = AUDIO_PRODUCT_INDEX, 357 }; 358 359 static const struct usb_temp_config_desc *audio_configs[] = { 360 &audio_config_desc, 361 NULL, 362 }; 363 364 static usb_temp_get_string_desc_t audio_get_string_desc; 365 366 struct usb_temp_device_desc usb_template_audio = { 367 .getStringDesc = &audio_get_string_desc, 368 .ppConfigDesc = audio_configs, 369 .idVendor = AUDIO_DEFAULT_VENDOR_ID, 370 .idProduct = AUDIO_DEFAULT_PRODUCT_ID, 371 .bcdDevice = 0x0100, 372 .bDeviceClass = UDCLASS_COMM, 373 .bDeviceSubClass = 0, 374 .bDeviceProtocol = 0, 375 .iManufacturer = AUDIO_MANUFACTURER_INDEX, 376 .iProduct = AUDIO_PRODUCT_INDEX, 377 .iSerialNumber = AUDIO_SERIAL_NUMBER_INDEX, 378 }; 379 380 /*------------------------------------------------------------------------* 381 * audio_get_string_desc 382 * 383 * Return values: 384 * NULL: Failure. No such string. 385 * Else: Success. Pointer to string descriptor is returned. 386 *------------------------------------------------------------------------*/ 387 static const void * 388 audio_get_string_desc(uint16_t lang_id, uint8_t string_index) 389 { 390 static const void *ptr[AUDIO_MAX_INDEX] = { 391 [AUDIO_LANG_INDEX] = &usb_string_lang_en, 392 [AUDIO_MIXER_INDEX] = &audio_mixer, 393 [AUDIO_RECORD_INDEX] = &audio_record, 394 [AUDIO_PLAYBACK_INDEX] = &audio_playback, 395 [AUDIO_MANUFACTURER_INDEX] = &audio_manufacturer, 396 [AUDIO_PRODUCT_INDEX] = &audio_product, 397 [AUDIO_SERIAL_NUMBER_INDEX] = &audio_serial_number, 398 }; 399 400 if (string_index == 0) { 401 return (&usb_string_lang_en); 402 } 403 if (lang_id != 0x0409) { 404 return (NULL); 405 } 406 if (string_index < AUDIO_MAX_INDEX) { 407 return (ptr[string_index]); 408 } 409 return (NULL); 410 } 411 412 static void 413 audio_init(void *arg __unused) 414 { 415 struct sysctl_oid *parent; 416 char parent_name[3]; 417 418 usb_make_str_desc(&audio_mixer, sizeof(audio_mixer), 419 AUDIO_DEFAULT_MIXER); 420 usb_make_str_desc(&audio_record, sizeof(audio_record), 421 AUDIO_DEFAULT_RECORD); 422 usb_make_str_desc(&audio_playback, sizeof(audio_playback), 423 AUDIO_DEFAULT_PLAYBACK); 424 usb_make_str_desc(&audio_manufacturer, sizeof(audio_manufacturer), 425 AUDIO_DEFAULT_MANUFACTURER); 426 usb_make_str_desc(&audio_product, sizeof(audio_product), 427 AUDIO_DEFAULT_PRODUCT); 428 usb_make_str_desc(&audio_serial_number, sizeof(audio_serial_number), 429 AUDIO_DEFAULT_SERIAL_NUMBER); 430 431 snprintf(parent_name, sizeof(parent_name), "%d", USB_TEMP_AUDIO); 432 sysctl_ctx_init(&audio_ctx_list); 433 434 parent = SYSCTL_ADD_NODE(&audio_ctx_list, 435 SYSCTL_STATIC_CHILDREN(_hw_usb_templates), OID_AUTO, 436 parent_name, CTLFLAG_RW | CTLFLAG_MPSAFE, 437 0, "USB Audio Interface device side template"); 438 SYSCTL_ADD_U16(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 439 "vendor_id", CTLFLAG_RWTUN, &usb_template_audio.idVendor, 440 1, "Vendor identifier"); 441 SYSCTL_ADD_U16(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 442 "product_id", CTLFLAG_RWTUN, &usb_template_audio.idProduct, 443 1, "Product identifier"); 444 #if 0 445 SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 446 "mixer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 447 &audio_mixer, sizeof(audio_mixer), usb_temp_sysctl, 448 "A", "Mixer interface string"); 449 SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 450 "record", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 451 &audio_record, sizeof(audio_record), usb_temp_sysctl, 452 "A", "Record interface string"); 453 SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 454 "playback", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 455 &audio_playback, sizeof(audio_playback), usb_temp_sysctl, 456 "A", "Playback interface string"); 457 #endif 458 SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 459 "manufacturer", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 460 &audio_manufacturer, sizeof(audio_manufacturer), usb_temp_sysctl, 461 "A", "Manufacturer string"); 462 SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 463 "product", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 464 &audio_product, sizeof(audio_product), usb_temp_sysctl, 465 "A", "Product string"); 466 SYSCTL_ADD_PROC(&audio_ctx_list, SYSCTL_CHILDREN(parent), OID_AUTO, 467 "serial_number", CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 468 &audio_serial_number, sizeof(audio_serial_number), usb_temp_sysctl, 469 "A", "Serial number string"); 470 } 471 472 static void 473 audio_uninit(void *arg __unused) 474 { 475 476 sysctl_ctx_free(&audio_ctx_list); 477 } 478 479 SYSINIT(audio_init, SI_SUB_LOCK, SI_ORDER_FIRST, audio_init, NULL); 480 SYSUNINIT(audio_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, audio_uninit, NULL); 481