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