1 /* $NetBSD: uaudio.c,v 1.74 2004/07/09 02:57:48 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Lennart Augustsson (lennart@augustsson.net) at 9 * Carlstedt Research & Technology. 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * USB audio specs: http://www.usb.org/developers/devclass_docs/audio10.pdf 42 * http://www.usb.org/developers/devclass_docs/frmts10.pdf 43 * http://www.usb.org/developers/devclass_docs/termt10.pdf 44 */ 45 46 #include <sys/cdefs.h> 47 __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.74 2004/07/09 02:57:48 mycroft Exp $"); 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/kernel.h> 52 #include <sys/malloc.h> 53 #include <sys/device.h> 54 #include <sys/ioctl.h> 55 #include <sys/tty.h> 56 #include <sys/file.h> 57 #include <sys/reboot.h> /* for bootverbose */ 58 #include <sys/select.h> 59 #include <sys/proc.h> 60 #include <sys/vnode.h> 61 #include <sys/device.h> 62 #include <sys/poll.h> 63 64 #include <sys/audioio.h> 65 #include <dev/audio_if.h> 66 #include <dev/mulaw.h> 67 #include <dev/auconv.h> 68 69 #include <dev/usb/usb.h> 70 #include <dev/usb/usbdi.h> 71 #include <dev/usb/usbdi_util.h> 72 #include <dev/usb/usb_quirks.h> 73 74 #include <dev/usb/uaudioreg.h> 75 76 #ifdef UAUDIO_DEBUG 77 #define DPRINTF(x) if (uaudiodebug) logprintf x 78 #define DPRINTFN(n,x) if (uaudiodebug>(n)) logprintf x 79 int uaudiodebug = 0; 80 #else 81 #define DPRINTF(x) 82 #define DPRINTFN(n,x) 83 #endif 84 85 #define UAUDIO_NCHANBUFS 6 /* number of outstanding request */ 86 #define UAUDIO_NFRAMES 10 /* ms of sound in each request */ 87 88 89 #define MIX_MAX_CHAN 8 90 struct mixerctl { 91 u_int16_t wValue[MIX_MAX_CHAN]; /* using nchan */ 92 u_int16_t wIndex; 93 u_int8_t nchan; 94 u_int8_t type; 95 #define MIX_ON_OFF 1 96 #define MIX_SIGNED_16 2 97 #define MIX_UNSIGNED_16 3 98 #define MIX_SIGNED_8 4 99 #define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1) 100 #define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16) 101 int minval, maxval; 102 u_int delta; 103 u_int mul; 104 u_int8_t class; 105 char ctlname[MAX_AUDIO_DEV_LEN]; 106 char *ctlunit; 107 }; 108 #define MAKE(h,l) (((h) << 8) | (l)) 109 110 struct as_info { 111 u_int8_t alt; 112 u_int8_t encoding; 113 u_int8_t attributes; /* Copy of bmAttributes of 114 * usb_audio_streaming_endpoint_descriptor 115 */ 116 usbd_interface_handle ifaceh; 117 usb_interface_descriptor_t *idesc; 118 usb_endpoint_descriptor_audio_t *edesc; 119 struct usb_audio_streaming_type1_descriptor *asf1desc; 120 int sc_busy; /* currently used */ 121 }; 122 123 struct chan { 124 void (*intr)(void *); /* DMA completion intr handler */ 125 void *arg; /* arg for intr() */ 126 usbd_pipe_handle pipe; 127 128 u_int sample_size; 129 u_int sample_rate; 130 u_int bytes_per_frame; 131 u_int fraction; /* fraction/1000 is the extra samples/frame */ 132 u_int residue; /* accumulates the fractional samples */ 133 134 u_char *start; /* upper layer buffer start */ 135 u_char *end; /* upper layer buffer end */ 136 u_char *cur; /* current position in upper layer buffer */ 137 int blksize; /* chunk size to report up */ 138 int transferred; /* transferred bytes not reported up */ 139 140 int altidx; /* currently used altidx */ 141 142 int curchanbuf; 143 struct chanbuf { 144 struct chan *chan; 145 usbd_xfer_handle xfer; 146 u_char *buffer; 147 u_int16_t sizes[UAUDIO_NFRAMES]; 148 u_int16_t offsets[UAUDIO_NFRAMES]; 149 u_int16_t size; 150 } chanbufs[UAUDIO_NCHANBUFS]; 151 152 struct uaudio_softc *sc; /* our softc */ 153 }; 154 155 struct uaudio_softc { 156 USBBASEDEVICE sc_dev; /* base device */ 157 usbd_device_handle sc_udev; /* USB device */ 158 159 int sc_ac_iface; /* Audio Control interface */ 160 usbd_interface_handle sc_ac_ifaceh; 161 162 struct chan sc_playchan; /* play channel */ 163 struct chan sc_recchan; /* record channel */ 164 165 int sc_nullalt; 166 167 int sc_audio_rev; 168 169 struct as_info *sc_alts; 170 int sc_nalts; 171 172 int sc_altflags; 173 #define HAS_8 0x01 174 #define HAS_16 0x02 175 #define HAS_8U 0x04 176 #define HAS_ALAW 0x08 177 #define HAS_MULAW 0x10 178 #define UA_NOFRAC 0x20 /* don't do sample rate adjustment */ 179 #define HAS_24 0x40 180 181 int sc_mode; /* play/record capability */ 182 183 struct mixerctl *sc_ctls; 184 int sc_nctls; 185 186 device_ptr_t sc_audiodev; 187 char sc_dying; 188 }; 189 190 #define UAC_OUTPUT 0 191 #define UAC_INPUT 1 192 #define UAC_EQUAL 2 193 #define UAC_NCLASSES 3 194 195 Static usbd_status uaudio_identify_ac(struct uaudio_softc *sc, 196 usb_config_descriptor_t *cdesc); 197 Static usbd_status uaudio_identify_as(struct uaudio_softc *sc, 198 usb_config_descriptor_t *cdesc); 199 Static usbd_status uaudio_process_as(struct uaudio_softc *sc, 200 char *buf, int *offsp, int size, 201 usb_interface_descriptor_t *id); 202 203 Static void uaudio_add_alt(struct uaudio_softc *sc, 204 struct as_info *ai); 205 Static void uaudio_mixer_alias_ctl(struct uaudio_softc *sc, 206 struct mixerctl *mp, const char *ctl); 207 208 Static usb_interface_descriptor_t *uaudio_find_iface(char *buf, 209 int size, int *offsp, int subtype); 210 211 Static void uaudio_mixer_add_ctl(struct uaudio_softc *sc, 212 struct mixerctl *mp); 213 Static char *uaudio_id_name(struct uaudio_softc *sc, 214 usb_descriptor_t **dps, int id); 215 Static struct usb_audio_cluster uaudio_get_cluster(int id, 216 usb_descriptor_t **dps); 217 Static void uaudio_add_input(struct uaudio_softc *sc, 218 usb_descriptor_t *v, usb_descriptor_t **dps); 219 Static void uaudio_add_output(struct uaudio_softc *sc, 220 usb_descriptor_t *v, usb_descriptor_t **dps); 221 Static void uaudio_add_mixer(struct uaudio_softc *sc, 222 usb_descriptor_t *v, usb_descriptor_t **dps); 223 Static void uaudio_add_selector(struct uaudio_softc *sc, 224 usb_descriptor_t *v, usb_descriptor_t **dps); 225 Static void uaudio_add_feature(struct uaudio_softc *sc, 226 usb_descriptor_t *v, usb_descriptor_t **dps); 227 Static void uaudio_add_processing_updown(struct uaudio_softc *sc, 228 usb_descriptor_t *v, usb_descriptor_t **dps); 229 Static void uaudio_add_processing(struct uaudio_softc *sc, 230 usb_descriptor_t *v, usb_descriptor_t **dps); 231 Static void uaudio_add_extension(struct uaudio_softc *sc, 232 usb_descriptor_t *v, usb_descriptor_t **dps); 233 Static usbd_status uaudio_identify(struct uaudio_softc *sc, 234 usb_config_descriptor_t *cdesc); 235 236 Static int uaudio_signext(int type, int val); 237 Static int uaudio_value2bsd(struct mixerctl *mc, int val); 238 Static int uaudio_bsd2value(struct mixerctl *mc, int val); 239 Static int uaudio_get(struct uaudio_softc *sc, int type, 240 int which, int wValue, int wIndex, int len); 241 Static int uaudio_ctl_get(struct uaudio_softc *sc, int which, 242 struct mixerctl *mc, int chan); 243 Static void uaudio_set(struct uaudio_softc *sc, int type, 244 int which, int wValue, int wIndex, int l, int v); 245 Static void uaudio_ctl_set(struct uaudio_softc *sc, int which, 246 struct mixerctl *mc, int chan, int val); 247 248 Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, u_int); 249 250 Static usbd_status uaudio_chan_open(struct uaudio_softc *sc, 251 struct chan *ch); 252 Static void uaudio_chan_close(struct uaudio_softc *sc, 253 struct chan *ch); 254 Static usbd_status uaudio_chan_alloc_buffers(struct uaudio_softc *, 255 struct chan *); 256 Static void uaudio_chan_free_buffers(struct uaudio_softc *, 257 struct chan *); 258 Static void uaudio_chan_init(struct chan *, int, 259 const struct audio_params *, int); 260 Static void uaudio_chan_set_param(struct chan *ch, u_char *start, 261 u_char *end, int blksize); 262 Static void uaudio_chan_ptransfer(struct chan *ch); 263 Static void uaudio_chan_pintr(usbd_xfer_handle xfer, 264 usbd_private_handle priv, usbd_status status); 265 266 Static void uaudio_chan_rtransfer(struct chan *ch); 267 Static void uaudio_chan_rintr(usbd_xfer_handle xfer, 268 usbd_private_handle priv, usbd_status status); 269 270 Static int uaudio_open(void *, int); 271 Static void uaudio_close(void *); 272 Static int uaudio_drain(void *); 273 Static int uaudio_query_encoding(void *, struct audio_encoding *); 274 Static void uaudio_get_minmax_rates(int, const struct as_info *, 275 const struct audio_params *, 276 int, u_long *, u_long *); 277 Static int uaudio_match_alt_sub(int, const struct as_info *, 278 const struct audio_params *, 279 int, u_long); 280 Static int uaudio_match_alt_chan(int, const struct as_info *, 281 struct audio_params *, int); 282 Static int uaudio_match_alt(int, const struct as_info *, 283 struct audio_params *, int); 284 Static int uaudio_set_params(void *, int, int, 285 struct audio_params *, struct audio_params *); 286 Static int uaudio_round_blocksize(void *, int); 287 Static int uaudio_trigger_output(void *, void *, void *, 288 int, void (*)(void *), void *, 289 struct audio_params *); 290 Static int uaudio_trigger_input (void *, void *, void *, 291 int, void (*)(void *), void *, 292 struct audio_params *); 293 Static int uaudio_halt_in_dma(void *); 294 Static int uaudio_halt_out_dma(void *); 295 Static int uaudio_getdev(void *, struct audio_device *); 296 Static int uaudio_mixer_set_port(void *, mixer_ctrl_t *); 297 Static int uaudio_mixer_get_port(void *, mixer_ctrl_t *); 298 Static int uaudio_query_devinfo(void *, mixer_devinfo_t *); 299 Static int uaudio_get_props(void *); 300 301 Static struct audio_hw_if uaudio_hw_if = { 302 uaudio_open, 303 uaudio_close, 304 uaudio_drain, 305 uaudio_query_encoding, 306 uaudio_set_params, 307 uaudio_round_blocksize, 308 NULL, 309 NULL, 310 NULL, 311 NULL, 312 NULL, 313 uaudio_halt_out_dma, 314 uaudio_halt_in_dma, 315 NULL, 316 uaudio_getdev, 317 NULL, 318 uaudio_mixer_set_port, 319 uaudio_mixer_get_port, 320 uaudio_query_devinfo, 321 NULL, 322 NULL, 323 NULL, 324 NULL, 325 uaudio_get_props, 326 uaudio_trigger_output, 327 uaudio_trigger_input, 328 NULL, 329 }; 330 331 Static struct audio_device uaudio_device = { 332 "USB audio", 333 "", 334 "uaudio" 335 }; 336 337 USB_DECLARE_DRIVER(uaudio); 338 339 USB_MATCH(uaudio) 340 { 341 USB_MATCH_START(uaudio, uaa); 342 usb_interface_descriptor_t *id; 343 344 if (uaa->iface == NULL) 345 return (UMATCH_NONE); 346 347 id = usbd_get_interface_descriptor(uaa->iface); 348 /* Trigger on the control interface. */ 349 if (id == NULL || 350 id->bInterfaceClass != UICLASS_AUDIO || 351 id->bInterfaceSubClass != UISUBCLASS_AUDIOCONTROL || 352 (usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO)) 353 return (UMATCH_NONE); 354 355 return (UMATCH_IFACECLASS_IFACESUBCLASS); 356 } 357 358 USB_ATTACH(uaudio) 359 { 360 USB_ATTACH_START(uaudio, sc, uaa); 361 usb_interface_descriptor_t *id; 362 usb_config_descriptor_t *cdesc; 363 char devinfo[1024]; 364 usbd_status err; 365 int i, j, found; 366 367 usbd_devinfo(uaa->device, 0, devinfo, sizeof(devinfo)); 368 printf(": %s\n", devinfo); 369 370 sc->sc_udev = uaa->device; 371 372 cdesc = usbd_get_config_descriptor(sc->sc_udev); 373 if (cdesc == NULL) { 374 printf("%s: failed to get configuration descriptor\n", 375 USBDEVNAME(sc->sc_dev)); 376 USB_ATTACH_ERROR_RETURN; 377 } 378 379 err = uaudio_identify(sc, cdesc); 380 if (err) { 381 printf("%s: audio descriptors make no sense, error=%d\n", 382 USBDEVNAME(sc->sc_dev), err); 383 USB_ATTACH_ERROR_RETURN; 384 } 385 386 sc->sc_ac_ifaceh = uaa->iface; 387 /* Pick up the AS interface. */ 388 for (i = 0; i < uaa->nifaces; i++) { 389 if (uaa->ifaces[i] == NULL) 390 continue; 391 id = usbd_get_interface_descriptor(uaa->ifaces[i]); 392 if (id == NULL) 393 continue; 394 found = 0; 395 for (j = 0; j < sc->sc_nalts; j++) { 396 if (id->bInterfaceNumber == 397 sc->sc_alts[j].idesc->bInterfaceNumber) { 398 sc->sc_alts[j].ifaceh = uaa->ifaces[i]; 399 found = 1; 400 } 401 } 402 if (found) 403 uaa->ifaces[i] = NULL; 404 } 405 406 for (j = 0; j < sc->sc_nalts; j++) { 407 if (sc->sc_alts[j].ifaceh == NULL) { 408 printf("%s: alt %d missing AS interface(s)\n", 409 USBDEVNAME(sc->sc_dev), j); 410 USB_ATTACH_ERROR_RETURN; 411 } 412 } 413 414 printf("%s: audio rev %d.%02x\n", USBDEVNAME(sc->sc_dev), 415 sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff); 416 417 sc->sc_playchan.sc = sc->sc_recchan.sc = sc; 418 sc->sc_playchan.altidx = -1; 419 sc->sc_recchan.altidx = -1; 420 421 if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC) 422 sc->sc_altflags |= UA_NOFRAC; 423 424 #ifndef UAUDIO_DEBUG 425 if (bootverbose) 426 #endif 427 printf("%s: %d mixer controls\n", USBDEVNAME(sc->sc_dev), 428 sc->sc_nctls); 429 430 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 431 USBDEV(sc->sc_dev)); 432 433 DPRINTF(("uaudio_attach: doing audio_attach_mi\n")); 434 #if defined(__OpenBSD__) 435 audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev); 436 #else 437 sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, &sc->sc_dev); 438 #endif 439 440 USB_ATTACH_SUCCESS_RETURN; 441 } 442 443 int 444 uaudio_activate(device_ptr_t self, enum devact act) 445 { 446 struct uaudio_softc *sc = (struct uaudio_softc *)self; 447 int rv = 0; 448 449 switch (act) { 450 case DVACT_ACTIVATE: 451 return (EOPNOTSUPP); 452 break; 453 454 case DVACT_DEACTIVATE: 455 if (sc->sc_audiodev != NULL) 456 rv = config_deactivate(sc->sc_audiodev); 457 sc->sc_dying = 1; 458 break; 459 } 460 return (rv); 461 } 462 463 int 464 uaudio_detach(device_ptr_t self, int flags) 465 { 466 struct uaudio_softc *sc = (struct uaudio_softc *)self; 467 int rv = 0; 468 469 /* Wait for outstanding requests to complete. */ 470 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES); 471 472 if (sc->sc_audiodev != NULL) 473 rv = config_detach(sc->sc_audiodev, flags); 474 475 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 476 USBDEV(sc->sc_dev)); 477 478 return (rv); 479 } 480 481 int 482 uaudio_query_encoding(void *addr, struct audio_encoding *fp) 483 { 484 struct uaudio_softc *sc = addr; 485 int flags = sc->sc_altflags; 486 int idx; 487 488 if (sc->sc_dying) 489 return (EIO); 490 491 if (sc->sc_nalts == 0 || flags == 0) 492 return (ENXIO); 493 494 idx = fp->index; 495 switch (idx) { 496 case 0: 497 strlcpy(fp->name, AudioEulinear, sizeof(fp->name)); 498 fp->encoding = AUDIO_ENCODING_ULINEAR; 499 fp->precision = 8; 500 fp->flags = flags&HAS_8U ? 0 : AUDIO_ENCODINGFLAG_EMULATED; 501 return (0); 502 case 1: 503 strlcpy(fp->name, AudioEmulaw, sizeof(fp->name)); 504 fp->encoding = AUDIO_ENCODING_ULAW; 505 fp->precision = 8; 506 fp->flags = flags&HAS_MULAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED; 507 return (0); 508 case 2: 509 strlcpy(fp->name, AudioEalaw, sizeof(fp->name)); 510 fp->encoding = AUDIO_ENCODING_ALAW; 511 fp->precision = 8; 512 fp->flags = flags&HAS_ALAW ? 0 : AUDIO_ENCODINGFLAG_EMULATED; 513 return (0); 514 case 3: 515 strlcpy(fp->name, AudioEslinear, sizeof(fp->name)); 516 fp->encoding = AUDIO_ENCODING_SLINEAR; 517 fp->precision = 8; 518 fp->flags = flags&HAS_8 ? 0 : AUDIO_ENCODINGFLAG_EMULATED; 519 return (0); 520 case 4: 521 strlcpy(fp->name, AudioEslinear_le, sizeof(fp->name)); 522 fp->encoding = AUDIO_ENCODING_SLINEAR_LE; 523 fp->precision = 16; 524 fp->flags = 0; 525 return (0); 526 case 5: 527 strlcpy(fp->name, AudioEulinear_le, sizeof(fp->name)); 528 fp->encoding = AUDIO_ENCODING_ULINEAR_LE; 529 fp->precision = 16; 530 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 531 return (0); 532 case 6: 533 strlcpy(fp->name, AudioEslinear_be, sizeof(fp->name)); 534 fp->encoding = AUDIO_ENCODING_SLINEAR_BE; 535 fp->precision = 16; 536 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 537 return (0); 538 case 7: 539 strlcpy(fp->name, AudioEulinear_be, sizeof(fp->name)); 540 fp->encoding = AUDIO_ENCODING_ULINEAR_BE; 541 fp->precision = 16; 542 fp->flags = AUDIO_ENCODINGFLAG_EMULATED; 543 return (0); 544 default: 545 return (EINVAL); 546 } 547 } 548 549 usb_interface_descriptor_t * 550 uaudio_find_iface(char *buf, int size, int *offsp, int subtype) 551 { 552 usb_interface_descriptor_t *d; 553 554 while (*offsp < size) { 555 d = (void *)(buf + *offsp); 556 *offsp += d->bLength; 557 if (d->bDescriptorType == UDESC_INTERFACE && 558 d->bInterfaceClass == UICLASS_AUDIO && 559 d->bInterfaceSubClass == subtype) 560 return (d); 561 } 562 return (NULL); 563 } 564 565 void 566 uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc) 567 { 568 int res; 569 size_t len = sizeof(*mc) * (sc->sc_nctls + 1); 570 struct mixerctl *nmc = sc->sc_nctls == 0 ? 571 malloc(len, M_USBDEV, M_NOWAIT) : 572 realloc(sc->sc_ctls, len, M_USBDEV, M_NOWAIT); 573 574 if (nmc == NULL) { 575 printf("uaudio_mixer_add_ctl: no memory\n"); 576 return; 577 } 578 sc->sc_ctls = nmc; 579 580 mc->delta = 0; 581 if (mc->type != MIX_ON_OFF) { 582 /* Determine min and max values. */ 583 mc->minval = uaudio_signext(mc->type, 584 uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE, 585 mc->wValue[0], mc->wIndex, 586 MIX_SIZE(mc->type))); 587 mc->maxval = 1 + uaudio_signext(mc->type, 588 uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE, 589 mc->wValue[0], mc->wIndex, 590 MIX_SIZE(mc->type))); 591 mc->mul = mc->maxval - mc->minval; 592 if (mc->mul == 0) 593 mc->mul = 1; 594 res = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE, 595 mc->wValue[0], mc->wIndex, 596 MIX_SIZE(mc->type)); 597 if (res > 0) 598 mc->delta = (res * 255 + mc->mul/2) / mc->mul; 599 } else { 600 mc->minval = 0; 601 mc->maxval = 1; 602 } 603 604 sc->sc_ctls[sc->sc_nctls++] = *mc; 605 606 #ifdef UAUDIO_DEBUG 607 if (uaudiodebug > 2) { 608 int i; 609 DPRINTF(("uaudio_mixer_add_ctl: wValue=%04x",mc->wValue[0])); 610 for (i = 1; i < mc->nchan; i++) 611 DPRINTF((",%04x", mc->wValue[i])); 612 DPRINTF((" wIndex=%04x type=%d name='%s' unit='%s' " 613 "min=%d max=%d\n", 614 mc->wIndex, mc->type, mc->ctlname, mc->ctlunit, 615 mc->minval, mc->maxval)); 616 } 617 #endif 618 } 619 620 void 621 uaudio_mixer_alias_ctl(struct uaudio_softc *sc, struct mixerctl *mc, 622 const char *name) 623 { 624 /* XXX mark as alias? */ 625 strlcpy(mc->ctlname, name, sizeof(mc->ctlname)); 626 uaudio_mixer_add_ctl(sc, mc); 627 } 628 629 char * 630 uaudio_id_name(struct uaudio_softc *sc, usb_descriptor_t **dps, int id) 631 { 632 static char buf[32]; 633 snprintf(buf, sizeof(buf), "i%d", id); 634 return (buf); 635 } 636 637 struct usb_audio_cluster 638 uaudio_get_cluster(int id, usb_descriptor_t **dps) 639 { 640 struct usb_audio_cluster r; 641 usb_descriptor_t *dp; 642 int i; 643 644 for (i = 0; i < 25; i++) { /* avoid infinite loops */ 645 dp = dps[id]; 646 if (dp == 0) 647 goto bad; 648 switch (dp->bDescriptorSubtype) { 649 case UDESCSUB_AC_INPUT: 650 #define p ((struct usb_audio_input_terminal *)dp) 651 r.bNrChannels = p->bNrChannels; 652 USETW(r.wChannelConfig, UGETW(p->wChannelConfig)); 653 r.iChannelNames = p->iChannelNames; 654 #undef p 655 return (r); 656 case UDESCSUB_AC_OUTPUT: 657 #define p ((struct usb_audio_output_terminal *)dp) 658 id = p->bSourceId; 659 #undef p 660 break; 661 case UDESCSUB_AC_MIXER: 662 #define p ((struct usb_audio_mixer_unit *)dp) 663 r = *(struct usb_audio_cluster *) 664 &p->baSourceId[p->bNrInPins]; 665 #undef p 666 return (r); 667 case UDESCSUB_AC_SELECTOR: 668 /* XXX This is not really right */ 669 #define p ((struct usb_audio_selector_unit *)dp) 670 id = p->baSourceId[0]; 671 #undef p 672 break; 673 case UDESCSUB_AC_FEATURE: 674 #define p ((struct usb_audio_feature_unit *)dp) 675 id = p->bSourceId; 676 #undef p 677 break; 678 case UDESCSUB_AC_PROCESSING: 679 #define p ((struct usb_audio_processing_unit *)dp) 680 r = *(struct usb_audio_cluster *) 681 &p->baSourceId[p->bNrInPins]; 682 #undef p 683 return (r); 684 case UDESCSUB_AC_EXTENSION: 685 #define p ((struct usb_audio_extension_unit *)dp) 686 r = *(struct usb_audio_cluster *) 687 &p->baSourceId[p->bNrInPins]; 688 #undef p 689 return (r); 690 default: 691 goto bad; 692 } 693 } 694 bad: 695 printf("uaudio_get_cluster: bad data\n"); 696 memset(&r, 0, sizeof r); 697 return (r); 698 699 } 700 701 void 702 uaudio_add_input(struct uaudio_softc *sc, usb_descriptor_t *v, 703 usb_descriptor_t **dps) 704 { 705 #ifdef UAUDIO_DEBUG 706 struct usb_audio_input_terminal *d = 707 (struct usb_audio_input_terminal *)v; 708 709 DPRINTFN(2,("uaudio_add_input: bTerminalId=%d wTerminalType=0x%04x " 710 "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d " 711 "iChannelNames=%d iTerminal=%d\n", 712 d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal, 713 d->bNrChannels, UGETW(d->wChannelConfig), 714 d->iChannelNames, d->iTerminal)); 715 #endif 716 } 717 718 void 719 uaudio_add_output(struct uaudio_softc *sc, usb_descriptor_t *v, 720 usb_descriptor_t **dps) 721 { 722 #ifdef UAUDIO_DEBUG 723 struct usb_audio_output_terminal *d = 724 (struct usb_audio_output_terminal *)v; 725 726 DPRINTFN(2,("uaudio_add_output: bTerminalId=%d wTerminalType=0x%04x " 727 "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n", 728 d->bTerminalId, UGETW(d->wTerminalType), d->bAssocTerminal, 729 d->bSourceId, d->iTerminal)); 730 #endif 731 } 732 733 void 734 uaudio_add_mixer(struct uaudio_softc *sc, usb_descriptor_t *v, 735 usb_descriptor_t **dps) 736 { 737 struct usb_audio_mixer_unit *d = (struct usb_audio_mixer_unit *)v; 738 struct usb_audio_mixer_unit_1 *d1; 739 int c, chs, ichs, ochs, i, o, bno, p, mo, mc, k; 740 uByte *bm; 741 struct mixerctl mix; 742 743 DPRINTFN(2,("uaudio_add_mixer: bUnitId=%d bNrInPins=%d\n", 744 d->bUnitId, d->bNrInPins)); 745 746 /* Compute the number of input channels */ 747 ichs = 0; 748 for (i = 0; i < d->bNrInPins; i++) 749 ichs += uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels; 750 751 /* and the number of output channels */ 752 d1 = (struct usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins]; 753 ochs = d1->bNrChannels; 754 DPRINTFN(2,("uaudio_add_mixer: ichs=%d ochs=%d\n", ichs, ochs)); 755 756 bm = d1->bmControls; 757 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 758 mix.class = -1; 759 mix.type = MIX_SIGNED_16; 760 mix.ctlunit = AudioNvolume; 761 #define BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1) 762 for (p = i = 0; i < d->bNrInPins; i++) { 763 chs = uaudio_get_cluster(d->baSourceId[i], dps).bNrChannels; 764 mc = 0; 765 for (c = 0; c < chs; c++) { 766 mo = 0; 767 for (o = 0; o < ochs; o++) { 768 bno = (p + c) * ochs + o; 769 if (BIT(bno)) 770 mo++; 771 } 772 if (mo == 1) 773 mc++; 774 } 775 if (mc == chs && chs <= MIX_MAX_CHAN) { 776 k = 0; 777 for (c = 0; c < chs; c++) 778 for (o = 0; o < ochs; o++) { 779 bno = (p + c) * ochs + o; 780 if (BIT(bno)) 781 mix.wValue[k++] = 782 MAKE(p+c+1, o+1); 783 } 784 snprintf(mix.ctlname, sizeof(mix.ctlname), "mix%d-%s", 785 d->bUnitId, uaudio_id_name(sc, dps, 786 d->baSourceId[i])); 787 mix.nchan = chs; 788 uaudio_mixer_add_ctl(sc, &mix); 789 } else { 790 /* XXX */ 791 } 792 #undef BIT 793 p += chs; 794 } 795 796 } 797 798 void 799 uaudio_add_selector(struct uaudio_softc *sc, usb_descriptor_t *v, 800 usb_descriptor_t **dps) 801 { 802 #ifdef UAUDIO_DEBUG 803 struct usb_audio_selector_unit *d = 804 (struct usb_audio_selector_unit *)v; 805 806 DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n", 807 d->bUnitId, d->bNrInPins)); 808 #endif 809 printf("uaudio_add_selector: NOT IMPLEMENTED\n"); 810 } 811 812 void 813 uaudio_add_feature(struct uaudio_softc *sc, usb_descriptor_t *v, 814 usb_descriptor_t **dps) 815 { 816 struct usb_audio_feature_unit *d = (struct usb_audio_feature_unit *)v; 817 uByte *ctls = d->bmaControls; 818 int ctlsize = d->bControlSize; 819 int nchan = (d->bLength - 7) / ctlsize; 820 int srcId = d->bSourceId; 821 u_int fumask, mmask, cmask; 822 struct mixerctl mix; 823 int chan, ctl, i, unit; 824 825 #define GET(i) (ctls[(i)*ctlsize] | \ 826 (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0)) 827 828 mmask = GET(0); 829 /* Figure out what we can control */ 830 for (cmask = 0, chan = 1; chan < nchan; chan++) { 831 DPRINTFN(9,("uaudio_add_feature: chan=%d mask=%x\n", 832 chan, GET(chan))); 833 cmask |= GET(chan); 834 } 835 836 DPRINTFN(1,("uaudio_add_feature: bUnitId=%d bSourceId=%d, " 837 "%d channels, mmask=0x%04x, cmask=0x%04x\n", 838 d->bUnitId, srcId, nchan, mmask, cmask)); 839 840 if (nchan > MIX_MAX_CHAN) 841 nchan = MIX_MAX_CHAN; 842 unit = d->bUnitId; 843 mix.wIndex = MAKE(unit, sc->sc_ac_iface); 844 for (ctl = MUTE_CONTROL; ctl < LOUDNESS_CONTROL; ctl++) { 845 fumask = FU_MASK(ctl); 846 DPRINTFN(4,("uaudio_add_feature: ctl=%d fumask=0x%04x\n", 847 ctl, fumask)); 848 if (mmask & fumask) { 849 mix.nchan = 1; 850 mix.wValue[0] = MAKE(ctl, 0); 851 } else if (cmask & fumask) { 852 mix.nchan = nchan - 1; 853 for (i = 1; i < nchan; i++) { 854 if (GET(i) & fumask) 855 mix.wValue[i-1] = MAKE(ctl, i); 856 else 857 mix.wValue[i-1] = -1; 858 } 859 } else { 860 continue; 861 } 862 #undef GET 863 mix.class = UAC_OUTPUT; /* XXX we don't really know this */ 864 switch (ctl) { 865 case MUTE_CONTROL: 866 mix.type = MIX_ON_OFF; 867 mix.ctlunit = ""; 868 uaudio_mixer_alias_ctl(sc, &mix, AudioNmute); 869 snprintf(mix.ctlname, sizeof(mix.ctlname), 870 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 871 AudioNmute); 872 break; 873 case VOLUME_CONTROL: 874 mix.type = MIX_SIGNED_16; 875 mix.ctlunit = AudioNvolume; 876 uaudio_mixer_alias_ctl(sc, &mix, AudioNmaster); 877 snprintf(mix.ctlname, sizeof(mix.ctlname), 878 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 879 AudioNmaster); 880 break; 881 case BASS_CONTROL: 882 mix.type = MIX_SIGNED_8; 883 mix.ctlunit = AudioNbass; 884 uaudio_mixer_alias_ctl(sc, &mix, AudioNbass); 885 snprintf(mix.ctlname, sizeof(mix.ctlname), 886 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 887 AudioNbass); 888 break; 889 case MID_CONTROL: 890 mix.type = MIX_SIGNED_8; 891 mix.ctlunit = AudioNmid; 892 snprintf(mix.ctlname, sizeof(mix.ctlname), 893 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 894 AudioNmid); 895 break; 896 case TREBLE_CONTROL: 897 mix.type = MIX_SIGNED_8; 898 mix.ctlunit = AudioNtreble; 899 uaudio_mixer_alias_ctl(sc, &mix, AudioNtreble); 900 snprintf(mix.ctlname, sizeof(mix.ctlname), 901 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 902 AudioNtreble); 903 break; 904 case GRAPHIC_EQUALIZER_CONTROL: 905 continue; /* XXX don't add anything */ 906 break; 907 case AGC_CONTROL: 908 mix.type = MIX_ON_OFF; 909 snprintf(mix.ctlname, sizeof(mix.ctlname), 910 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 911 AudioNagc); 912 mix.ctlunit = ""; 913 break; 914 case DELAY_CONTROL: 915 mix.type = MIX_UNSIGNED_16; 916 snprintf(mix.ctlname, sizeof(mix.ctlname), 917 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 918 AudioNdelay); 919 mix.ctlunit = "4 ms"; 920 break; 921 case BASS_BOOST_CONTROL: 922 mix.type = MIX_ON_OFF; 923 snprintf(mix.ctlname, sizeof(mix.ctlname), 924 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 925 AudioNbassboost); 926 mix.ctlunit = ""; 927 break; 928 case LOUDNESS_CONTROL: 929 mix.type = MIX_ON_OFF; 930 snprintf(mix.ctlname, sizeof(mix.ctlname), 931 "fea%d-%s-%s", unit, uaudio_id_name(sc, dps, srcId), 932 AudioNloudness); 933 mix.ctlunit = ""; 934 break; 935 } 936 uaudio_mixer_add_ctl(sc, &mix); 937 } 938 } 939 940 void 941 uaudio_add_processing_updown(struct uaudio_softc *sc, usb_descriptor_t *v, 942 usb_descriptor_t **dps) 943 { 944 struct usb_audio_processing_unit *d = 945 (struct usb_audio_processing_unit *)v; 946 struct usb_audio_processing_unit_1 *d1 = 947 (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins]; 948 struct usb_audio_processing_unit_updown *ud = 949 (struct usb_audio_processing_unit_updown *) 950 &d1->bmControls[d1->bControlSize]; 951 struct mixerctl mix; 952 int i; 953 954 DPRINTFN(2,("uaudio_add_processing_updown: bUnitId=%d bNrModes=%d\n", 955 d->bUnitId, ud->bNrModes)); 956 957 if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) { 958 DPRINTF(("uaudio_add_processing_updown: no mode select\n")); 959 return; 960 } 961 962 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 963 mix.nchan = 1; 964 mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0); 965 mix.class = -1; 966 mix.type = MIX_ON_OFF; /* XXX */ 967 mix.ctlunit = ""; 968 snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId); 969 970 for (i = 0; i < ud->bNrModes; i++) { 971 DPRINTFN(2,("uaudio_add_processing_updown: i=%d bm=0x%x\n", 972 i, UGETW(ud->waModes[i]))); 973 /* XXX */ 974 } 975 uaudio_mixer_add_ctl(sc, &mix); 976 } 977 978 void 979 uaudio_add_processing(struct uaudio_softc *sc, usb_descriptor_t *v, 980 usb_descriptor_t **dps) 981 { 982 struct usb_audio_processing_unit *d = 983 (struct usb_audio_processing_unit *)v; 984 struct usb_audio_processing_unit_1 *d1 = 985 (struct usb_audio_processing_unit_1 *)&d->baSourceId[d->bNrInPins]; 986 int ptype = UGETW(d->wProcessType); 987 struct mixerctl mix; 988 989 DPRINTFN(2,("uaudio_add_processing: wProcessType=%d bUnitId=%d " 990 "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins)); 991 992 if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) { 993 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 994 mix.nchan = 1; 995 mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0); 996 mix.class = -1; 997 mix.type = MIX_ON_OFF; 998 mix.ctlunit = ""; 999 snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable", 1000 d->bUnitId, ptype); 1001 uaudio_mixer_add_ctl(sc, &mix); 1002 } 1003 1004 switch(ptype) { 1005 case UPDOWNMIX_PROCESS: 1006 uaudio_add_processing_updown(sc, v, dps); 1007 break; 1008 case DOLBY_PROLOGIC_PROCESS: 1009 case P3D_STEREO_EXTENDER_PROCESS: 1010 case REVERBATION_PROCESS: 1011 case CHORUS_PROCESS: 1012 case DYN_RANGE_COMP_PROCESS: 1013 default: 1014 #ifdef UAUDIO_DEBUG 1015 printf("uaudio_add_processing: unit %d, type=%d not impl.\n", 1016 d->bUnitId, ptype); 1017 #endif 1018 break; 1019 } 1020 } 1021 1022 void 1023 uaudio_add_extension(struct uaudio_softc *sc, usb_descriptor_t *v, 1024 usb_descriptor_t **dps) 1025 { 1026 struct usb_audio_extension_unit *d = 1027 (struct usb_audio_extension_unit *)v; 1028 struct usb_audio_extension_unit_1 *d1 = 1029 (struct usb_audio_extension_unit_1 *)&d->baSourceId[d->bNrInPins]; 1030 struct mixerctl mix; 1031 1032 DPRINTFN(2,("uaudio_add_extension: bUnitId=%d bNrInPins=%d\n", 1033 d->bUnitId, d->bNrInPins)); 1034 1035 if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU) 1036 return; 1037 1038 if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { 1039 mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 1040 mix.nchan = 1; 1041 mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0); 1042 mix.class = -1; 1043 mix.type = MIX_ON_OFF; 1044 mix.ctlunit = ""; 1045 snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable", 1046 d->bUnitId); 1047 uaudio_mixer_add_ctl(sc, &mix); 1048 } 1049 } 1050 1051 usbd_status 1052 uaudio_identify(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc) 1053 { 1054 usbd_status err; 1055 1056 err = uaudio_identify_ac(sc, cdesc); 1057 if (err) 1058 return (err); 1059 return (uaudio_identify_as(sc, cdesc)); 1060 } 1061 1062 void 1063 uaudio_add_alt(struct uaudio_softc *sc, struct as_info *ai) 1064 { 1065 size_t len = sizeof(*ai) * (sc->sc_nalts + 1); 1066 struct as_info *nai = (sc->sc_nalts == 0) ? 1067 malloc(len, M_USBDEV, M_NOWAIT) : 1068 realloc(sc->sc_alts, len, M_USBDEV, M_NOWAIT); 1069 1070 if (nai == NULL) { 1071 printf("uaudio_add_alt: no memory\n"); 1072 return; 1073 } 1074 1075 sc->sc_alts = nai; 1076 DPRINTFN(2,("uaudio_add_alt: adding alt=%d, enc=%d\n", 1077 ai->alt, ai->encoding)); 1078 sc->sc_alts[sc->sc_nalts++] = *ai; 1079 } 1080 1081 usbd_status 1082 uaudio_process_as(struct uaudio_softc *sc, char *buf, int *offsp, 1083 int size, usb_interface_descriptor_t *id) 1084 #define offs (*offsp) 1085 { 1086 struct usb_audio_streaming_interface_descriptor *asid; 1087 struct usb_audio_streaming_type1_descriptor *asf1d; 1088 usb_endpoint_descriptor_audio_t *ed; 1089 struct usb_audio_streaming_endpoint_descriptor *sed; 1090 int format, chan, prec, enc; 1091 int dir, type; 1092 struct as_info ai; 1093 1094 asid = (void *)(buf + offs); 1095 if (asid->bDescriptorType != UDESC_CS_INTERFACE || 1096 asid->bDescriptorSubtype != AS_GENERAL) 1097 return (USBD_INVAL); 1098 offs += asid->bLength; 1099 if (offs > size) 1100 return (USBD_INVAL); 1101 asf1d = (void *)(buf + offs); 1102 if (asf1d->bDescriptorType != UDESC_CS_INTERFACE || 1103 asf1d->bDescriptorSubtype != FORMAT_TYPE) 1104 return (USBD_INVAL); 1105 offs += asf1d->bLength; 1106 if (offs > size) 1107 return (USBD_INVAL); 1108 1109 if (asf1d->bFormatType != FORMAT_TYPE_I) { 1110 printf("%s: ignored setting with type %d format\n", 1111 USBDEVNAME(sc->sc_dev), UGETW(asid->wFormatTag)); 1112 return (USBD_NORMAL_COMPLETION); 1113 } 1114 1115 ed = (void *)(buf + offs); 1116 if (ed->bDescriptorType != UDESC_ENDPOINT) 1117 return (USBD_INVAL); 1118 DPRINTF(("uaudio_process_as: endpoint bLength=%d bDescriptorType=%d " 1119 "bEndpointAddress=%d bmAttributes=0x%x wMaxPacketSize=%d " 1120 "bInterval=%d bRefresh=%d bSynchAddress=%d\n", 1121 ed->bLength, ed->bDescriptorType, ed->bEndpointAddress, 1122 ed->bmAttributes, UGETW(ed->wMaxPacketSize), 1123 ed->bInterval, ed->bRefresh, ed->bSynchAddress)); 1124 offs += ed->bLength; 1125 if (offs > size) 1126 return (USBD_INVAL); 1127 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS) 1128 return (USBD_INVAL); 1129 1130 dir = UE_GET_DIR(ed->bEndpointAddress); 1131 type = UE_GET_ISO_TYPE(ed->bmAttributes); 1132 if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) && 1133 dir == UE_DIR_IN && type == UE_ISO_ADAPT) 1134 type = UE_ISO_ASYNC; 1135 1136 /* We can't handle endpoints that need a sync pipe yet. */ 1137 if (dir == UE_DIR_IN ? type == UE_ISO_ADAPT : type == UE_ISO_ASYNC) { 1138 printf("%s: ignored %sput endpoint of type %s\n", 1139 USBDEVNAME(sc->sc_dev), 1140 dir == UE_DIR_IN ? "in" : "out", 1141 dir == UE_DIR_IN ? "adaptive" : "async"); 1142 return (USBD_NORMAL_COMPLETION); 1143 } 1144 1145 sed = (void *)(buf + offs); 1146 if (sed->bDescriptorType != UDESC_CS_ENDPOINT || 1147 sed->bDescriptorSubtype != AS_GENERAL) 1148 return (USBD_INVAL); 1149 offs += sed->bLength; 1150 if (offs > size) 1151 return (USBD_INVAL); 1152 1153 format = UGETW(asid->wFormatTag); 1154 chan = asf1d->bNrChannels; 1155 prec = asf1d->bBitResolution; 1156 if (prec != 8 && prec != 16 && prec != 24) { 1157 printf("%s: ignored setting with precision %d\n", 1158 USBDEVNAME(sc->sc_dev), prec); 1159 return (USBD_NORMAL_COMPLETION); 1160 } 1161 switch (format) { 1162 case UA_FMT_PCM: 1163 if (prec == 8) { 1164 sc->sc_altflags |= HAS_8; 1165 } else if (prec == 16) { 1166 sc->sc_altflags |= HAS_16; 1167 } else if (prec == 24) { 1168 sc->sc_altflags |= HAS_24; 1169 } 1170 enc = AUDIO_ENCODING_SLINEAR_LE; 1171 break; 1172 case UA_FMT_PCM8: 1173 enc = AUDIO_ENCODING_ULINEAR_LE; 1174 sc->sc_altflags |= HAS_8U; 1175 break; 1176 case UA_FMT_ALAW: 1177 enc = AUDIO_ENCODING_ALAW; 1178 sc->sc_altflags |= HAS_ALAW; 1179 break; 1180 case UA_FMT_MULAW: 1181 enc = AUDIO_ENCODING_ULAW; 1182 sc->sc_altflags |= HAS_MULAW; 1183 break; 1184 default: 1185 printf("%s: ignored setting with format %d\n", 1186 USBDEVNAME(sc->sc_dev), format); 1187 return (USBD_NORMAL_COMPLETION); 1188 } 1189 DPRINTFN(1, ("uaudio_process_as: alt=%d enc=%d chan=%d prec=%d\n", 1190 id->bAlternateSetting, enc, chan, prec)); 1191 ai.alt = id->bAlternateSetting; 1192 ai.encoding = enc; 1193 ai.attributes = sed->bmAttributes; 1194 ai.idesc = id; 1195 ai.edesc = ed; 1196 ai.asf1desc = asf1d; 1197 ai.sc_busy = 0; 1198 uaudio_add_alt(sc, &ai); 1199 #ifdef UAUDIO_DEBUG 1200 { 1201 int j; 1202 if (asf1d->bSamFreqType == UA_SAMP_CONTNUOUS) { 1203 DPRINTFN(1, ("uaudio_process_as: rate=%d-%d\n", 1204 UA_SAMP_LO(asf1d), UA_SAMP_HI(asf1d))); 1205 } else { 1206 DPRINTFN(1, ("uaudio_process_as: ")); 1207 for (j = 0; j < asf1d->bSamFreqType; j++) 1208 DPRINTFN(1, (" %d", UA_GETSAMP(asf1d, j))); 1209 DPRINTFN(1, ("\n")); 1210 } 1211 if (ai.attributes & UA_SED_FREQ_CONTROL) 1212 DPRINTFN(1, ("uaudio_process_as: FREQ_CONTROL\n")); 1213 if (ai.attributes & UA_SED_PITCH_CONTROL) 1214 DPRINTFN(1, ("uaudio_process_as: PITCH_CONTROL\n")); 1215 } 1216 #endif 1217 sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD; 1218 1219 return (USBD_NORMAL_COMPLETION); 1220 } 1221 #undef offs 1222 1223 usbd_status 1224 uaudio_identify_as(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc) 1225 { 1226 usb_interface_descriptor_t *id; 1227 char *buf; 1228 int size, offs; 1229 1230 size = UGETW(cdesc->wTotalLength); 1231 buf = (char *)cdesc; 1232 1233 /* Locate the AudioStreaming interface descriptor. */ 1234 offs = 0; 1235 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOSTREAM); 1236 if (id == NULL) 1237 return (USBD_INVAL); 1238 1239 /* Loop through all the alternate settings. */ 1240 while (offs <= size) { 1241 DPRINTFN(2, ("uaudio_identify: interface %d\n", 1242 id->bInterfaceNumber)); 1243 switch (id->bNumEndpoints) { 1244 case 0: 1245 DPRINTFN(2, ("uaudio_identify: AS null alt=%d\n", 1246 id->bAlternateSetting)); 1247 sc->sc_nullalt = id->bAlternateSetting; 1248 break; 1249 case 1: 1250 uaudio_process_as(sc, buf, &offs, size, id); 1251 break; 1252 default: 1253 #ifdef UAUDIO_DEBUG 1254 printf("%s: ignored audio interface with %d " 1255 "endpoints\n", 1256 USBDEVNAME(sc->sc_dev), id->bNumEndpoints); 1257 #endif 1258 break; 1259 } 1260 id = uaudio_find_iface(buf, size, &offs,UISUBCLASS_AUDIOSTREAM); 1261 if (id == NULL) 1262 break; 1263 } 1264 if (offs > size) 1265 return (USBD_INVAL); 1266 DPRINTF(("uaudio_identify_as: %d alts available\n", sc->sc_nalts)); 1267 1268 if (sc->sc_mode == 0) { 1269 printf("%s: no usable endpoint found\n", 1270 USBDEVNAME(sc->sc_dev)); 1271 return (USBD_INVAL); 1272 } 1273 1274 return (USBD_NORMAL_COMPLETION); 1275 } 1276 1277 usbd_status 1278 uaudio_identify_ac(struct uaudio_softc *sc, usb_config_descriptor_t *cdesc) 1279 { 1280 usb_interface_descriptor_t *id; 1281 struct usb_audio_control_descriptor *acdp; 1282 usb_descriptor_t *dp, *dps[256]; 1283 char *buf, *ibuf, *ibufend; 1284 int size, offs, aclen, ndps, i; 1285 1286 size = UGETW(cdesc->wTotalLength); 1287 buf = (char *)cdesc; 1288 1289 /* Locate the AudioControl interface descriptor. */ 1290 offs = 0; 1291 id = uaudio_find_iface(buf, size, &offs, UISUBCLASS_AUDIOCONTROL); 1292 if (id == NULL) 1293 return (USBD_INVAL); 1294 if (offs + sizeof *acdp > size) 1295 return (USBD_INVAL); 1296 sc->sc_ac_iface = id->bInterfaceNumber; 1297 DPRINTFN(2,("uaudio_identify: AC interface is %d\n", sc->sc_ac_iface)); 1298 1299 /* A class-specific AC interface header should follow. */ 1300 ibuf = buf + offs; 1301 acdp = (struct usb_audio_control_descriptor *)ibuf; 1302 if (acdp->bDescriptorType != UDESC_CS_INTERFACE || 1303 acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER) 1304 return (USBD_INVAL); 1305 aclen = UGETW(acdp->wTotalLength); 1306 if (offs + aclen > size) 1307 return (USBD_INVAL); 1308 1309 if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC) && 1310 UGETW(acdp->bcdADC) != UAUDIO_VERSION) 1311 return (USBD_INVAL); 1312 1313 sc->sc_audio_rev = UGETW(acdp->bcdADC); 1314 DPRINTFN(2,("uaudio_identify: found AC header, vers=%03x, len=%d\n", 1315 sc->sc_audio_rev, aclen)); 1316 1317 sc->sc_nullalt = -1; 1318 1319 /* Scan through all the AC specific descriptors */ 1320 ibufend = ibuf + aclen; 1321 dp = (usb_descriptor_t *)ibuf; 1322 ndps = 0; 1323 memset(dps, 0, sizeof dps); 1324 for (;;) { 1325 ibuf += dp->bLength; 1326 if (ibuf >= ibufend) 1327 break; 1328 dp = (usb_descriptor_t *)ibuf; 1329 if (ibuf + dp->bLength > ibufend) 1330 return (USBD_INVAL); 1331 if (dp->bDescriptorType != UDESC_CS_INTERFACE) { 1332 printf("uaudio_identify: skip desc type=0x%02x\n", 1333 dp->bDescriptorType); 1334 continue; 1335 } 1336 i = ((struct usb_audio_input_terminal *)dp)->bTerminalId; 1337 dps[i] = dp; 1338 if (i > ndps) 1339 ndps = i; 1340 } 1341 ndps++; 1342 1343 for (i = 0; i < ndps; i++) { 1344 dp = dps[i]; 1345 if (dp == NULL) 1346 continue; 1347 DPRINTF(("uaudio_identify: subtype=%d\n", 1348 dp->bDescriptorSubtype)); 1349 switch (dp->bDescriptorSubtype) { 1350 case UDESCSUB_AC_HEADER: 1351 printf("uaudio_identify: unexpected AC header\n"); 1352 break; 1353 case UDESCSUB_AC_INPUT: 1354 uaudio_add_input(sc, dp, dps); 1355 break; 1356 case UDESCSUB_AC_OUTPUT: 1357 uaudio_add_output(sc, dp, dps); 1358 break; 1359 case UDESCSUB_AC_MIXER: 1360 uaudio_add_mixer(sc, dp, dps); 1361 break; 1362 case UDESCSUB_AC_SELECTOR: 1363 uaudio_add_selector(sc, dp, dps); 1364 break; 1365 case UDESCSUB_AC_FEATURE: 1366 uaudio_add_feature(sc, dp, dps); 1367 break; 1368 case UDESCSUB_AC_PROCESSING: 1369 uaudio_add_processing(sc, dp, dps); 1370 break; 1371 case UDESCSUB_AC_EXTENSION: 1372 uaudio_add_extension(sc, dp, dps); 1373 break; 1374 default: 1375 printf("uaudio_identify: bad AC desc subtype=0x%02x\n", 1376 dp->bDescriptorSubtype); 1377 break; 1378 } 1379 } 1380 return (USBD_NORMAL_COMPLETION); 1381 } 1382 1383 int 1384 uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi) 1385 { 1386 struct uaudio_softc *sc = addr; 1387 struct mixerctl *mc; 1388 int n, nctls; 1389 1390 DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index)); 1391 if (sc->sc_dying) 1392 return (EIO); 1393 1394 n = mi->index; 1395 nctls = sc->sc_nctls; 1396 1397 switch (n) { 1398 case UAC_OUTPUT: 1399 mi->type = AUDIO_MIXER_CLASS; 1400 mi->mixer_class = UAC_OUTPUT; 1401 mi->next = mi->prev = AUDIO_MIXER_LAST; 1402 strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name)); 1403 return (0); 1404 case UAC_INPUT: 1405 mi->type = AUDIO_MIXER_CLASS; 1406 mi->mixer_class = UAC_INPUT; 1407 mi->next = mi->prev = AUDIO_MIXER_LAST; 1408 strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name)); 1409 return (0); 1410 case UAC_EQUAL: 1411 mi->type = AUDIO_MIXER_CLASS; 1412 mi->mixer_class = UAC_EQUAL; 1413 mi->next = mi->prev = AUDIO_MIXER_LAST; 1414 strlcpy(mi->label.name, AudioCequalization, 1415 sizeof(mi->label.name)); 1416 return (0); 1417 default: 1418 break; 1419 } 1420 1421 n -= UAC_NCLASSES; 1422 if (n < 0 || n >= nctls) 1423 return (ENXIO); 1424 1425 mc = &sc->sc_ctls[n]; 1426 strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name)); 1427 mi->mixer_class = mc->class; 1428 mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */ 1429 switch (mc->type) { 1430 case MIX_ON_OFF: 1431 mi->type = AUDIO_MIXER_ENUM; 1432 mi->un.e.num_mem = 2; 1433 strlcpy(mi->un.e.member[0].label.name, AudioNoff, 1434 sizeof(mi->un.e.member[0].label.name)); 1435 mi->un.e.member[0].ord = 0; 1436 strlcpy(mi->un.e.member[1].label.name, AudioNon, 1437 sizeof(mi->un.e.member[1].label.name)); 1438 mi->un.e.member[1].ord = 1; 1439 break; 1440 default: 1441 mi->type = AUDIO_MIXER_VALUE; 1442 strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN); 1443 mi->un.v.num_channels = mc->nchan; 1444 mi->un.v.delta = mc->delta; 1445 break; 1446 } 1447 return (0); 1448 } 1449 1450 int 1451 uaudio_open(void *addr, int flags) 1452 { 1453 struct uaudio_softc *sc = addr; 1454 1455 DPRINTF(("uaudio_open: sc=%p\n", sc)); 1456 if (sc->sc_dying) 1457 return (EIO); 1458 1459 if ((flags & ~sc->sc_mode) & (AUMODE_PLAY | AUMODE_RECORD)) 1460 return (EACCES); 1461 1462 return (0); 1463 } 1464 1465 /* 1466 * Close function is called at splaudio(). 1467 */ 1468 void 1469 uaudio_close(void *addr) 1470 { 1471 } 1472 1473 int 1474 uaudio_drain(void *addr) 1475 { 1476 struct uaudio_softc *sc = addr; 1477 1478 usbd_delay_ms(sc->sc_udev, UAUDIO_NCHANBUFS * UAUDIO_NFRAMES); 1479 1480 return (0); 1481 } 1482 1483 int 1484 uaudio_halt_out_dma(void *addr) 1485 { 1486 struct uaudio_softc *sc = addr; 1487 1488 DPRINTF(("uaudio_halt_out_dma: enter\n")); 1489 if (sc->sc_playchan.pipe != NULL) { 1490 uaudio_chan_close(sc, &sc->sc_playchan); 1491 sc->sc_playchan.pipe = NULL; 1492 uaudio_chan_free_buffers(sc, &sc->sc_playchan); 1493 sc->sc_playchan.intr = NULL; 1494 } 1495 return (0); 1496 } 1497 1498 int 1499 uaudio_halt_in_dma(void *addr) 1500 { 1501 struct uaudio_softc *sc = addr; 1502 1503 DPRINTF(("uaudio_halt_in_dma: enter\n")); 1504 if (sc->sc_recchan.pipe != NULL) { 1505 uaudio_chan_close(sc, &sc->sc_recchan); 1506 sc->sc_recchan.pipe = NULL; 1507 uaudio_chan_free_buffers(sc, &sc->sc_recchan); 1508 sc->sc_recchan.intr = NULL; 1509 } 1510 return (0); 1511 } 1512 1513 int 1514 uaudio_getdev(void *addr, struct audio_device *retp) 1515 { 1516 struct uaudio_softc *sc = addr; 1517 1518 DPRINTF(("uaudio_mixer_getdev:\n")); 1519 if (sc->sc_dying) 1520 return (EIO); 1521 1522 *retp = uaudio_device; 1523 return (0); 1524 } 1525 1526 /* 1527 * Make sure the block size is large enough to hold all outstanding transfers. 1528 */ 1529 int 1530 uaudio_round_blocksize(void *addr, int blk) 1531 { 1532 struct uaudio_softc *sc = addr; 1533 int bpf; 1534 1535 DPRINTF(("uaudio_round_blocksize: p.bpf=%d r.bpf=%d\n", 1536 sc->sc_playchan.bytes_per_frame, 1537 sc->sc_recchan.bytes_per_frame)); 1538 if (sc->sc_playchan.bytes_per_frame > sc->sc_recchan.bytes_per_frame) { 1539 bpf = sc->sc_playchan.bytes_per_frame 1540 + sc->sc_playchan.sample_size; 1541 } else { 1542 bpf = sc->sc_recchan.bytes_per_frame 1543 + sc->sc_recchan.sample_size; 1544 } 1545 /* XXX */ 1546 bpf *= UAUDIO_NFRAMES * UAUDIO_NCHANBUFS; 1547 1548 bpf = (bpf + 15) &~ 15; 1549 1550 if (blk < bpf) 1551 blk = bpf; 1552 1553 #ifdef DIAGNOSTIC 1554 if (blk <= 0) { 1555 printf("uaudio_round_blocksize: blk=%d\n", blk); 1556 blk = 512; 1557 } 1558 #endif 1559 1560 DPRINTFN(1,("uaudio_round_blocksize: blk=%d\n", blk)); 1561 return (blk); 1562 } 1563 1564 int 1565 uaudio_get_props(void *addr) 1566 { 1567 return (AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT); 1568 1569 } 1570 1571 int 1572 uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue, 1573 int wIndex, int len) 1574 { 1575 usb_device_request_t req; 1576 u_int8_t data[4]; 1577 usbd_status err; 1578 int val; 1579 1580 if (wValue == -1) 1581 return (0); 1582 1583 req.bmRequestType = type; 1584 req.bRequest = which; 1585 USETW(req.wValue, wValue); 1586 USETW(req.wIndex, wIndex); 1587 USETW(req.wLength, len); 1588 DPRINTFN(2,("uaudio_get: type=0x%02x req=0x%02x wValue=0x%04x " 1589 "wIndex=0x%04x len=%d\n", 1590 type, which, wValue, wIndex, len)); 1591 err = usbd_do_request(sc->sc_udev, &req, data); 1592 if (err) { 1593 DPRINTF(("uaudio_get: err=%s\n", usbd_errstr(err))); 1594 return (-1); 1595 } 1596 switch (len) { 1597 case 1: 1598 val = data[0]; 1599 break; 1600 case 2: 1601 val = data[0] | (data[1] << 8); 1602 break; 1603 default: 1604 DPRINTF(("uaudio_get: bad length=%d\n", len)); 1605 return (-1); 1606 } 1607 DPRINTFN(2,("uaudio_get: val=%d\n", val)); 1608 return (val); 1609 } 1610 1611 void 1612 uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue, 1613 int wIndex, int len, int val) 1614 { 1615 usb_device_request_t req; 1616 u_int8_t data[4]; 1617 usbd_status err; 1618 1619 if (wValue == -1) 1620 return; 1621 1622 req.bmRequestType = type; 1623 req.bRequest = which; 1624 USETW(req.wValue, wValue); 1625 USETW(req.wIndex, wIndex); 1626 USETW(req.wLength, len); 1627 switch (len) { 1628 case 1: 1629 data[0] = val; 1630 break; 1631 case 2: 1632 data[0] = val; 1633 data[1] = val >> 8; 1634 break; 1635 default: 1636 return; 1637 } 1638 DPRINTFN(2,("uaudio_set: type=0x%02x req=0x%02x wValue=0x%04x " 1639 "wIndex=0x%04x len=%d, val=%d\n", 1640 type, which, wValue, wIndex, len, val & 0xffff)); 1641 err = usbd_do_request(sc->sc_udev, &req, data); 1642 #ifdef UAUDIO_DEBUG 1643 if (err) 1644 DPRINTF(("uaudio_set: err=%d\n", err)); 1645 #endif 1646 } 1647 1648 int 1649 uaudio_signext(int type, int val) 1650 { 1651 if (!MIX_UNSIGNED(type)) { 1652 if (MIX_SIZE(type) == 2) 1653 val = (int16_t)val; 1654 else 1655 val = (int8_t)val; 1656 } 1657 return (val); 1658 } 1659 1660 int 1661 uaudio_value2bsd(struct mixerctl *mc, int val) 1662 { 1663 DPRINTFN(5, ("uaudio_value2bsd: type=%03x val=%d min=%d max=%d ", 1664 mc->type, val, mc->minval, mc->maxval)); 1665 if (mc->type == MIX_ON_OFF) 1666 val = (val != 0); 1667 else 1668 val = ((uaudio_signext(mc->type, val) - mc->minval) * 255 1669 + mc->mul/2) / mc->mul; 1670 DPRINTFN(5, ("val'=%d\n", val)); 1671 return (val); 1672 } 1673 1674 int 1675 uaudio_bsd2value(struct mixerctl *mc, int val) 1676 { 1677 DPRINTFN(5,("uaudio_bsd2value: type=%03x val=%d min=%d max=%d ", 1678 mc->type, val, mc->minval, mc->maxval)); 1679 if (mc->type == MIX_ON_OFF) 1680 val = (val != 0); 1681 else 1682 val = (val + mc->delta/2) * mc->mul / 255 + mc->minval; 1683 DPRINTFN(5, ("val'=%d\n", val)); 1684 return (val); 1685 } 1686 1687 int 1688 uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc, 1689 int chan) 1690 { 1691 int val; 1692 1693 DPRINTFN(5,("uaudio_ctl_get: which=%d chan=%d\n", which, chan)); 1694 val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan], 1695 mc->wIndex, MIX_SIZE(mc->type)); 1696 return (uaudio_value2bsd(mc, val)); 1697 } 1698 1699 void 1700 uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc, 1701 int chan, int val) 1702 { 1703 val = uaudio_bsd2value(mc, val); 1704 uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan], 1705 mc->wIndex, MIX_SIZE(mc->type), val); 1706 } 1707 1708 int 1709 uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp) 1710 { 1711 struct uaudio_softc *sc = addr; 1712 struct mixerctl *mc; 1713 int i, n, vals[MIX_MAX_CHAN], val; 1714 1715 DPRINTFN(2,("uaudio_mixer_get_port: index=%d\n", cp->dev)); 1716 1717 if (sc->sc_dying) 1718 return (EIO); 1719 1720 n = cp->dev - UAC_NCLASSES; 1721 if (n < 0 || n >= sc->sc_nctls) 1722 return (ENXIO); 1723 mc = &sc->sc_ctls[n]; 1724 1725 if (mc->type == MIX_ON_OFF) { 1726 if (cp->type != AUDIO_MIXER_ENUM) 1727 return (EINVAL); 1728 cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0); 1729 } else { 1730 if (cp->type != AUDIO_MIXER_VALUE) 1731 return (EINVAL); 1732 if (cp->un.value.num_channels != 1 && 1733 cp->un.value.num_channels != mc->nchan) 1734 return (EINVAL); 1735 for (i = 0; i < mc->nchan; i++) 1736 vals[i] = uaudio_ctl_get(sc, GET_CUR, mc, i); 1737 if (cp->un.value.num_channels == 1 && mc->nchan != 1) { 1738 for (val = 0, i = 0; i < mc->nchan; i++) 1739 val += vals[i]; 1740 vals[0] = val / mc->nchan; 1741 } 1742 for (i = 0; i < cp->un.value.num_channels; i++) 1743 cp->un.value.level[i] = vals[i]; 1744 } 1745 1746 return (0); 1747 } 1748 1749 int 1750 uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp) 1751 { 1752 struct uaudio_softc *sc = addr; 1753 struct mixerctl *mc; 1754 int i, n, vals[MIX_MAX_CHAN]; 1755 1756 DPRINTFN(2,("uaudio_mixer_set_port: index = %d\n", cp->dev)); 1757 if (sc->sc_dying) 1758 return (EIO); 1759 1760 n = cp->dev - UAC_NCLASSES; 1761 if (n < 0 || n >= sc->sc_nctls) 1762 return (ENXIO); 1763 mc = &sc->sc_ctls[n]; 1764 1765 if (mc->type == MIX_ON_OFF) { 1766 if (cp->type != AUDIO_MIXER_ENUM) 1767 return (EINVAL); 1768 uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord); 1769 } else { 1770 if (cp->type != AUDIO_MIXER_VALUE) 1771 return (EINVAL); 1772 if (cp->un.value.num_channels == 1) 1773 for (i = 0; i < mc->nchan; i++) 1774 vals[i] = cp->un.value.level[0]; 1775 else if (cp->un.value.num_channels == mc->nchan) 1776 for (i = 0; i < mc->nchan; i++) 1777 vals[i] = cp->un.value.level[i]; 1778 else 1779 return (EINVAL); 1780 for (i = 0; i < mc->nchan; i++) 1781 uaudio_ctl_set(sc, SET_CUR, mc, i, vals[i]); 1782 } 1783 return (0); 1784 } 1785 1786 int 1787 uaudio_trigger_input(void *addr, void *start, void *end, int blksize, 1788 void (*intr)(void *), void *arg, 1789 struct audio_params *param) 1790 { 1791 struct uaudio_softc *sc = addr; 1792 struct chan *ch = &sc->sc_recchan; 1793 usbd_status err; 1794 int i, s; 1795 1796 if (sc->sc_dying) 1797 return (EIO); 1798 1799 DPRINTFN(3,("uaudio_trigger_input: sc=%p start=%p end=%p " 1800 "blksize=%d\n", sc, start, end, blksize)); 1801 1802 uaudio_chan_set_param(ch, start, end, blksize); 1803 DPRINTFN(3,("uaudio_trigger_input: sample_size=%d bytes/frame=%d " 1804 "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, 1805 ch->fraction)); 1806 1807 err = uaudio_chan_alloc_buffers(sc, ch); 1808 if (err) 1809 return (EIO); 1810 1811 err = uaudio_chan_open(sc, ch); 1812 if (err) { 1813 uaudio_chan_free_buffers(sc, ch); 1814 return (EIO); 1815 } 1816 1817 ch->intr = intr; 1818 ch->arg = arg; 1819 1820 s = splusb(); 1821 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX -1 shouldn't be needed */ 1822 uaudio_chan_rtransfer(ch); 1823 splx(s); 1824 1825 return (0); 1826 } 1827 1828 int 1829 uaudio_trigger_output(void *addr, void *start, void *end, int blksize, 1830 void (*intr)(void *), void *arg, 1831 struct audio_params *param) 1832 { 1833 struct uaudio_softc *sc = addr; 1834 struct chan *ch = &sc->sc_playchan; 1835 usbd_status err; 1836 int i, s; 1837 1838 if (sc->sc_dying) 1839 return (EIO); 1840 1841 DPRINTFN(3,("uaudio_trigger_output: sc=%p start=%p end=%p " 1842 "blksize=%d\n", sc, start, end, blksize)); 1843 1844 uaudio_chan_set_param(ch, start, end, blksize); 1845 DPRINTFN(3,("uaudio_trigger_output: sample_size=%d bytes/frame=%d " 1846 "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, 1847 ch->fraction)); 1848 1849 err = uaudio_chan_alloc_buffers(sc, ch); 1850 if (err) 1851 return (EIO); 1852 1853 err = uaudio_chan_open(sc, ch); 1854 if (err) { 1855 uaudio_chan_free_buffers(sc, ch); 1856 return (EIO); 1857 } 1858 1859 ch->intr = intr; 1860 ch->arg = arg; 1861 1862 s = splusb(); 1863 for (i = 0; i < UAUDIO_NCHANBUFS-1; i++) /* XXX */ 1864 uaudio_chan_ptransfer(ch); 1865 splx(s); 1866 1867 return (0); 1868 } 1869 1870 /* Set up a pipe for a channel. */ 1871 usbd_status 1872 uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) 1873 { 1874 struct as_info *as = &sc->sc_alts[ch->altidx]; 1875 int endpt = as->edesc->bEndpointAddress; 1876 usbd_status err; 1877 1878 DPRINTF(("uaudio_chan_open: endpt=0x%02x, speed=%d, alt=%d\n", 1879 endpt, ch->sample_rate, as->alt)); 1880 1881 /* Set alternate interface corresponding to the mode. */ 1882 err = usbd_set_interface(as->ifaceh, as->alt); 1883 if (err) 1884 return (err); 1885 1886 /* Some devices do not support this request, so ignore errors. */ 1887 #ifdef UAUDIO_DEBUG 1888 err = uaudio_set_speed(sc, endpt, ch->sample_rate); 1889 if (err) 1890 DPRINTF(("uaudio_chan_open: set_speed failed err=%s\n", 1891 usbd_errstr(err))); 1892 #else 1893 (void)uaudio_set_speed(sc, endpt, ch->sample_rate); 1894 #endif 1895 1896 DPRINTF(("uaudio_chan_open: create pipe to 0x%02x\n", endpt)); 1897 err = usbd_open_pipe(as->ifaceh, endpt, 0, &ch->pipe); 1898 return (err); 1899 } 1900 1901 void 1902 uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch) 1903 { 1904 struct as_info *as = &sc->sc_alts[ch->altidx]; 1905 1906 as->sc_busy = 0; 1907 if (sc->sc_nullalt >= 0) { 1908 DPRINTF(("uaudio_chan_close: set null alt=%d\n", 1909 sc->sc_nullalt)); 1910 usbd_set_interface(as->ifaceh, sc->sc_nullalt); 1911 } 1912 usbd_abort_pipe(ch->pipe); 1913 usbd_close_pipe(ch->pipe); 1914 } 1915 1916 usbd_status 1917 uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch) 1918 { 1919 usbd_xfer_handle xfer; 1920 void *buf; 1921 int i, size; 1922 1923 size = (ch->bytes_per_frame + ch->sample_size) * UAUDIO_NFRAMES; 1924 for (i = 0; i < UAUDIO_NCHANBUFS; i++) { 1925 xfer = usbd_alloc_xfer(sc->sc_udev); 1926 if (xfer == 0) 1927 goto bad; 1928 ch->chanbufs[i].xfer = xfer; 1929 buf = usbd_alloc_buffer(xfer, size); 1930 if (buf == 0) { 1931 i++; 1932 goto bad; 1933 } 1934 ch->chanbufs[i].buffer = buf; 1935 ch->chanbufs[i].chan = ch; 1936 } 1937 1938 return (USBD_NORMAL_COMPLETION); 1939 1940 bad: 1941 while (--i >= 0) 1942 /* implicit buffer free */ 1943 usbd_free_xfer(ch->chanbufs[i].xfer); 1944 return (USBD_NOMEM); 1945 } 1946 1947 void 1948 uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch) 1949 { 1950 int i; 1951 1952 for (i = 0; i < UAUDIO_NCHANBUFS; i++) 1953 usbd_free_xfer(ch->chanbufs[i].xfer); 1954 } 1955 1956 /* Called at splusb() */ 1957 void 1958 uaudio_chan_ptransfer(struct chan *ch) 1959 { 1960 struct chanbuf *cb; 1961 int i, n, size, residue, total; 1962 1963 if (ch->sc->sc_dying) 1964 return; 1965 1966 /* Pick the next channel buffer. */ 1967 cb = &ch->chanbufs[ch->curchanbuf]; 1968 if (++ch->curchanbuf >= UAUDIO_NCHANBUFS) 1969 ch->curchanbuf = 0; 1970 1971 /* Compute the size of each frame in the next transfer. */ 1972 residue = ch->residue; 1973 total = 0; 1974 for (i = 0; i < UAUDIO_NFRAMES; i++) { 1975 size = ch->bytes_per_frame; 1976 residue += ch->fraction; 1977 if (residue >= USB_FRAMES_PER_SECOND) { 1978 if ((ch->sc->sc_altflags & UA_NOFRAC) == 0) 1979 size += ch->sample_size; 1980 residue -= USB_FRAMES_PER_SECOND; 1981 } 1982 cb->sizes[i] = size; 1983 total += size; 1984 } 1985 ch->residue = residue; 1986 cb->size = total; 1987 1988 /* 1989 * Transfer data from upper layer buffer to channel buffer, taking 1990 * care of wrapping the upper layer buffer. 1991 */ 1992 n = min(total, ch->end - ch->cur); 1993 memcpy(cb->buffer, ch->cur, n); 1994 ch->cur += n; 1995 if (ch->cur >= ch->end) 1996 ch->cur = ch->start; 1997 if (total > n) { 1998 total -= n; 1999 memcpy(cb->buffer + n, ch->cur, total); 2000 ch->cur += total; 2001 } 2002 2003 #ifdef UAUDIO_DEBUG 2004 if (uaudiodebug > 8) { 2005 DPRINTF(("uaudio_chan_ptransfer: buffer=%p, residue=0.%03d\n", 2006 cb->buffer, ch->residue)); 2007 for (i = 0; i < UAUDIO_NFRAMES; i++) { 2008 DPRINTF((" [%d] length %d\n", i, cb->sizes[i])); 2009 } 2010 } 2011 #endif 2012 2013 DPRINTFN(5,("uaudio_chan_transfer: ptransfer xfer=%p\n", cb->xfer)); 2014 /* Fill the request */ 2015 usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, 2016 UAUDIO_NFRAMES, USBD_NO_COPY, 2017 uaudio_chan_pintr); 2018 2019 (void)usbd_transfer(cb->xfer); 2020 } 2021 2022 void 2023 uaudio_chan_pintr(usbd_xfer_handle xfer, usbd_private_handle priv, 2024 usbd_status status) 2025 { 2026 struct chanbuf *cb = priv; 2027 struct chan *ch = cb->chan; 2028 u_int32_t count; 2029 int s; 2030 2031 /* Return if we are aborting. */ 2032 if (status == USBD_CANCELLED) 2033 return; 2034 2035 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 2036 DPRINTFN(5,("uaudio_chan_pintr: count=%d, transferred=%d\n", 2037 count, ch->transferred)); 2038 #ifdef DIAGNOSTIC 2039 if (count != cb->size) { 2040 printf("uaudio_chan_pintr: count(%d) != size(%d)\n", 2041 count, cb->size); 2042 } 2043 #endif 2044 2045 ch->transferred += cb->size; 2046 s = splaudio(); 2047 /* Call back to upper layer */ 2048 while (ch->transferred >= ch->blksize) { 2049 ch->transferred -= ch->blksize; 2050 DPRINTFN(5,("uaudio_chan_pintr: call %p(%p)\n", 2051 ch->intr, ch->arg)); 2052 ch->intr(ch->arg); 2053 } 2054 splx(s); 2055 2056 /* start next transfer */ 2057 uaudio_chan_ptransfer(ch); 2058 } 2059 2060 /* Called at splusb() */ 2061 void 2062 uaudio_chan_rtransfer(struct chan *ch) 2063 { 2064 struct chanbuf *cb; 2065 int i, size, residue, total; 2066 2067 if (ch->sc->sc_dying) 2068 return; 2069 2070 /* Pick the next channel buffer. */ 2071 cb = &ch->chanbufs[ch->curchanbuf]; 2072 if (++ch->curchanbuf >= UAUDIO_NCHANBUFS) 2073 ch->curchanbuf = 0; 2074 2075 /* Compute the size of each frame in the next transfer. */ 2076 residue = ch->residue; 2077 total = 0; 2078 for (i = 0; i < UAUDIO_NFRAMES; i++) { 2079 size = ch->bytes_per_frame; 2080 cb->sizes[i] = size; 2081 cb->offsets[i] = total; 2082 total += size; 2083 } 2084 ch->residue = residue; 2085 cb->size = total; 2086 2087 #ifdef UAUDIO_DEBUG 2088 if (uaudiodebug > 8) { 2089 DPRINTF(("uaudio_chan_rtransfer: buffer=%p, residue=0.%03d\n", 2090 cb->buffer, ch->residue)); 2091 for (i = 0; i < UAUDIO_NFRAMES; i++) { 2092 DPRINTF((" [%d] length %d\n", i, cb->sizes[i])); 2093 } 2094 } 2095 #endif 2096 2097 DPRINTFN(5,("uaudio_chan_rtransfer: transfer xfer=%p\n", cb->xfer)); 2098 /* Fill the request */ 2099 usbd_setup_isoc_xfer(cb->xfer, ch->pipe, cb, cb->sizes, 2100 UAUDIO_NFRAMES, USBD_NO_COPY, 2101 uaudio_chan_rintr); 2102 2103 (void)usbd_transfer(cb->xfer); 2104 } 2105 2106 void 2107 uaudio_chan_rintr(usbd_xfer_handle xfer, usbd_private_handle priv, 2108 usbd_status status) 2109 { 2110 struct chanbuf *cb = priv; 2111 struct chan *ch = cb->chan; 2112 u_int32_t count; 2113 int s, i, n, frsize; 2114 2115 /* Return if we are aborting. */ 2116 if (status == USBD_CANCELLED) 2117 return; 2118 2119 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 2120 DPRINTFN(5,("uaudio_chan_rintr: count=%d, transferred=%d\n", 2121 count, ch->transferred)); 2122 2123 /* count < cb->size is normal for asynchronous source */ 2124 #ifdef DIAGNOSTIC 2125 if (count > cb->size) { 2126 printf("uaudio_chan_rintr: count(%d) > size(%d)\n", 2127 count, cb->size); 2128 } 2129 #endif 2130 2131 /* 2132 * Transfer data from channel buffer to upper layer buffer, taking 2133 * care of wrapping the upper layer buffer. 2134 */ 2135 for(i = 0; i < UAUDIO_NFRAMES; i++) { 2136 frsize = cb->sizes[i]; 2137 n = min(frsize, ch->end - ch->cur); 2138 memcpy(ch->cur, cb->buffer + cb->offsets[i], n); 2139 ch->cur += n; 2140 if (ch->cur >= ch->end) 2141 ch->cur = ch->start; 2142 if (frsize > n) { 2143 memcpy(ch->cur, cb->buffer + cb->offsets[i] + n, 2144 frsize - n); 2145 ch->cur += frsize - n; 2146 } 2147 } 2148 2149 /* Call back to upper layer */ 2150 ch->transferred += count; 2151 s = splaudio(); 2152 while (ch->transferred >= ch->blksize) { 2153 ch->transferred -= ch->blksize; 2154 DPRINTFN(5,("uaudio_chan_rintr: call %p(%p)\n", 2155 ch->intr, ch->arg)); 2156 ch->intr(ch->arg); 2157 } 2158 splx(s); 2159 2160 /* start next transfer */ 2161 uaudio_chan_rtransfer(ch); 2162 } 2163 2164 void 2165 uaudio_chan_init(struct chan *ch, int altidx, const struct audio_params *param, 2166 int maxpktsize) 2167 { 2168 int samples_per_frame, sample_size; 2169 2170 ch->altidx = altidx; 2171 sample_size = param->precision * param->factor * param->hw_channels / 8; 2172 samples_per_frame = param->hw_sample_rate / USB_FRAMES_PER_SECOND; 2173 ch->sample_size = sample_size; 2174 ch->sample_rate = param->hw_sample_rate; 2175 if (maxpktsize == 0) { 2176 ch->fraction = param->hw_sample_rate % USB_FRAMES_PER_SECOND; 2177 ch->bytes_per_frame = samples_per_frame * sample_size; 2178 } else { 2179 ch->fraction = 0; 2180 ch->bytes_per_frame = maxpktsize; 2181 } 2182 ch->residue = 0; 2183 } 2184 2185 void 2186 uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize) 2187 { 2188 ch->start = start; 2189 ch->end = end; 2190 ch->cur = start; 2191 ch->blksize = blksize; 2192 ch->transferred = 0; 2193 2194 ch->curchanbuf = 0; 2195 } 2196 2197 void 2198 uaudio_get_minmax_rates(int nalts, const struct as_info *alts, 2199 const struct audio_params *p, int mode, 2200 u_long *min, u_long *max) 2201 { 2202 int i, j; 2203 struct usb_audio_streaming_type1_descriptor *a1d; 2204 2205 *min = ULONG_MAX; 2206 *max = 0; 2207 for (i = 0; i < nalts; i++) { 2208 a1d = alts[i].asf1desc; 2209 if (alts[i].sc_busy) 2210 continue; 2211 if (p->hw_channels != a1d->bNrChannels) 2212 continue; 2213 if (p->hw_precision != a1d->bBitResolution) 2214 continue; 2215 if (p->hw_encoding != alts[i].encoding) 2216 continue; 2217 if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress)) 2218 continue; 2219 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) { 2220 DPRINTFN(2,("uaudio_get_minmax_rates: cont %d-%d\n", 2221 UA_SAMP_LO(a1d), UA_SAMP_HI(a1d))); 2222 if (UA_SAMP_LO(a1d) < *min) 2223 *min = UA_SAMP_LO(a1d); 2224 if (UA_SAMP_HI(a1d) > *max) 2225 *max = UA_SAMP_HI(a1d); 2226 } else { 2227 for (j = 0; j < a1d->bSamFreqType; j++) { 2228 DPRINTFN(2,("uaudio_get_minmax_rates: disc #%d: %d\n", 2229 j, UA_GETSAMP(a1d, j))); 2230 if (UA_GETSAMP(a1d, j) < *min) 2231 *min = UA_GETSAMP(a1d, j); 2232 if (UA_GETSAMP(a1d, j) > *max) 2233 *max = UA_GETSAMP(a1d, j); 2234 } 2235 } 2236 } 2237 } 2238 2239 int 2240 uaudio_match_alt_sub(int nalts, const struct as_info *alts, 2241 const struct audio_params *p, int mode, u_long rate) 2242 { 2243 int i, j; 2244 struct usb_audio_streaming_type1_descriptor *a1d; 2245 2246 DPRINTF(("uaudio_match_alt_sub: search for %luHz %dch\n", 2247 rate, p->hw_channels)); 2248 for (i = 0; i < nalts; i++) { 2249 a1d = alts[i].asf1desc; 2250 if (alts[i].sc_busy) 2251 continue; 2252 if (p->hw_channels != a1d->bNrChannels) 2253 continue; 2254 if (p->hw_precision != a1d->bBitResolution) 2255 continue; 2256 if (p->hw_encoding != alts[i].encoding) 2257 continue; 2258 if (mode != UE_GET_DIR(alts[i].edesc->bEndpointAddress)) 2259 continue; 2260 if (a1d->bSamFreqType == UA_SAMP_CONTNUOUS) { 2261 DPRINTFN(2,("uaudio_match_alt_sub: cont %d-%d\n", 2262 UA_SAMP_LO(a1d), UA_SAMP_HI(a1d))); 2263 if (UA_SAMP_LO(a1d) <= rate && rate <= UA_SAMP_HI(a1d)) 2264 return i; 2265 } else { 2266 for (j = 0; j < a1d->bSamFreqType; j++) { 2267 DPRINTFN(2,("uaudio_match_alt_sub: disc #%d: %d\n", 2268 j, UA_GETSAMP(a1d, j))); 2269 /* XXX allow for some slack */ 2270 if (UA_GETSAMP(a1d, j) == rate) 2271 return i; 2272 } 2273 } 2274 } 2275 return -1; 2276 } 2277 2278 int 2279 uaudio_match_alt_chan(int nalts, const struct as_info *alts, 2280 struct audio_params *p, int mode) 2281 { 2282 int i, n; 2283 u_long min, max; 2284 u_long rate; 2285 2286 /* Exact match */ 2287 DPRINTF(("uaudio_match_alt_chan: examine %ldHz %dch %dbit.\n", 2288 p->sample_rate, p->hw_channels, p->hw_precision)); 2289 i = uaudio_match_alt_sub(nalts, alts, p, mode, p->sample_rate); 2290 if (i >= 0) 2291 return i; 2292 2293 uaudio_get_minmax_rates(nalts, alts, p, mode, &min, &max); 2294 DPRINTF(("uaudio_match_alt_chan: min=%lu max=%lu\n", min, max)); 2295 if (max <= 0) 2296 return -1; 2297 /* Search for biggers */ 2298 n = 2; 2299 while ((rate = p->sample_rate * n++) <= max) { 2300 i = uaudio_match_alt_sub(nalts, alts, p, mode, rate); 2301 if (i >= 0) { 2302 p->hw_sample_rate = rate; 2303 return i; 2304 } 2305 } 2306 if (p->sample_rate >= min) { 2307 i = uaudio_match_alt_sub(nalts, alts, p, mode, max); 2308 if (i >= 0) { 2309 p->hw_sample_rate = max; 2310 return i; 2311 } 2312 } else { 2313 i = uaudio_match_alt_sub(nalts, alts, p, mode, min); 2314 if (i >= 0) { 2315 p->hw_sample_rate = min; 2316 return i; 2317 } 2318 } 2319 return -1; 2320 } 2321 2322 int 2323 uaudio_match_alt(int nalts, const struct as_info *alts, 2324 struct audio_params *p, int mode) 2325 { 2326 int i, n; 2327 2328 mode = mode == AUMODE_PLAY ? UE_DIR_OUT : UE_DIR_IN; 2329 i = uaudio_match_alt_chan(nalts, alts, p, mode); 2330 if (i >= 0) 2331 return i; 2332 2333 for (n = p->channels + 1; n <= AUDIO_MAX_CHANNELS; n++) { 2334 p->hw_channels = n; 2335 i = uaudio_match_alt_chan(nalts, alts, p, mode); 2336 if (i >= 0) 2337 return i; 2338 } 2339 2340 if (p->channels != 2) 2341 return -1; 2342 p->hw_channels = 1; 2343 return uaudio_match_alt_chan(nalts, alts, p, mode); 2344 } 2345 2346 int 2347 uaudio_set_params(void *addr, int setmode, int usemode, 2348 struct audio_params *play, struct audio_params *rec) 2349 { 2350 struct uaudio_softc *sc = addr; 2351 int flags = sc->sc_altflags; 2352 int factor; 2353 int enc, i; 2354 int paltidx=-1, raltidx=-1; 2355 void (*swcode)(void *, u_char *buf, int cnt); 2356 struct audio_params *p; 2357 int mode; 2358 2359 if (sc->sc_dying) 2360 return (EIO); 2361 2362 if (((usemode & AUMODE_PLAY) && sc->sc_playchan.pipe != NULL) || 2363 ((usemode & AUMODE_RECORD) && sc->sc_recchan.pipe != NULL)) 2364 return (EBUSY); 2365 2366 if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) 2367 sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0; 2368 if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) 2369 sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0; 2370 2371 for (mode = AUMODE_RECORD; mode != -1; 2372 mode = mode == AUMODE_RECORD ? AUMODE_PLAY : -1) { 2373 if ((setmode & mode) == 0) 2374 continue; 2375 2376 p = (mode == AUMODE_PLAY) ? play : rec; 2377 2378 factor = 1; 2379 swcode = 0; 2380 enc = p->encoding; 2381 switch (enc) { 2382 case AUDIO_ENCODING_SLINEAR_BE: 2383 /* FALLTHROUGH */ 2384 case AUDIO_ENCODING_SLINEAR_LE: 2385 if (enc == AUDIO_ENCODING_SLINEAR_BE 2386 && p->precision == 16 && (flags & HAS_16)) { 2387 swcode = swap_bytes; 2388 enc = AUDIO_ENCODING_SLINEAR_LE; 2389 } else if (p->precision == 8) { 2390 if (flags & HAS_8) { 2391 /* No conversion */ 2392 } else if (flags & HAS_8U) { 2393 swcode = change_sign8; 2394 enc = AUDIO_ENCODING_ULINEAR_LE; 2395 } else if (flags & HAS_16) { 2396 factor = 2; 2397 p->hw_precision = 16; 2398 if (mode == AUMODE_PLAY) 2399 swcode = linear8_to_linear16_le; 2400 else 2401 swcode = linear16_to_linear8_le; 2402 } 2403 } 2404 break; 2405 case AUDIO_ENCODING_ULINEAR_BE: 2406 /* FALLTHROUGH */ 2407 case AUDIO_ENCODING_ULINEAR_LE: 2408 if (p->precision == 16) { 2409 if (enc == AUDIO_ENCODING_ULINEAR_LE) 2410 swcode = change_sign16_le; 2411 else if (mode == AUMODE_PLAY) 2412 swcode = swap_bytes_change_sign16_le; 2413 else 2414 swcode = change_sign16_swap_bytes_le; 2415 enc = AUDIO_ENCODING_SLINEAR_LE; 2416 } else if (p->precision == 8) { 2417 if (flags & HAS_8U) { 2418 /* No conversion */ 2419 } else if (flags & HAS_8) { 2420 swcode = change_sign8; 2421 enc = AUDIO_ENCODING_SLINEAR_LE; 2422 } else if (flags & HAS_16) { 2423 factor = 2; 2424 p->hw_precision = 16; 2425 enc = AUDIO_ENCODING_SLINEAR_LE; 2426 if (mode == AUMODE_PLAY) 2427 swcode = ulinear8_to_slinear16_le; 2428 else 2429 swcode = slinear16_to_ulinear8_le; 2430 } 2431 } 2432 break; 2433 case AUDIO_ENCODING_ULAW: 2434 if (flags & HAS_MULAW) 2435 break; 2436 if (flags & HAS_16) { 2437 if (mode == AUMODE_PLAY) 2438 swcode = mulaw_to_slinear16_le; 2439 else 2440 swcode = slinear16_to_mulaw_le; 2441 factor = 2; 2442 enc = AUDIO_ENCODING_SLINEAR_LE; 2443 p->hw_precision = 16; 2444 } else if (flags & HAS_8U) { 2445 if (mode == AUMODE_PLAY) 2446 swcode = mulaw_to_ulinear8; 2447 else 2448 swcode = ulinear8_to_mulaw; 2449 enc = AUDIO_ENCODING_ULINEAR_LE; 2450 } else if (flags & HAS_8) { 2451 if (mode == AUMODE_PLAY) 2452 swcode = mulaw_to_slinear8; 2453 else 2454 swcode = slinear8_to_mulaw; 2455 enc = AUDIO_ENCODING_SLINEAR_LE; 2456 } else 2457 return (EINVAL); 2458 break; 2459 case AUDIO_ENCODING_ALAW: 2460 if (flags & HAS_ALAW) 2461 break; 2462 if (mode == AUMODE_PLAY && (flags & HAS_16)) { 2463 swcode = alaw_to_slinear16_le; 2464 factor = 2; 2465 enc = AUDIO_ENCODING_SLINEAR_LE; 2466 p->hw_precision = 16; 2467 } else if (flags & HAS_8U) { 2468 if (mode == AUMODE_PLAY) 2469 swcode = alaw_to_ulinear8; 2470 else 2471 swcode = ulinear8_to_alaw; 2472 enc = AUDIO_ENCODING_ULINEAR_LE; 2473 } else if (flags & HAS_8) { 2474 if (mode == AUMODE_PLAY) 2475 swcode = alaw_to_slinear8; 2476 else 2477 swcode = slinear8_to_alaw; 2478 enc = AUDIO_ENCODING_SLINEAR_LE; 2479 } else 2480 return (EINVAL); 2481 break; 2482 default: 2483 return (EINVAL); 2484 } 2485 /* XXX do some other conversions... */ 2486 2487 DPRINTF(("uaudio_set_params: chan=%d prec=%d enc=%d rate=%ld\n", 2488 p->channels, p->hw_precision, enc, p->sample_rate)); 2489 2490 p->hw_encoding = enc; 2491 i = uaudio_match_alt(sc->sc_nalts, sc->sc_alts, p, mode); 2492 if (i < 0) 2493 return (EINVAL); 2494 2495 p->sw_code = swcode; 2496 p->factor = factor; 2497 2498 if (mode == AUMODE_PLAY) 2499 paltidx = i; 2500 else 2501 raltidx = i; 2502 } 2503 2504 if ((setmode & AUMODE_PLAY)) { 2505 /* XXX abort transfer if currently happening? */ 2506 uaudio_chan_init(&sc->sc_playchan, paltidx, play, 0); 2507 } 2508 if ((setmode & AUMODE_RECORD)) { 2509 /* XXX abort transfer if currently happening? */ 2510 uaudio_chan_init(&sc->sc_recchan, raltidx, rec, 2511 UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize)); 2512 } 2513 2514 if ((usemode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) 2515 sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1; 2516 if ((usemode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) 2517 sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1; 2518 2519 DPRINTF(("uaudio_set_params: use altidx=p%d/r%d, altno=p%d/r%d\n", 2520 sc->sc_playchan.altidx, sc->sc_recchan.altidx, 2521 (sc->sc_playchan.altidx >= 0) 2522 ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting 2523 : -1, 2524 (sc->sc_recchan.altidx >= 0) 2525 ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting 2526 : -1)); 2527 2528 return (0); 2529 } 2530 2531 usbd_status 2532 uaudio_set_speed(struct uaudio_softc *sc, int endpt, u_int speed) 2533 { 2534 usb_device_request_t req; 2535 u_int8_t data[3]; 2536 2537 DPRINTFN(5,("uaudio_set_speed: endpt=%d speed=%u\n", endpt, speed)); 2538 req.bmRequestType = UT_WRITE_CLASS_ENDPOINT; 2539 req.bRequest = SET_CUR; 2540 USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0); 2541 USETW(req.wIndex, endpt); 2542 USETW(req.wLength, 3); 2543 data[0] = speed; 2544 data[1] = speed >> 8; 2545 data[2] = speed >> 16; 2546 2547 return (usbd_do_request(sc->sc_udev, &req, data)); 2548 } 2549