1 1.184 mlelstv /* $NetBSD: uaudio.c,v 1.184 2025/04/12 08:12:39 mlelstv Exp $ */ 2 1.1 augustss 3 1.1 augustss /* 4 1.133 mrg * Copyright (c) 1999, 2012 The NetBSD Foundation, Inc. 5 1.1 augustss * All rights reserved. 6 1.1 augustss * 7 1.5 augustss * This code is derived from software contributed to The NetBSD Foundation 8 1.24 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at 9 1.183 mrg * Carlstedt Research & Technology, and Matthew R. Green (mrg (at) eterna23.net). 10 1.1 augustss * 11 1.1 augustss * Redistribution and use in source and binary forms, with or without 12 1.1 augustss * modification, are permitted provided that the following conditions 13 1.1 augustss * are met: 14 1.1 augustss * 1. Redistributions of source code must retain the above copyright 15 1.1 augustss * notice, this list of conditions and the following disclaimer. 16 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 augustss * notice, this list of conditions and the following disclaimer in the 18 1.1 augustss * documentation and/or other materials provided with the distribution. 19 1.1 augustss * 20 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 augustss * POSSIBILITY OF SUCH DAMAGE. 31 1.1 augustss */ 32 1.1 augustss 33 1.1 augustss /* 34 1.144 gson * USB audio specs: http://www.usb.org/developers/docs/devclass_docs/audio10.pdf 35 1.144 gson * http://www.usb.org/developers/docs/devclass_docs/frmts10.pdf 36 1.144 gson * http://www.usb.org/developers/docs/devclass_docs/termt10.pdf 37 1.1 augustss */ 38 1.44 lukem 39 1.44 lukem #include <sys/cdefs.h> 40 1.184 mlelstv __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1.184 2025/04/12 08:12:39 mlelstv Exp $"); 41 1.141 gson 42 1.141 gson #ifdef _KERNEL_OPT 43 1.141 gson #include "opt_usb.h" 44 1.141 gson #endif 45 1.1 augustss 46 1.1 augustss #include <sys/param.h> 47 1.1 augustss #include <sys/systm.h> 48 1.1 augustss #include <sys/kernel.h> 49 1.1 augustss #include <sys/malloc.h> 50 1.1 augustss #include <sys/device.h> 51 1.1 augustss #include <sys/ioctl.h> 52 1.1 augustss #include <sys/file.h> 53 1.40 augustss #include <sys/reboot.h> /* for bootverbose */ 54 1.1 augustss #include <sys/select.h> 55 1.1 augustss #include <sys/proc.h> 56 1.1 augustss #include <sys/vnode.h> 57 1.1 augustss #include <sys/poll.h> 58 1.114 kent #include <sys/module.h> 59 1.119 jmcneill #include <sys/bus.h> 60 1.122 mrg #include <sys/cpu.h> 61 1.136 wiz #include <sys/atomic.h> 62 1.179 mlelstv #include <sys/sysctl.h> 63 1.1 augustss 64 1.1 augustss #include <sys/audioio.h> 65 1.160 isaki #include <dev/audio/audio_if.h> 66 1.1 augustss 67 1.1 augustss #include <dev/usb/usb.h> 68 1.1 augustss #include <dev/usb/usbdi.h> 69 1.119 jmcneill #include <dev/usb/usbdivar.h> 70 1.1 augustss #include <dev/usb/usbdi_util.h> 71 1.1 augustss #include <dev/usb/usb_quirks.h> 72 1.1 augustss 73 1.120 jakllsch #include <dev/usb/usbdevs.h> 74 1.120 jakllsch 75 1.1 augustss #include <dev/usb/uaudioreg.h> 76 1.1 augustss 77 1.80 kent /* #define UAUDIO_DEBUG */ 78 1.175 mlelstv #define UAUDIO_MULTIPLE_ENDPOINTS 79 1.4 augustss #ifdef UAUDIO_DEBUG 80 1.122 mrg #define DPRINTF(x,y...) do { \ 81 1.122 mrg if (uaudiodebug) { \ 82 1.122 mrg struct lwp *l = curlwp; \ 83 1.122 mrg printf("%s[%d:%d]: "x, __func__, l->l_proc->p_pid, l->l_lid, y); \ 84 1.122 mrg } \ 85 1.122 mrg } while (0) 86 1.122 mrg #define DPRINTFN_CLEAN(n,x...) do { \ 87 1.122 mrg if (uaudiodebug > (n)) \ 88 1.122 mrg printf(x); \ 89 1.122 mrg } while (0) 90 1.122 mrg #define DPRINTFN(n,x,y...) do { \ 91 1.122 mrg if (uaudiodebug > (n)) { \ 92 1.122 mrg struct lwp *l = curlwp; \ 93 1.122 mrg printf("%s[%d:%d]: "x, __func__, l->l_proc->p_pid, l->l_lid, y); \ 94 1.122 mrg } \ 95 1.122 mrg } while (0) 96 1.135 mrg int uaudiodebug = 0; 97 1.1 augustss #else 98 1.122 mrg #define DPRINTF(x,y...) 99 1.122 mrg #define DPRINTFN_CLEAN(n,x...) 100 1.122 mrg #define DPRINTFN(n,x,y...) 101 1.1 augustss #endif 102 1.1 augustss 103 1.179 mlelstv /* number of outstanding requests */ 104 1.179 mlelstv #define UAUDIO_NCHANBUFS 6 105 1.179 mlelstv /* number of USB frames per request, also the number of ms */ 106 1.179 mlelstv #define UAUDIO_NFRAMES 10 107 1.179 mlelstv /* number of microframes per requewst (high, super) */ 108 1.181 mlelstv #define UAUDIO_NFRAMES_HI 40 109 1.1 augustss 110 1.1 augustss 111 1.1 augustss #define MIX_MAX_CHAN 8 112 1.175 mlelstv struct range { 113 1.175 mlelstv int minval, maxval, resval; 114 1.175 mlelstv }; 115 1.175 mlelstv 116 1.1 augustss struct mixerctl { 117 1.94 kent uint16_t wValue[MIX_MAX_CHAN]; /* using nchan */ 118 1.94 kent uint16_t wIndex; 119 1.94 kent uint8_t nchan; 120 1.94 kent uint8_t type; 121 1.175 mlelstv #define MIX_ON_OFF 0x01 122 1.175 mlelstv #define MIX_SELECTOR 0x02 123 1.175 mlelstv #define MIX_SIGNED_8 0x10 124 1.175 mlelstv #define MIX_UNSIGNED_8 0x18 125 1.175 mlelstv #define MIX_SIGNED_16 0x20 126 1.175 mlelstv #define MIX_UNSIGNED_16 0x28 127 1.175 mlelstv #define MIX_SIGNED_32 0x40 128 1.175 mlelstv #define MIX_UNSIGNED_32 0x48 129 1.175 mlelstv #define MIX_SIZE(n) ( \ 130 1.175 mlelstv ((n) == MIX_UNSIGNED_32 || (n) == MIX_SIGNED_32) ? 4 : \ 131 1.175 mlelstv ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16) ? 2 : 1 ) 132 1.175 mlelstv #define MIX_UNSIGNED(n) ( \ 133 1.175 mlelstv (n) == MIX_UNSIGNED_8 || \ 134 1.175 mlelstv (n) == MIX_UNSIGNED_16 || \ 135 1.175 mlelstv (n) == MIX_UNSIGNED_32 ) 136 1.175 mlelstv struct range range0; 137 1.175 mlelstv struct range *ranges; 138 1.175 mlelstv u_int nranges; 139 1.34 augustss u_int delta; 140 1.34 augustss u_int mul; 141 1.94 kent uint8_t class; 142 1.1 augustss char ctlname[MAX_AUDIO_DEV_LEN]; 143 1.99 christos const char *ctlunit; 144 1.1 augustss }; 145 1.1 augustss #define MAKE(h,l) (((h) << 8) | (l)) 146 1.1 augustss 147 1.1 augustss struct as_info { 148 1.94 kent uint8_t alt; 149 1.94 kent uint8_t encoding; 150 1.175 mlelstv uint8_t nchan; 151 1.94 kent uint8_t attributes; /* Copy of bmAttributes of 152 1.50 kent * usb_audio_streaming_endpoint_descriptor 153 1.50 kent */ 154 1.179 mlelstv uint8_t terminal; /* connected Terminal ID */ 155 1.146 skrll struct usbd_interface * ifaceh; 156 1.78 kent const usb_interface_descriptor_t *idesc; 157 1.78 kent const usb_endpoint_descriptor_audio_t *edesc; 158 1.80 kent const usb_endpoint_descriptor_audio_t *edesc1; 159 1.175 mlelstv const union usb_audio_streaming_type1_descriptor *asf1desc; 160 1.92 kent struct audio_format *aformat; 161 1.47 jdolecek int sc_busy; /* currently used */ 162 1.1 augustss }; 163 1.1 augustss 164 1.1 augustss struct chan { 165 1.67 wiz void (*intr)(void *); /* DMA completion intr handler */ 166 1.1 augustss void *arg; /* arg for intr() */ 167 1.146 skrll struct usbd_pipe *pipe; 168 1.146 skrll struct usbd_pipe *sync_pipe; 169 1.1 augustss 170 1.1 augustss u_int sample_size; 171 1.1 augustss u_int sample_rate; 172 1.1 augustss u_int bytes_per_frame; 173 1.1 augustss u_int fraction; /* fraction/1000 is the extra samples/frame */ 174 1.1 augustss u_int residue; /* accumulates the fractional samples */ 175 1.1 augustss 176 1.1 augustss u_char *start; /* upper layer buffer start */ 177 1.1 augustss u_char *end; /* upper layer buffer end */ 178 1.1 augustss u_char *cur; /* current position in upper layer buffer */ 179 1.1 augustss int blksize; /* chunk size to report up */ 180 1.1 augustss int transferred; /* transferred bytes not reported up */ 181 1.1 augustss 182 1.47 jdolecek int altidx; /* currently used altidx */ 183 1.31 augustss 184 1.1 augustss int curchanbuf; 185 1.179 mlelstv u_int nframes; /* UAUDIO_NFRAMES or UAUDIO_NFRAMES_HI */ 186 1.179 mlelstv u_int nchanbufs; /* 1..UAUDIO_NCHANBUFS */ 187 1.1 augustss struct chanbuf { 188 1.56 kent struct chan *chan; 189 1.146 skrll struct usbd_xfer *xfer; 190 1.56 kent u_char *buffer; 191 1.179 mlelstv uint16_t sizes[UAUDIO_NFRAMES_HI]; 192 1.179 mlelstv uint16_t offsets[UAUDIO_NFRAMES_HI]; 193 1.94 kent uint16_t size; 194 1.1 augustss } chanbufs[UAUDIO_NCHANBUFS]; 195 1.8 augustss 196 1.8 augustss struct uaudio_softc *sc; /* our softc */ 197 1.1 augustss }; 198 1.1 augustss 199 1.121 jmcneill /* 200 1.146 skrll * The MI USB audio subsystem is now MP-SAFE and expects sc_intr_lock to be 201 1.146 skrll * held on entry the callbacks passed to uaudio_trigger_{in,out}put 202 1.121 jmcneill */ 203 1.1 augustss struct uaudio_softc { 204 1.118 dyoung device_t sc_dev; /* base device */ 205 1.121 jmcneill kmutex_t sc_lock; 206 1.121 jmcneill kmutex_t sc_intr_lock; 207 1.146 skrll struct usbd_device *sc_udev; /* USB device */ 208 1.175 mlelstv int sc_version; 209 1.86 kent int sc_ac_iface; /* Audio Control interface */ 210 1.146 skrll struct usbd_interface * sc_ac_ifaceh; 211 1.86 kent struct chan sc_playchan; /* play channel */ 212 1.86 kent struct chan sc_recchan; /* record channel */ 213 1.86 kent int sc_nullalt; 214 1.86 kent int sc_audio_rev; 215 1.86 kent struct as_info *sc_alts; /* alternate settings */ 216 1.86 kent int sc_nalts; /* # of alternate settings */ 217 1.86 kent int sc_altflags; 218 1.56 kent #define HAS_8 0x01 219 1.56 kent #define HAS_16 0x02 220 1.56 kent #define HAS_8U 0x04 221 1.56 kent #define HAS_ALAW 0x08 222 1.56 kent #define HAS_MULAW 0x10 223 1.47 jdolecek #define UA_NOFRAC 0x20 /* don't do sample rate adjustment */ 224 1.51 kent #define HAS_24 0x40 225 1.175 mlelstv #define HAS_32 0x80 226 1.86 kent int sc_mode; /* play/record capability */ 227 1.86 kent struct mixerctl *sc_ctls; /* mixer controls */ 228 1.86 kent int sc_nctls; /* # of mixer controls */ 229 1.117 dyoung device_t sc_audiodev; 230 1.175 mlelstv int sc_nratectls; /* V2 sample rates */ 231 1.175 mlelstv int sc_ratectls[AUFMT_MAX_FREQUENCIES]; 232 1.178 mlelstv int sc_ratemode[AUFMT_MAX_FREQUENCIES]; 233 1.179 mlelstv int sc_playclock; 234 1.179 mlelstv int sc_recclock; 235 1.92 kent struct audio_format *sc_formats; 236 1.92 kent int sc_nformats; 237 1.179 mlelstv uint8_t sc_clock[256]; /* map terminals to clocks */ 238 1.92 kent u_int sc_channel_config; 239 1.179 mlelstv u_int sc_usb_frames_per_second; 240 1.86 kent char sc_dying; 241 1.119 jmcneill struct audio_device sc_adev; 242 1.1 augustss }; 243 1.1 augustss 244 1.82 kent struct terminal_list { 245 1.82 kent int size; 246 1.82 kent uint16_t terminals[1]; 247 1.82 kent }; 248 1.82 kent #define TERMINAL_LIST_SIZE(N) (offsetof(struct terminal_list, terminals) \ 249 1.82 kent + sizeof(uint16_t) * (N)) 250 1.82 kent 251 1.82 kent struct io_terminal { 252 1.82 kent union { 253 1.109 drochner const uaudio_cs_descriptor_t *desc; 254 1.178 mlelstv const union usb_audio_input_terminal *it; 255 1.178 mlelstv const union usb_audio_output_terminal *ot; 256 1.82 kent const struct usb_audio_mixer_unit *mu; 257 1.82 kent const struct usb_audio_selector_unit *su; 258 1.179 mlelstv const union usb_audio_feature_unit *fu; 259 1.82 kent const struct usb_audio_processing_unit *pu; 260 1.82 kent const struct usb_audio_extension_unit *eu; 261 1.175 mlelstv const struct usb_audio_clksrc_unit *cu; 262 1.175 mlelstv const struct usb_audio_clksel_unit *lu; 263 1.82 kent } d; 264 1.82 kent int inputs_size; 265 1.82 kent struct terminal_list **inputs; /* list of source input terminals */ 266 1.82 kent struct terminal_list *output; /* list of destination output terminals */ 267 1.83 kent int direct; /* directly connected to an output terminal */ 268 1.179 mlelstv uint8_t clock; 269 1.82 kent }; 270 1.82 kent 271 1.82 kent #define UAC_OUTPUT 0 272 1.82 kent #define UAC_INPUT 1 273 1.82 kent #define UAC_EQUAL 2 274 1.82 kent #define UAC_RECORD 3 275 1.82 kent #define UAC_NCLASSES 4 276 1.82 kent #ifdef UAUDIO_DEBUG 277 1.82 kent Static const char *uac_names[] = { 278 1.175 mlelstv AudioCoutputs, AudioCinputs, AudioCequalization, AudioCrecord 279 1.82 kent }; 280 1.82 kent #endif 281 1.1 augustss 282 1.142 gson #ifdef UAUDIO_DEBUG 283 1.142 gson Static void uaudio_dump_tml 284 1.142 gson (struct terminal_list *tml); 285 1.142 gson #endif 286 1.86 kent Static usbd_status uaudio_identify_ac 287 1.86 kent (struct uaudio_softc *, const usb_config_descriptor_t *); 288 1.86 kent Static usbd_status uaudio_identify_as 289 1.86 kent (struct uaudio_softc *, const usb_config_descriptor_t *); 290 1.86 kent Static usbd_status uaudio_process_as 291 1.86 kent (struct uaudio_softc *, const char *, int *, int, 292 1.86 kent const usb_interface_descriptor_t *); 293 1.78 kent 294 1.78 kent Static void uaudio_add_alt(struct uaudio_softc *, const struct as_info *); 295 1.78 kent 296 1.78 kent Static const usb_interface_descriptor_t *uaudio_find_iface 297 1.78 kent (const char *, int, int *, int); 298 1.78 kent 299 1.78 kent Static void uaudio_mixer_add_ctl(struct uaudio_softc *, struct mixerctl *); 300 1.86 kent Static char *uaudio_id_name 301 1.179 mlelstv (struct uaudio_softc *, const struct io_terminal *, uint8_t); 302 1.91 kent #ifdef UAUDIO_DEBUG 303 1.178 mlelstv Static void uaudio_dump_cluster 304 1.178 mlelstv (struct uaudio_softc *, const union usb_audio_cluster *); 305 1.91 kent #endif 306 1.178 mlelstv Static union usb_audio_cluster uaudio_get_cluster 307 1.178 mlelstv (struct uaudio_softc *, int, const struct io_terminal *); 308 1.86 kent Static void uaudio_add_input 309 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 310 1.86 kent Static void uaudio_add_output 311 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 312 1.86 kent Static void uaudio_add_mixer 313 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 314 1.86 kent Static void uaudio_add_selector 315 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 316 1.82 kent #ifdef UAUDIO_DEBUG 317 1.82 kent Static const char *uaudio_get_terminal_name(int); 318 1.82 kent #endif 319 1.86 kent Static int uaudio_determine_class 320 1.86 kent (const struct io_terminal *, struct mixerctl *); 321 1.86 kent Static const char *uaudio_feature_name 322 1.179 mlelstv (const struct io_terminal *, uint8_t, int); 323 1.86 kent Static void uaudio_add_feature 324 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 325 1.86 kent Static void uaudio_add_processing_updown 326 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 327 1.86 kent Static void uaudio_add_processing 328 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 329 1.175 mlelstv Static void uaudio_add_effect 330 1.175 mlelstv (struct uaudio_softc *, const struct io_terminal *, int); 331 1.86 kent Static void uaudio_add_extension 332 1.86 kent (struct uaudio_softc *, const struct io_terminal *, int); 333 1.175 mlelstv Static void uaudio_add_clksrc 334 1.175 mlelstv (struct uaudio_softc *, const struct io_terminal *, int); 335 1.175 mlelstv Static void uaudio_add_clksel 336 1.175 mlelstv (struct uaudio_softc *, const struct io_terminal *, int); 337 1.86 kent Static struct terminal_list *uaudio_merge_terminal_list 338 1.86 kent (const struct io_terminal *); 339 1.86 kent Static struct terminal_list *uaudio_io_terminaltype 340 1.178 mlelstv (struct uaudio_softc *, int, struct io_terminal *, int); 341 1.86 kent Static usbd_status uaudio_identify 342 1.86 kent (struct uaudio_softc *, const usb_config_descriptor_t *); 343 1.175 mlelstv Static u_int uaudio_get_rates 344 1.178 mlelstv (struct uaudio_softc *, int, u_int *, u_int); 345 1.175 mlelstv Static void uaudio_build_formats 346 1.175 mlelstv (struct uaudio_softc *); 347 1.78 kent 348 1.78 kent Static int uaudio_signext(int, int); 349 1.78 kent Static int uaudio_value2bsd(struct mixerctl *, int); 350 1.78 kent Static int uaudio_bsd2value(struct mixerctl *, int); 351 1.175 mlelstv Static const char *uaudio_clockname(u_int); 352 1.175 mlelstv Static int uaudio_makename 353 1.175 mlelstv (struct uaudio_softc *, uByte, const char *, uByte, char *, size_t); 354 1.78 kent Static int uaudio_get(struct uaudio_softc *, int, int, int, int, int); 355 1.175 mlelstv Static int uaudio_getbuf(struct uaudio_softc *, int, int, int, int, int, uint8_t *); 356 1.86 kent Static int uaudio_ctl_get 357 1.86 kent (struct uaudio_softc *, int, struct mixerctl *, int); 358 1.86 kent Static void uaudio_set 359 1.86 kent (struct uaudio_softc *, int, int, int, int, int, int); 360 1.86 kent Static void uaudio_ctl_set 361 1.86 kent (struct uaudio_softc *, int, struct mixerctl *, int, int); 362 1.78 kent 363 1.179 mlelstv Static usbd_status uaudio_speed(struct uaudio_softc *, int, int, uint8_t *, int); 364 1.175 mlelstv Static usbd_status uaudio_set_speed(struct uaudio_softc *, int, int, u_int); 365 1.78 kent 366 1.78 kent Static usbd_status uaudio_chan_open(struct uaudio_softc *, struct chan *); 367 1.146 skrll Static void uaudio_chan_abort(struct uaudio_softc *, struct chan *); 368 1.78 kent Static void uaudio_chan_close(struct uaudio_softc *, struct chan *); 369 1.86 kent Static usbd_status uaudio_chan_alloc_buffers 370 1.86 kent (struct uaudio_softc *, struct chan *); 371 1.78 kent Static void uaudio_chan_free_buffers(struct uaudio_softc *, struct chan *); 372 1.86 kent Static void uaudio_chan_init 373 1.179 mlelstv (struct chan *, int, const struct audio_params *, int, bool); 374 1.78 kent Static void uaudio_chan_set_param(struct chan *, u_char *, u_char *, int); 375 1.78 kent Static void uaudio_chan_ptransfer(struct chan *); 376 1.86 kent Static void uaudio_chan_pintr 377 1.146 skrll (struct usbd_xfer *, void *, usbd_status); 378 1.78 kent 379 1.78 kent Static void uaudio_chan_rtransfer(struct chan *); 380 1.86 kent Static void uaudio_chan_rintr 381 1.146 skrll (struct usbd_xfer *, void *, usbd_status); 382 1.78 kent 383 1.78 kent Static int uaudio_open(void *, int); 384 1.160 isaki Static int uaudio_query_format(void *, audio_format_query_t *); 385 1.160 isaki Static int uaudio_set_format 386 1.160 isaki (void *, int, const audio_params_t *, const audio_params_t *, 387 1.160 isaki audio_filter_reg_t *, audio_filter_reg_t *); 388 1.93 kent Static int uaudio_round_blocksize(void *, int, int, const audio_params_t *); 389 1.86 kent Static int uaudio_trigger_output 390 1.86 kent (void *, void *, void *, int, void (*)(void *), void *, 391 1.93 kent const audio_params_t *); 392 1.86 kent Static int uaudio_trigger_input 393 1.86 kent (void *, void *, void *, int, void (*)(void *), void *, 394 1.93 kent const audio_params_t *); 395 1.78 kent Static int uaudio_halt_in_dma(void *); 396 1.78 kent Static int uaudio_halt_out_dma(void *); 397 1.166 jdc Static void uaudio_halt_in_dma_unlocked(struct uaudio_softc *); 398 1.166 jdc Static void uaudio_halt_out_dma_unlocked(struct uaudio_softc *); 399 1.78 kent Static int uaudio_getdev(void *, struct audio_device *); 400 1.78 kent Static int uaudio_mixer_set_port(void *, mixer_ctrl_t *); 401 1.78 kent Static int uaudio_mixer_get_port(void *, mixer_ctrl_t *); 402 1.78 kent Static int uaudio_query_devinfo(void *, mixer_devinfo_t *); 403 1.78 kent Static int uaudio_get_props(void *); 404 1.121 jmcneill Static void uaudio_get_locks(void *, kmutex_t **, kmutex_t **); 405 1.1 augustss 406 1.88 yamt Static const struct audio_hw_if uaudio_hw_if = { 407 1.158 isaki .open = uaudio_open, 408 1.160 isaki .query_format = uaudio_query_format, 409 1.160 isaki .set_format = uaudio_set_format, 410 1.158 isaki .round_blocksize = uaudio_round_blocksize, 411 1.158 isaki .halt_output = uaudio_halt_out_dma, 412 1.158 isaki .halt_input = uaudio_halt_in_dma, 413 1.158 isaki .getdev = uaudio_getdev, 414 1.158 isaki .set_port = uaudio_mixer_set_port, 415 1.158 isaki .get_port = uaudio_mixer_get_port, 416 1.158 isaki .query_devinfo = uaudio_query_devinfo, 417 1.158 isaki .get_props = uaudio_get_props, 418 1.158 isaki .trigger_output = uaudio_trigger_output, 419 1.158 isaki .trigger_input = uaudio_trigger_input, 420 1.158 isaki .get_locks = uaudio_get_locks, 421 1.1 augustss }; 422 1.1 augustss 423 1.163 maxv static int uaudio_match(device_t, cfdata_t, void *); 424 1.163 maxv static void uaudio_attach(device_t, device_t, void *); 425 1.163 maxv static int uaudio_detach(device_t, int); 426 1.163 maxv static void uaudio_childdet(device_t, device_t); 427 1.163 maxv static int uaudio_activate(device_t, enum devact); 428 1.111 dyoung 429 1.159 mrg 430 1.113 cube CFATTACH_DECL2_NEW(uaudio, sizeof(struct uaudio_softc), 431 1.111 dyoung uaudio_match, uaudio_attach, uaudio_detach, uaudio_activate, NULL, 432 1.111 dyoung uaudio_childdet); 433 1.1 augustss 434 1.163 maxv static int 435 1.118 dyoung uaudio_match(device_t parent, cfdata_t match, void *aux) 436 1.1 augustss { 437 1.146 skrll struct usbif_attach_arg *uiaa = aux; 438 1.1 augustss 439 1.1 augustss /* Trigger on the control interface. */ 440 1.146 skrll if (uiaa->uiaa_class != UICLASS_AUDIO || 441 1.146 skrll uiaa->uiaa_subclass != UISUBCLASS_AUDIOCONTROL || 442 1.146 skrll (usbd_get_quirks(uiaa->uiaa_device)->uq_flags & UQ_BAD_AUDIO)) 443 1.94 kent return UMATCH_NONE; 444 1.1 augustss 445 1.94 kent return UMATCH_IFACECLASS_IFACESUBCLASS; 446 1.1 augustss } 447 1.1 augustss 448 1.163 maxv static void 449 1.118 dyoung uaudio_attach(device_t parent, device_t self, void *aux) 450 1.1 augustss { 451 1.118 dyoung struct uaudio_softc *sc = device_private(self); 452 1.146 skrll struct usbif_attach_arg *uiaa = aux; 453 1.1 augustss usb_interface_descriptor_t *id; 454 1.1 augustss usb_config_descriptor_t *cdesc; 455 1.98 augustss char *devinfop; 456 1.9 augustss usbd_status err; 457 1.37 mycroft int i, j, found; 458 1.1 augustss 459 1.113 cube sc->sc_dev = self; 460 1.146 skrll sc->sc_udev = uiaa->uiaa_device; 461 1.121 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 462 1.146 skrll mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SOFTUSB); 463 1.116 plunky 464 1.119 jmcneill strlcpy(sc->sc_adev.name, "USB audio", sizeof(sc->sc_adev.name)); 465 1.119 jmcneill strlcpy(sc->sc_adev.version, "", sizeof(sc->sc_adev.version)); 466 1.119 jmcneill snprintf(sc->sc_adev.config, sizeof(sc->sc_adev.config), "usb:%08x", 467 1.146 skrll sc->sc_udev->ud_cookie.cookie); 468 1.119 jmcneill 469 1.116 plunky aprint_naive("\n"); 470 1.116 plunky aprint_normal("\n"); 471 1.113 cube 472 1.146 skrll devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0); 473 1.116 plunky aprint_normal_dev(self, "%s\n", devinfop); 474 1.98 augustss usbd_devinfo_free(devinfop); 475 1.1 augustss 476 1.1 augustss cdesc = usbd_get_config_descriptor(sc->sc_udev); 477 1.13 augustss if (cdesc == NULL) { 478 1.113 cube aprint_error_dev(self, 479 1.113 cube "failed to get configuration descriptor\n"); 480 1.118 dyoung return; 481 1.13 augustss } 482 1.1 augustss 483 1.9 augustss err = uaudio_identify(sc, cdesc); 484 1.9 augustss if (err) { 485 1.113 cube aprint_error_dev(self, 486 1.113 cube "audio descriptors make no sense, error=%d\n", err); 487 1.118 dyoung return; 488 1.1 augustss } 489 1.1 augustss 490 1.146 skrll sc->sc_ac_ifaceh = uiaa->uiaa_iface; 491 1.1 augustss /* Pick up the AS interface. */ 492 1.146 skrll for (i = 0; i < uiaa->uiaa_nifaces; i++) { 493 1.146 skrll if (uiaa->uiaa_ifaces[i] == NULL) 494 1.37 mycroft continue; 495 1.146 skrll id = usbd_get_interface_descriptor(uiaa->uiaa_ifaces[i]); 496 1.37 mycroft if (id == NULL) 497 1.37 mycroft continue; 498 1.37 mycroft found = 0; 499 1.37 mycroft for (j = 0; j < sc->sc_nalts; j++) { 500 1.37 mycroft if (id->bInterfaceNumber == 501 1.37 mycroft sc->sc_alts[j].idesc->bInterfaceNumber) { 502 1.146 skrll sc->sc_alts[j].ifaceh = uiaa->uiaa_ifaces[i]; 503 1.37 mycroft found = 1; 504 1.1 augustss } 505 1.1 augustss } 506 1.37 mycroft if (found) 507 1.146 skrll uiaa->uiaa_ifaces[i] = NULL; 508 1.1 augustss } 509 1.1 augustss 510 1.37 mycroft for (j = 0; j < sc->sc_nalts; j++) { 511 1.37 mycroft if (sc->sc_alts[j].ifaceh == NULL) { 512 1.113 cube aprint_error_dev(self, 513 1.113 cube "alt %d missing AS interface(s)\n", j); 514 1.118 dyoung return; 515 1.37 mycroft } 516 1.1 augustss } 517 1.1 augustss 518 1.113 cube aprint_normal_dev(self, "audio rev %d.%02x\n", 519 1.7 augustss sc->sc_audio_rev >> 8, sc->sc_audio_rev & 0xff); 520 1.7 augustss 521 1.47 jdolecek sc->sc_playchan.sc = sc->sc_recchan.sc = sc; 522 1.60 kent sc->sc_playchan.altidx = -1; 523 1.60 kent sc->sc_recchan.altidx = -1; 524 1.8 augustss 525 1.179 mlelstv switch (sc->sc_udev->ud_speed) { 526 1.179 mlelstv case USB_SPEED_LOW: 527 1.179 mlelstv case USB_SPEED_FULL: 528 1.179 mlelstv sc->sc_usb_frames_per_second = USB_FRAMES_PER_SECOND; 529 1.179 mlelstv sc->sc_playchan.nframes = 530 1.179 mlelstv sc->sc_recchan.nframes = UAUDIO_NFRAMES; 531 1.179 mlelstv break; 532 1.179 mlelstv default: /* HIGH, SUPER, SUPER_PLUS, more ? */ 533 1.179 mlelstv sc->sc_usb_frames_per_second = USB_FRAMES_PER_SECOND * USB_UFRAMES_PER_FRAME; 534 1.179 mlelstv sc->sc_playchan.nframes = 535 1.179 mlelstv sc->sc_recchan.nframes = UAUDIO_NFRAMES_HI; 536 1.179 mlelstv break; 537 1.179 mlelstv } 538 1.179 mlelstv sc->sc_playchan.nchanbufs = 539 1.179 mlelstv sc->sc_recchan.nchanbufs = UAUDIO_NCHANBUFS; 540 1.179 mlelstv 541 1.179 mlelstv DPRINTF("usb fps %u, max channel frames %u, max channel buffers %u\n", 542 1.179 mlelstv sc->sc_usb_frames_per_second, sc->sc_playchan.nframes, sc->sc_playchan.nchanbufs); 543 1.179 mlelstv 544 1.31 augustss if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_FRAC) 545 1.47 jdolecek sc->sc_altflags |= UA_NOFRAC; 546 1.31 augustss 547 1.40 augustss #ifndef UAUDIO_DEBUG 548 1.40 augustss if (bootverbose) 549 1.40 augustss #endif 550 1.113 cube aprint_normal_dev(self, "%d mixer controls\n", 551 1.40 augustss sc->sc_nctls); 552 1.40 augustss 553 1.147 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); 554 1.41 augustss 555 1.122 mrg DPRINTF("%s", "doing audio_attach_mi\n"); 556 1.113 cube sc->sc_audiodev = audio_attach_mi(&uaudio_hw_if, sc, sc->sc_dev); 557 1.17 augustss 558 1.155 maya if (!pmf_device_register(self, NULL, NULL)) 559 1.155 maya aprint_error_dev(self, "couldn't establish power handler\n"); 560 1.155 maya 561 1.118 dyoung return; 562 1.1 augustss } 563 1.1 augustss 564 1.163 maxv static int 565 1.117 dyoung uaudio_activate(device_t self, enum devact act) 566 1.1 augustss { 567 1.117 dyoung struct uaudio_softc *sc = device_private(self); 568 1.1 augustss 569 1.1 augustss switch (act) { 570 1.1 augustss case DVACT_DEACTIVATE: 571 1.1 augustss sc->sc_dying = 1; 572 1.117 dyoung return 0; 573 1.117 dyoung default: 574 1.117 dyoung return EOPNOTSUPP; 575 1.1 augustss } 576 1.1 augustss } 577 1.1 augustss 578 1.163 maxv static void 579 1.111 dyoung uaudio_childdet(device_t self, device_t child) 580 1.111 dyoung { 581 1.111 dyoung struct uaudio_softc *sc = device_private(self); 582 1.111 dyoung 583 1.111 dyoung KASSERT(sc->sc_audiodev == child); 584 1.111 dyoung sc->sc_audiodev = NULL; 585 1.111 dyoung } 586 1.111 dyoung 587 1.163 maxv static int 588 1.111 dyoung uaudio_detach(device_t self, int flags) 589 1.1 augustss { 590 1.111 dyoung struct uaudio_softc *sc = device_private(self); 591 1.175 mlelstv int rv, i; 592 1.155 maya 593 1.166 jdc sc->sc_dying = 1; 594 1.166 jdc 595 1.155 maya pmf_device_deregister(self); 596 1.1 augustss 597 1.8 augustss /* Wait for outstanding requests to complete. */ 598 1.166 jdc uaudio_halt_out_dma_unlocked(sc); 599 1.166 jdc uaudio_halt_in_dma_unlocked(sc); 600 1.8 augustss 601 1.170 mlelstv if (sc->sc_audiodev != NULL) { 602 1.1 augustss rv = config_detach(sc->sc_audiodev, flags); 603 1.170 mlelstv if (rv) 604 1.170 mlelstv return rv; 605 1.170 mlelstv } 606 1.17 augustss 607 1.147 msaitoh usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev); 608 1.1 augustss 609 1.92 kent if (sc->sc_formats != NULL) 610 1.146 skrll kmem_free(sc->sc_formats, 611 1.146 skrll sizeof(struct audio_format) * sc->sc_nformats); 612 1.121 jmcneill 613 1.175 mlelstv if (sc->sc_ctls != NULL) { 614 1.175 mlelstv for (i=0; i<sc->sc_nctls; ++i) { 615 1.175 mlelstv if (sc->sc_ctls[i].nranges == 0) 616 1.175 mlelstv continue; 617 1.175 mlelstv kmem_free( sc->sc_ctls[i].ranges, 618 1.175 mlelstv sc->sc_ctls[i].nranges * sizeof(struct range)); 619 1.175 mlelstv } 620 1.175 mlelstv kmem_free(sc->sc_ctls, sizeof(struct mixerctl) * sc->sc_nctls); 621 1.175 mlelstv } 622 1.175 mlelstv 623 1.175 mlelstv if (sc->sc_alts != NULL) 624 1.175 mlelstv kmem_free(sc->sc_alts, sizeof(struct as_info) * sc->sc_nalts); 625 1.175 mlelstv 626 1.121 jmcneill mutex_destroy(&sc->sc_lock); 627 1.121 jmcneill mutex_destroy(&sc->sc_intr_lock); 628 1.121 jmcneill 629 1.170 mlelstv return 0; 630 1.1 augustss } 631 1.1 augustss 632 1.86 kent Static int 633 1.160 isaki uaudio_query_format(void *addr, audio_format_query_t *afp) 634 1.1 augustss { 635 1.94 kent struct uaudio_softc *sc; 636 1.1 augustss 637 1.94 kent sc = addr; 638 1.160 isaki return audio_query_format(sc->sc_formats, sc->sc_nformats, afp); 639 1.1 augustss } 640 1.1 augustss 641 1.86 kent Static const usb_interface_descriptor_t * 642 1.99 christos uaudio_find_iface(const char *tbuf, int size, int *offsp, int subtype) 643 1.1 augustss { 644 1.78 kent const usb_interface_descriptor_t *d; 645 1.1 augustss 646 1.172 mlelstv while (*offsp + sizeof(*d) <= size) { 647 1.99 christos d = (const void *)(tbuf + *offsp); 648 1.172 mlelstv DPRINTFN(3, "%d + %d <= %d type %d class %d/%d iface %d\n", 649 1.172 mlelstv *offsp, d->bLength, size, 650 1.172 mlelstv d->bDescriptorType, 651 1.172 mlelstv d->bInterfaceClass, 652 1.172 mlelstv d->bInterfaceSubClass, 653 1.172 mlelstv d->bInterfaceNumber); 654 1.1 augustss *offsp += d->bLength; 655 1.1 augustss if (d->bDescriptorType == UDESC_INTERFACE && 656 1.19 augustss d->bInterfaceClass == UICLASS_AUDIO && 657 1.1 augustss d->bInterfaceSubClass == subtype) 658 1.94 kent return d; 659 1.1 augustss } 660 1.94 kent return NULL; 661 1.1 augustss } 662 1.1 augustss 663 1.86 kent Static void 664 1.26 augustss uaudio_mixer_add_ctl(struct uaudio_softc *sc, struct mixerctl *mc) 665 1.1 augustss { 666 1.33 augustss int res; 667 1.175 mlelstv size_t len, count, msz; 668 1.84 kent struct mixerctl *nmc; 669 1.175 mlelstv struct range *r; 670 1.175 mlelstv uint8_t *buf, *p; 671 1.175 mlelstv int i; 672 1.33 augustss 673 1.82 kent if (mc->class < UAC_NCLASSES) { 674 1.122 mrg DPRINTF("adding %s.%s\n", uac_names[mc->class], mc->ctlname); 675 1.82 kent } else { 676 1.122 mrg DPRINTF("adding %s\n", mc->ctlname); 677 1.82 kent } 678 1.84 kent len = sizeof(*mc) * (sc->sc_nctls + 1); 679 1.146 skrll nmc = kmem_alloc(len, KM_SLEEP); 680 1.84 kent /* Copy old data, if there was any */ 681 1.84 kent if (sc->sc_nctls != 0) { 682 1.175 mlelstv memcpy(nmc, sc->sc_ctls, sizeof(*mc) * sc->sc_nctls); 683 1.175 mlelstv for (i = 0; i<sc->sc_nctls; ++i) { 684 1.175 mlelstv if (sc->sc_ctls[i].ranges == &sc->sc_ctls[i].range0) 685 1.175 mlelstv nmc[i].ranges = &nmc[i].range0; 686 1.175 mlelstv } 687 1.146 skrll kmem_free(sc->sc_ctls, sizeof(*mc) * sc->sc_nctls); 688 1.84 kent } 689 1.42 christos sc->sc_ctls = nmc; 690 1.1 augustss 691 1.175 mlelstv /* 692 1.175 mlelstv * preset 693 1.175 mlelstv * - mc->class 694 1.175 mlelstv * - mc->ctlname 695 1.175 mlelstv * - mc->ctlunit 696 1.175 mlelstv * - mc->wIndex 697 1.175 mlelstv * - mc->wValue[] 698 1.175 mlelstv * - mc->type 699 1.175 mlelstv * - mc->nchan 700 1.175 mlelstv * 701 1.175 mlelstv * - mc->range0, mc->mul for MIX_SELECTOR 702 1.175 mlelstv */ 703 1.175 mlelstv sc->sc_ctls[sc->sc_nctls] = *mc; 704 1.175 mlelstv mc = &sc->sc_ctls[sc->sc_nctls++]; 705 1.175 mlelstv msz = MIX_SIZE(mc->type); 706 1.175 mlelstv 707 1.33 augustss mc->delta = 0; 708 1.175 mlelstv mc->nranges = 0; 709 1.175 mlelstv mc->ranges = r = &mc->range0; 710 1.175 mlelstv mc->mul = 0; 711 1.79 kent if (mc->type == MIX_ON_OFF) { 712 1.175 mlelstv r->minval = 0; 713 1.175 mlelstv r->maxval = 1; 714 1.175 mlelstv r->resval = 1; 715 1.175 mlelstv res = r->resval; 716 1.79 kent } else if (mc->type == MIX_SELECTOR) { 717 1.175 mlelstv /* range0 already set by uaudio_add_selector */ 718 1.175 mlelstv res = r->resval; 719 1.175 mlelstv } else if (sc->sc_version == UAUDIO_VERSION1) { 720 1.1 augustss /* Determine min and max values. */ 721 1.175 mlelstv r->minval = uaudio_signext(mc->type, 722 1.56 kent uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE, 723 1.175 mlelstv mc->wValue[0], mc->wIndex, msz)); 724 1.175 mlelstv r->maxval = uaudio_signext(mc->type, 725 1.1 augustss uaudio_get(sc, GET_MAX, UT_READ_CLASS_INTERFACE, 726 1.175 mlelstv mc->wValue[0], mc->wIndex, msz)); 727 1.175 mlelstv r->resval = uaudio_get(sc, GET_RES, UT_READ_CLASS_INTERFACE, 728 1.175 mlelstv mc->wValue[0], mc->wIndex, msz); 729 1.175 mlelstv mc->mul = r->maxval - r->minval; 730 1.175 mlelstv res = r->resval; 731 1.175 mlelstv } else { /* UAUDIO_VERSION2 */ 732 1.178 mlelstv count = (uint16_t)uaudio_get(sc, V2_RANGES, 733 1.178 mlelstv UT_READ_CLASS_INTERFACE, 734 1.178 mlelstv mc->wValue[0], mc->wIndex, 2); 735 1.178 mlelstv 736 1.178 mlelstv if (count == 0 || count == (uint16_t)-1) { 737 1.178 mlelstv DPRINTF("invalid range count %zu\n", count); 738 1.178 mlelstv return; 739 1.178 mlelstv } 740 1.175 mlelstv 741 1.175 mlelstv if (count > 1) { 742 1.175 mlelstv r = kmem_alloc(sizeof(struct range) * count, 743 1.175 mlelstv KM_SLEEP); 744 1.175 mlelstv mc->ranges = r; 745 1.175 mlelstv mc->nranges = count; 746 1.175 mlelstv } 747 1.175 mlelstv 748 1.175 mlelstv mc->ranges[0].minval = 0; 749 1.175 mlelstv mc->ranges[0].maxval = 0; 750 1.175 mlelstv mc->ranges[0].resval = 1; 751 1.175 mlelstv 752 1.175 mlelstv /* again with the required buffer size */ 753 1.175 mlelstv len = 2 + count * 3 * msz; 754 1.175 mlelstv buf = kmem_alloc(len, KM_SLEEP); 755 1.175 mlelstv uaudio_getbuf(sc, V2_RANGES, UT_READ_CLASS_INTERFACE, 756 1.175 mlelstv mc->wValue[0], mc->wIndex, len, buf); 757 1.175 mlelstv res = 0; 758 1.175 mlelstv p = &buf[2]; 759 1.175 mlelstv for (i=0, p=buf+2; i<count; ++i) { 760 1.175 mlelstv uint32_t minval, maxval, resval; 761 1.175 mlelstv switch (msz) { 762 1.175 mlelstv case 1: 763 1.175 mlelstv minval = *p++; 764 1.175 mlelstv maxval = *p++; 765 1.175 mlelstv resval = *p++; 766 1.175 mlelstv break; 767 1.175 mlelstv case 2: 768 1.175 mlelstv minval = p[0] | p[1] << 8; 769 1.175 mlelstv p += 2; 770 1.175 mlelstv maxval = p[0] | p[1] << 8; 771 1.175 mlelstv p += 2; 772 1.175 mlelstv resval = p[0] | p[1] << 8; 773 1.175 mlelstv p += 2; 774 1.175 mlelstv break; 775 1.175 mlelstv case 3: 776 1.175 mlelstv minval = p[0] | p[1] << 8 | p[2] << 16; 777 1.175 mlelstv p += 3; 778 1.175 mlelstv maxval = p[0] | p[1] << 8 | p[2] << 16; 779 1.175 mlelstv p += 3; 780 1.175 mlelstv resval = p[0] | p[1] << 8 | p[2] << 16; 781 1.175 mlelstv p += 3; 782 1.175 mlelstv break; 783 1.175 mlelstv case 4: 784 1.175 mlelstv minval = p[0] | p[1] << 8 \ 785 1.175 mlelstv | p[2] << 16 | p[3] << 24; 786 1.175 mlelstv p += 4; 787 1.175 mlelstv maxval = p[0] | p[1] << 8 \ 788 1.175 mlelstv | p[2] << 16 | p[3] << 24; 789 1.175 mlelstv p += 4; 790 1.175 mlelstv resval = p[0] | p[1] << 8 \ 791 1.175 mlelstv | p[2] << 16 | p[3] << 24; 792 1.175 mlelstv p += 4; 793 1.175 mlelstv break; 794 1.175 mlelstv default: /* not allowed */ 795 1.175 mlelstv minval = maxval = 0; 796 1.175 mlelstv resval = 1; 797 1.175 mlelstv break; 798 1.175 mlelstv } 799 1.175 mlelstv mc->ranges[i].minval = uaudio_signext(mc->type, minval); 800 1.175 mlelstv mc->ranges[i].maxval = uaudio_signext(mc->type, maxval); 801 1.175 mlelstv mc->ranges[i].resval = uaudio_signext(mc->type, resval); 802 1.175 mlelstv if (mc->ranges[i].resval > res) 803 1.175 mlelstv res = mc->ranges[i].resval; 804 1.175 mlelstv } 805 1.175 mlelstv kmem_free(buf, len); 806 1.175 mlelstv 807 1.175 mlelstv mc->mul = mc->ranges[count - 1].maxval - mc->ranges[0].minval; 808 1.175 mlelstv 809 1.175 mlelstv /* 810 1.175 mlelstv * use resolution 1 (ideally the lcd) for 811 1.175 mlelstv * multiple (valid) resolution values. 812 1.175 mlelstv */ 813 1.175 mlelstv if (count > 1 && res > 0) 814 1.175 mlelstv res = 1; 815 1.1 augustss } 816 1.1 augustss 817 1.175 mlelstv if (mc->mul == 0) 818 1.175 mlelstv mc->mul = 1; 819 1.179 mlelstv 820 1.179 mlelstv mc->delta = (res * 255 + mc->mul - 1) / mc->mul; 821 1.1 augustss 822 1.4 augustss #ifdef UAUDIO_DEBUG 823 1.1 augustss if (uaudiodebug > 2) { 824 1.122 mrg DPRINTFN_CLEAN(2, "wValue=%04x", mc->wValue[0]); 825 1.1 augustss for (i = 1; i < mc->nchan; i++) 826 1.122 mrg DPRINTFN_CLEAN(2, ",%04x", mc->wValue[i]); 827 1.175 mlelstv DPRINTFN_CLEAN(2, "\n"); 828 1.175 mlelstv count = mc->nranges > 0 ? mc->nranges : 1; 829 1.175 mlelstv for (i = 0; i < count; i++) 830 1.175 mlelstv DPRINTFN_CLEAN(2, "%d: wIndex=%04x type=%d name='%s' " 831 1.175 mlelstv "unit='%s' min=%d max=%d res=%d\n", 832 1.175 mlelstv i, mc->wIndex, mc->type, mc->ctlname, mc->ctlunit, 833 1.175 mlelstv mc->ranges[i].minval, 834 1.175 mlelstv mc->ranges[i].maxval, 835 1.175 mlelstv mc->ranges[i].resval); 836 1.1 augustss } 837 1.1 augustss #endif 838 1.1 augustss } 839 1.1 augustss 840 1.86 kent Static char * 841 1.107 christos uaudio_id_name(struct uaudio_softc *sc, 842 1.179 mlelstv const struct io_terminal *iot, uint8_t id) 843 1.1 augustss { 844 1.99 christos static char tbuf[32]; 845 1.94 kent 846 1.179 mlelstv snprintf(tbuf, sizeof(tbuf), "i%u", id); 847 1.179 mlelstv 848 1.99 christos return tbuf; 849 1.1 augustss } 850 1.1 augustss 851 1.91 kent #ifdef UAUDIO_DEBUG 852 1.91 kent Static void 853 1.178 mlelstv uaudio_dump_cluster(struct uaudio_softc *sc, const union usb_audio_cluster *cl) 854 1.91 kent { 855 1.178 mlelstv static const char *channel_v1_names[16] = { 856 1.91 kent "LEFT", "RIGHT", "CENTER", "LFE", 857 1.91 kent "LEFT_SURROUND", "RIGHT_SURROUND", "LEFT_CENTER", "RIGHT_CENTER", 858 1.91 kent "SURROUND", "LEFT_SIDE", "RIGHT_SIDE", "TOP", 859 1.91 kent "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15", 860 1.91 kent }; 861 1.178 mlelstv static const char *channel_v2_names[32] = { 862 1.178 mlelstv "LEFT", "RIGHT", "CENTER", "LFE", 863 1.178 mlelstv "BACK_LEFT", "BACK_RIGHT", "FLC", "FRC", 864 1.178 mlelstv "BACK_CENTER", "SIDE_LEFT", "SIDE_RIGHT", "TOP CENTER", 865 1.178 mlelstv "TFL", "TFC", "TFR", "TBL", "TBC", "TBR", 866 1.178 mlelstv "TFLC", "TFRC", "LLFE", "RLFE", "TSL", "TSR", 867 1.178 mlelstv "BC", "BLC", "BRC", 868 1.178 mlelstv "RESERVED27", "RESERVED28", "RESERVED29", "RESERVED30", 869 1.178 mlelstv "RAW_DATA" 870 1.178 mlelstv }; 871 1.178 mlelstv const char **channel_names; 872 1.178 mlelstv uint32_t cc; 873 1.178 mlelstv int i, first, icn; 874 1.178 mlelstv 875 1.178 mlelstv switch (sc->sc_version) { 876 1.178 mlelstv case UAUDIO_VERSION1: 877 1.178 mlelstv channel_names = channel_v1_names; 878 1.178 mlelstv cc = UGETW(cl->v1.wChannelConfig); 879 1.178 mlelstv icn = cl->v1.iChannelNames; 880 1.178 mlelstv printf("cluster: bNrChannels=%u wChannelConfig=%#.4x", 881 1.178 mlelstv cl->v1.bNrChannels, cc); 882 1.178 mlelstv break; 883 1.178 mlelstv case UAUDIO_VERSION2: 884 1.178 mlelstv channel_names = channel_v2_names; 885 1.178 mlelstv cc = UGETDW(cl->v2.bmChannelConfig); 886 1.178 mlelstv icn = cl->v2.iChannelNames; 887 1.178 mlelstv printf("cluster: bNrChannels=%u bmChannelConfig=%#.8x", 888 1.178 mlelstv cl->v2.bNrChannels, cc); 889 1.178 mlelstv break; 890 1.178 mlelstv default: 891 1.178 mlelstv return; 892 1.178 mlelstv } 893 1.91 kent 894 1.91 kent first = TRUE; 895 1.91 kent for (i = 0; cc != 0; i++) { 896 1.91 kent if (cc & 1) { 897 1.118 dyoung printf("%c%s", first ? '<' : ',', channel_names[i]); 898 1.91 kent first = FALSE; 899 1.91 kent } 900 1.91 kent cc = cc >> 1; 901 1.91 kent } 902 1.178 mlelstv printf("> iChannelNames=%u", icn); 903 1.91 kent } 904 1.91 kent #endif 905 1.91 kent 906 1.178 mlelstv Static union usb_audio_cluster 907 1.178 mlelstv uaudio_get_cluster(struct uaudio_softc *sc, int id, const struct io_terminal *iot) 908 1.1 augustss { 909 1.178 mlelstv union usb_audio_cluster r; 910 1.109 drochner const uaudio_cs_descriptor_t *dp; 911 1.179 mlelstv u_int pins; 912 1.1 augustss int i; 913 1.1 augustss 914 1.1 augustss for (i = 0; i < 25; i++) { /* avoid infinite loops */ 915 1.82 kent dp = iot[id].d.desc; 916 1.1 augustss if (dp == 0) 917 1.1 augustss goto bad; 918 1.178 mlelstv 919 1.1 augustss switch (dp->bDescriptorSubtype) { 920 1.1 augustss case UDESCSUB_AC_INPUT: 921 1.178 mlelstv switch (sc->sc_version) { 922 1.178 mlelstv case UAUDIO_VERSION1: 923 1.178 mlelstv r.v1.bNrChannels = iot[id].d.it->v1.bNrChannels; 924 1.179 mlelstv USETW(r.v1.wChannelConfig, 925 1.179 mlelstv UGETW(iot[id].d.it->v1.wChannelConfig)); 926 1.178 mlelstv r.v1.iChannelNames = iot[id].d.it->v1.iChannelNames; 927 1.178 mlelstv break; 928 1.178 mlelstv case UAUDIO_VERSION2: 929 1.178 mlelstv r.v2.bNrChannels = iot[id].d.it->v2.bNrChannels; 930 1.179 mlelstv USETDW(r.v2.bmChannelConfig, 931 1.179 mlelstv UGETW(iot[id].d.it->v2.bmChannelConfig)); 932 1.178 mlelstv r.v2.iChannelNames = iot[id].d.it->v2.iChannelNames; 933 1.178 mlelstv break; 934 1.178 mlelstv } 935 1.94 kent return r; 936 1.1 augustss case UDESCSUB_AC_OUTPUT: 937 1.179 mlelstv /* XXX This is not really right */ 938 1.178 mlelstv id = iot[id].d.ot->v1.bSourceId; 939 1.1 augustss break; 940 1.1 augustss case UDESCSUB_AC_MIXER: 941 1.179 mlelstv switch (sc->sc_version) { 942 1.179 mlelstv case UAUDIO_VERSION1: 943 1.179 mlelstv pins = iot[id].d.mu->bNrInPins; 944 1.179 mlelstv r.v1 = *(const struct usb_audio_v1_cluster *) 945 1.179 mlelstv &iot[id].d.mu->baSourceId[pins]; 946 1.179 mlelstv break; 947 1.179 mlelstv case UAUDIO_VERSION2: 948 1.179 mlelstv pins = iot[id].d.mu->bNrInPins; 949 1.179 mlelstv r.v2 = *(const struct usb_audio_v2_cluster *) 950 1.179 mlelstv &iot[id].d.mu->baSourceId[pins]; 951 1.179 mlelstv break; 952 1.179 mlelstv } 953 1.94 kent return r; 954 1.1 augustss case UDESCSUB_AC_SELECTOR: 955 1.1 augustss /* XXX This is not really right */ 956 1.82 kent id = iot[id].d.su->baSourceId[0]; 957 1.1 augustss break; 958 1.1 augustss case UDESCSUB_AC_FEATURE: 959 1.179 mlelstv /* XXX This is not really right */ 960 1.179 mlelstv switch (sc->sc_version) { 961 1.179 mlelstv case UAUDIO_VERSION1: 962 1.179 mlelstv id = iot[id].d.fu->v1.bSourceId; 963 1.179 mlelstv break; 964 1.179 mlelstv case UAUDIO_VERSION2: 965 1.179 mlelstv id = iot[id].d.fu->v2.bSourceId; 966 1.179 mlelstv break; 967 1.179 mlelstv } 968 1.1 augustss break; 969 1.1 augustss case UDESCSUB_AC_PROCESSING: 970 1.179 mlelstv switch (sc->sc_version) { 971 1.179 mlelstv case UAUDIO_VERSION1: 972 1.179 mlelstv pins = iot[id].d.pu->bNrInPins; 973 1.179 mlelstv r.v1 = *(const struct usb_audio_v1_cluster *) 974 1.179 mlelstv &iot[id].d.pu->baSourceId[pins]; 975 1.179 mlelstv break; 976 1.179 mlelstv case UAUDIO_VERSION2: 977 1.179 mlelstv pins = iot[id].d.pu->bNrInPins; 978 1.179 mlelstv r.v2 = *(const struct usb_audio_v2_cluster *) 979 1.179 mlelstv &iot[id].d.pu->baSourceId[pins]; 980 1.179 mlelstv break; 981 1.179 mlelstv } 982 1.94 kent return r; 983 1.1 augustss case UDESCSUB_AC_EXTENSION: 984 1.179 mlelstv switch (sc->sc_version) { 985 1.179 mlelstv case UAUDIO_VERSION1: 986 1.179 mlelstv pins = iot[id].d.eu->bNrInPins; 987 1.179 mlelstv r.v1 = *(const struct usb_audio_v1_cluster *) 988 1.179 mlelstv &iot[id].d.eu->baSourceId[pins]; 989 1.179 mlelstv break; 990 1.179 mlelstv case UAUDIO_VERSION2: 991 1.179 mlelstv pins = iot[id].d.eu->bNrInPins; 992 1.179 mlelstv r.v2 = *(const struct usb_audio_v2_cluster *) 993 1.179 mlelstv &iot[id].d.eu->baSourceId[pins]; 994 1.179 mlelstv break; 995 1.179 mlelstv } 996 1.94 kent return r; 997 1.1 augustss default: 998 1.1 augustss goto bad; 999 1.1 augustss } 1000 1.1 augustss } 1001 1.1 augustss bad: 1002 1.113 cube aprint_error("uaudio_get_cluster: bad data\n"); 1003 1.146 skrll memset(&r, 0, sizeof(r)); 1004 1.94 kent return r; 1005 1.1 augustss 1006 1.1 augustss } 1007 1.1 augustss 1008 1.86 kent Static void 1009 1.82 kent uaudio_add_input(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1010 1.1 augustss { 1011 1.178 mlelstv const union usb_audio_input_terminal *d; 1012 1.1 augustss 1013 1.94 kent d = iot[id].d.it; 1014 1.178 mlelstv switch (sc->sc_version) { 1015 1.178 mlelstv case UAUDIO_VERSION1: 1016 1.92 kent #ifdef UAUDIO_DEBUG 1017 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x " 1018 1.178 mlelstv "bAssocTerminal=%d bNrChannels=%d wChannelConfig=%d " 1019 1.178 mlelstv "iChannelNames=%d iTerminal=%d\n", 1020 1.178 mlelstv d->v1.bTerminalId, UGETW(d->v1.wTerminalType), d->v1.bAssocTerminal, 1021 1.178 mlelstv d->v1.bNrChannels, UGETW(d->v1.wChannelConfig), 1022 1.178 mlelstv d->v1.iChannelNames, d->v1.iTerminal); 1023 1.1 augustss #endif 1024 1.178 mlelstv /* If USB input terminal, record wChannelConfig */ 1025 1.179 mlelstv if ((UGETW(d->v1.wTerminalType) & 0xff00) != UAT_UNDEFINED) 1026 1.178 mlelstv return; 1027 1.178 mlelstv sc->sc_channel_config = UGETW(d->v1.wChannelConfig); 1028 1.179 mlelstv sc->sc_clock[id] = 0; 1029 1.178 mlelstv break; 1030 1.178 mlelstv case UAUDIO_VERSION2: 1031 1.178 mlelstv #ifdef UAUDIO_DEBUG 1032 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x " 1033 1.178 mlelstv "bAssocTerminal=%d bNrChannels=%d bmChannelConfig=%x " 1034 1.178 mlelstv "iChannelNames=%d bCSourceId=%d iTerminal=%d\n", 1035 1.178 mlelstv d->v2.bTerminalId, UGETW(d->v2.wTerminalType), d->v2.bAssocTerminal, 1036 1.178 mlelstv d->v2.bNrChannels, UGETDW(d->v2.bmChannelConfig), 1037 1.178 mlelstv d->v2.iChannelNames, d->v2.bCSourceId, d->v2.iTerminal); 1038 1.178 mlelstv #endif 1039 1.178 mlelstv /* If USB input terminal, record wChannelConfig */ 1040 1.179 mlelstv if ((UGETW(d->v2.wTerminalType) & 0xff00) != UAT_UNDEFINED) 1041 1.178 mlelstv return; 1042 1.178 mlelstv sc->sc_channel_config = UGETDW(d->v2.bmChannelConfig); 1043 1.179 mlelstv sc->sc_clock[id] = d->v2.bCSourceId; 1044 1.178 mlelstv break; 1045 1.178 mlelstv } 1046 1.1 augustss } 1047 1.1 augustss 1048 1.86 kent Static void 1049 1.107 christos uaudio_add_output(struct uaudio_softc *sc, 1050 1.107 christos const struct io_terminal *iot, int id) 1051 1.1 augustss { 1052 1.4 augustss #ifdef UAUDIO_DEBUG 1053 1.178 mlelstv const union usb_audio_output_terminal *d; 1054 1.1 augustss 1055 1.94 kent d = iot[id].d.ot; 1056 1.178 mlelstv switch (sc->sc_version) { 1057 1.178 mlelstv case UAUDIO_VERSION1: 1058 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x " 1059 1.178 mlelstv "bAssocTerminal=%d bSourceId=%d iTerminal=%d\n", 1060 1.178 mlelstv d->v1.bTerminalId, UGETW(d->v1.wTerminalType), d->v1.bAssocTerminal, 1061 1.178 mlelstv d->v1.bSourceId, d->v1.iTerminal); 1062 1.179 mlelstv sc->sc_clock[id] = 0; 1063 1.178 mlelstv break; 1064 1.178 mlelstv case UAUDIO_VERSION2: 1065 1.178 mlelstv DPRINTFN(2,"bTerminalId=%d wTerminalType=0x%04x " 1066 1.178 mlelstv "bAssocTerminal=%d bSourceId=%d bCSourceId=%d, iTerminal=%d\n", 1067 1.178 mlelstv d->v2.bTerminalId, UGETW(d->v2.wTerminalType), d->v2.bAssocTerminal, 1068 1.178 mlelstv d->v2.bSourceId, d->v2.bCSourceId, d->v2.iTerminal); 1069 1.179 mlelstv sc->sc_clock[id] = d->v2.bCSourceId; 1070 1.178 mlelstv break; 1071 1.178 mlelstv } 1072 1.1 augustss #endif 1073 1.1 augustss } 1074 1.1 augustss 1075 1.86 kent Static void 1076 1.82 kent uaudio_add_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1077 1.1 augustss { 1078 1.94 kent const struct usb_audio_mixer_unit *d; 1079 1.178 mlelstv const union usb_audio_mixer_unit_1 *d1; 1080 1.179 mlelstv int c, chs, ichs, ochs, nchs, i, o, bno, p, k; 1081 1.179 mlelstv size_t bm_size; 1082 1.99 christos const uByte *bm; 1083 1.1 augustss struct mixerctl mix; 1084 1.1 augustss 1085 1.94 kent d = iot[id].d.mu; 1086 1.179 mlelstv d1 = (const union usb_audio_mixer_unit_1 *)&d->baSourceId[d->bNrInPins]; 1087 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrInPins=%d\n", 1088 1.122 mrg d->bUnitId, d->bNrInPins); 1089 1.56 kent 1090 1.179 mlelstv mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 1091 1.179 mlelstv uaudio_determine_class(&iot[id], &mix); 1092 1.179 mlelstv mix.type = MIX_SIGNED_16; 1093 1.179 mlelstv mix.ctlunit = AudioNvolume; 1094 1.178 mlelstv 1095 1.1 augustss /* Compute the number of input channels */ 1096 1.178 mlelstv /* and the number of output channels */ 1097 1.1 augustss ichs = 0; 1098 1.178 mlelstv switch (sc->sc_version) { 1099 1.178 mlelstv case UAUDIO_VERSION1: 1100 1.178 mlelstv for (i = 0; i < d->bNrInPins; i++) 1101 1.178 mlelstv ichs += uaudio_get_cluster(sc, d->baSourceId[i], iot).v1.bNrChannels; 1102 1.178 mlelstv ochs = d1->v1.bNrChannels; 1103 1.178 mlelstv DPRINTFN(2,"ichs=%d ochs=%d\n", ichs, ochs); 1104 1.178 mlelstv bm = d1->v1.bmControls; 1105 1.178 mlelstv break; 1106 1.178 mlelstv case UAUDIO_VERSION2: 1107 1.178 mlelstv for (i = 0; i < d->bNrInPins; i++) 1108 1.178 mlelstv ichs += uaudio_get_cluster(sc, d->baSourceId[i], iot).v2.bNrChannels; 1109 1.178 mlelstv ochs = d1->v2.bNrChannels; 1110 1.178 mlelstv DPRINTFN(2,"ichs=%d ochs=%d\n", ichs, ochs); 1111 1.179 mlelstv bm = d1->v2.bmMixerControls; 1112 1.179 mlelstv bm_size = ichs * ochs / 8 + ((ichs * ochs % 8) ? 1 : 0); 1113 1.179 mlelstv /* bmControls */ 1114 1.179 mlelstv if ((bm[bm_size] & UA_MIX_CLUSTER_MASK) != UA_MIX_CLUSTER_RW) 1115 1.179 mlelstv return; 1116 1.178 mlelstv break; 1117 1.178 mlelstv default: 1118 1.178 mlelstv return; 1119 1.178 mlelstv } 1120 1.179 mlelstv 1121 1.1 augustss for (p = i = 0; i < d->bNrInPins; i++) { 1122 1.178 mlelstv switch (sc->sc_version) { 1123 1.178 mlelstv case UAUDIO_VERSION1: 1124 1.179 mlelstv chs = uaudio_get_cluster(sc, d->baSourceId[i], iot) 1125 1.179 mlelstv .v1.bNrChannels; 1126 1.178 mlelstv break; 1127 1.178 mlelstv case UAUDIO_VERSION2: 1128 1.179 mlelstv chs = uaudio_get_cluster(sc, d->baSourceId[i], iot) 1129 1.179 mlelstv .v2.bNrChannels; 1130 1.178 mlelstv break; 1131 1.178 mlelstv default: 1132 1.179 mlelstv continue; 1133 1.178 mlelstv } 1134 1.179 mlelstv 1135 1.179 mlelstv #define _BIT(bno) ((bm[bno / 8] >> (7 - bno % 8)) & 1) 1136 1.179 mlelstv 1137 1.179 mlelstv nchs = chs < MIX_MAX_CHAN ? chs : MIX_MAX_CHAN; 1138 1.179 mlelstv 1139 1.179 mlelstv k = 0; 1140 1.179 mlelstv for (c = 0; c < nchs; c++) { 1141 1.1 augustss for (o = 0; o < ochs; o++) { 1142 1.1 augustss bno = (p + c) * ochs + o; 1143 1.101 dyoung if (_BIT(bno)) 1144 1.179 mlelstv mix.wValue[k++] = 1145 1.179 mlelstv MAKE(p+c+1, o+1); 1146 1.1 augustss } 1147 1.1 augustss } 1148 1.179 mlelstv mix.nchan = nchs; 1149 1.179 mlelstv 1150 1.179 mlelstv snprintf(mix.ctlname, sizeof(mix.ctlname), 1151 1.179 mlelstv "mix%d-%s", d->bUnitId, 1152 1.179 mlelstv uaudio_id_name(sc, iot, d->baSourceId[i]) 1153 1.179 mlelstv ); 1154 1.179 mlelstv uaudio_mixer_add_ctl(sc, &mix); 1155 1.179 mlelstv 1156 1.101 dyoung #undef _BIT 1157 1.179 mlelstv 1158 1.1 augustss p += chs; 1159 1.1 augustss } 1160 1.1 augustss } 1161 1.1 augustss 1162 1.86 kent Static void 1163 1.82 kent uaudio_add_selector(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1164 1.1 augustss { 1165 1.94 kent const struct usb_audio_selector_unit *d; 1166 1.79 kent struct mixerctl mix; 1167 1.79 kent int i, wp; 1168 1.1 augustss 1169 1.94 kent d = iot[id].d.su; 1170 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrInPins=%d\n", 1171 1.122 mrg d->bUnitId, d->bNrInPins); 1172 1.79 kent mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 1173 1.179 mlelstv if (sc->sc_version == UAUDIO_VERSION2) 1174 1.179 mlelstv mix.wValue[0] = MAKE(V2_CUR_SELECTOR, 0); 1175 1.179 mlelstv else 1176 1.179 mlelstv mix.wValue[0] = MAKE(0, 0); 1177 1.82 kent uaudio_determine_class(&iot[id], &mix); 1178 1.79 kent mix.nchan = 1; 1179 1.79 kent mix.type = MIX_SELECTOR; 1180 1.79 kent mix.ctlunit = ""; 1181 1.175 mlelstv mix.range0.minval = 1; 1182 1.175 mlelstv mix.range0.maxval = d->bNrInPins; 1183 1.175 mlelstv mix.range0.resval = 1; 1184 1.175 mlelstv mix.mul = mix.range0.maxval - mix.range0.minval; 1185 1.81 kent wp = snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "sel%d-", d->bUnitId); 1186 1.79 kent for (i = 1; i <= d->bNrInPins; i++) { 1187 1.179 mlelstv wp += strlcpy(mix.ctlname + wp, 1188 1.179 mlelstv uaudio_id_name(sc, iot, d->baSourceId[i-1]), 1189 1.179 mlelstv MAX_AUDIO_DEV_LEN - wp); 1190 1.79 kent if (wp > MAX_AUDIO_DEV_LEN - 1) 1191 1.79 kent break; 1192 1.79 kent } 1193 1.79 kent uaudio_mixer_add_ctl(sc, &mix); 1194 1.1 augustss } 1195 1.1 augustss 1196 1.82 kent #ifdef UAUDIO_DEBUG 1197 1.86 kent Static const char * 1198 1.82 kent uaudio_get_terminal_name(int terminal_type) 1199 1.82 kent { 1200 1.99 christos static char tbuf[100]; 1201 1.82 kent 1202 1.82 kent switch (terminal_type) { 1203 1.87 kent /* USB terminal types */ 1204 1.87 kent case UAT_UNDEFINED: return "UAT_UNDEFINED"; 1205 1.82 kent case UAT_STREAM: return "UAT_STREAM"; 1206 1.87 kent case UAT_VENDOR: return "UAT_VENDOR"; 1207 1.87 kent /* input terminal types */ 1208 1.87 kent case UATI_UNDEFINED: return "UATI_UNDEFINED"; 1209 1.82 kent case UATI_MICROPHONE: return "UATI_MICROPHONE"; 1210 1.82 kent case UATI_DESKMICROPHONE: return "UATI_DESKMICROPHONE"; 1211 1.82 kent case UATI_PERSONALMICROPHONE: return "UATI_PERSONALMICROPHONE"; 1212 1.82 kent case UATI_OMNIMICROPHONE: return "UATI_OMNIMICROPHONE"; 1213 1.82 kent case UATI_MICROPHONEARRAY: return "UATI_MICROPHONEARRAY"; 1214 1.82 kent case UATI_PROCMICROPHONEARR: return "UATI_PROCMICROPHONEARR"; 1215 1.87 kent /* output terminal types */ 1216 1.87 kent case UATO_UNDEFINED: return "UATO_UNDEFINED"; 1217 1.82 kent case UATO_SPEAKER: return "UATO_SPEAKER"; 1218 1.87 kent case UATO_HEADPHONES: return "UATO_HEADPHONES"; 1219 1.87 kent case UATO_DISPLAYAUDIO: return "UATO_DISPLAYAUDIO"; 1220 1.82 kent case UATO_DESKTOPSPEAKER: return "UATO_DESKTOPSPEAKER"; 1221 1.82 kent case UATO_ROOMSPEAKER: return "UATO_ROOMSPEAKER"; 1222 1.82 kent case UATO_COMMSPEAKER: return "UATO_COMMSPEAKER"; 1223 1.82 kent case UATO_SUBWOOFER: return "UATO_SUBWOOFER"; 1224 1.87 kent /* bidir terminal types */ 1225 1.82 kent case UATB_UNDEFINED: return "UATB_UNDEFINED"; 1226 1.82 kent case UATB_HANDSET: return "UATB_HANDSET"; 1227 1.82 kent case UATB_HEADSET: return "UATB_HEADSET"; 1228 1.82 kent case UATB_SPEAKERPHONE: return "UATB_SPEAKERPHONE"; 1229 1.82 kent case UATB_SPEAKERPHONEESUP: return "UATB_SPEAKERPHONEESUP"; 1230 1.82 kent case UATB_SPEAKERPHONEECANC: return "UATB_SPEAKERPHONEECANC"; 1231 1.87 kent /* telephony terminal types */ 1232 1.82 kent case UATT_UNDEFINED: return "UATT_UNDEFINED"; 1233 1.82 kent case UATT_PHONELINE: return "UATT_PHONELINE"; 1234 1.82 kent case UATT_TELEPHONE: return "UATT_TELEPHONE"; 1235 1.82 kent case UATT_DOWNLINEPHONE: return "UATT_DOWNLINEPHONE"; 1236 1.87 kent /* external terminal types */ 1237 1.82 kent case UATE_UNDEFINED: return "UATE_UNDEFINED"; 1238 1.87 kent case UATE_ANALOGCONN: return "UATE_ANALOGCONN"; 1239 1.87 kent case UATE_LINECONN: return "UATE_LINECONN"; 1240 1.87 kent case UATE_LEGACYCONN: return "UATE_LEGACYCONN"; 1241 1.87 kent case UATE_DIGITALAUIFC: return "UATE_DIGITALAUIFC"; 1242 1.87 kent case UATE_SPDIF: return "UATE_SPDIF"; 1243 1.87 kent case UATE_1394DA: return "UATE_1394DA"; 1244 1.87 kent case UATE_1394DV: return "UATE_1394DV"; 1245 1.87 kent /* embedded function terminal types */ 1246 1.82 kent case UATF_UNDEFINED: return "UATF_UNDEFINED"; 1247 1.82 kent case UATF_CALIBNOISE: return "UATF_CALIBNOISE"; 1248 1.82 kent case UATF_EQUNOISE: return "UATF_EQUNOISE"; 1249 1.87 kent case UATF_CDPLAYER: return "UATF_CDPLAYER"; 1250 1.82 kent case UATF_DAT: return "UATF_DAT"; 1251 1.82 kent case UATF_DCC: return "UATF_DCC"; 1252 1.82 kent case UATF_MINIDISK: return "UATF_MINIDISK"; 1253 1.82 kent case UATF_ANALOGTAPE: return "UATF_ANALOGTAPE"; 1254 1.82 kent case UATF_PHONOGRAPH: return "UATF_PHONOGRAPH"; 1255 1.82 kent case UATF_VCRAUDIO: return "UATF_VCRAUDIO"; 1256 1.87 kent case UATF_VIDEODISCAUDIO: return "UATF_VIDEODISCAUDIO"; 1257 1.87 kent case UATF_DVDAUDIO: return "UATF_DVDAUDIO"; 1258 1.87 kent case UATF_TVTUNERAUDIO: return "UATF_TVTUNERAUDIO"; 1259 1.82 kent case UATF_SATELLITE: return "UATF_SATELLITE"; 1260 1.82 kent case UATF_CABLETUNER: return "UATF_CABLETUNER"; 1261 1.82 kent case UATF_DSS: return "UATF_DSS"; 1262 1.82 kent case UATF_RADIORECV: return "UATF_RADIORECV"; 1263 1.82 kent case UATF_RADIOXMIT: return "UATF_RADIOXMIT"; 1264 1.82 kent case UATF_MULTITRACK: return "UATF_MULTITRACK"; 1265 1.87 kent case UATF_SYNTHESIZER: return "UATF_SYNTHESIZER"; 1266 1.82 kent default: 1267 1.164 christos snprintf(tbuf, sizeof(tbuf), "unknown type (%#.4x)", terminal_type); 1268 1.99 christos return tbuf; 1269 1.82 kent } 1270 1.82 kent } 1271 1.82 kent #endif 1272 1.82 kent 1273 1.86 kent Static int 1274 1.82 kent uaudio_determine_class(const struct io_terminal *iot, struct mixerctl *mix) 1275 1.82 kent { 1276 1.82 kent int terminal_type; 1277 1.82 kent 1278 1.82 kent if (iot == NULL || iot->output == NULL) { 1279 1.82 kent mix->class = UAC_OUTPUT; 1280 1.82 kent return 0; 1281 1.82 kent } 1282 1.82 kent terminal_type = 0; 1283 1.82 kent if (iot->output->size == 1) 1284 1.82 kent terminal_type = iot->output->terminals[0]; 1285 1.82 kent /* 1286 1.82 kent * If the only output terminal is USB, 1287 1.82 kent * the class is UAC_RECORD. 1288 1.82 kent */ 1289 1.82 kent if ((terminal_type & 0xff00) == (UAT_UNDEFINED & 0xff00)) { 1290 1.82 kent mix->class = UAC_RECORD; 1291 1.82 kent if (iot->inputs_size == 1 1292 1.82 kent && iot->inputs[0] != NULL 1293 1.82 kent && iot->inputs[0]->size == 1) 1294 1.82 kent return iot->inputs[0]->terminals[0]; 1295 1.82 kent else 1296 1.82 kent return 0; 1297 1.82 kent } 1298 1.82 kent /* 1299 1.83 kent * If the ultimate destination of the unit is just one output 1300 1.82 kent * terminal and the unit is connected to the output terminal 1301 1.82 kent * directly, the class is UAC_OUTPUT. 1302 1.82 kent */ 1303 1.82 kent if (terminal_type != 0 && iot->direct) { 1304 1.82 kent mix->class = UAC_OUTPUT; 1305 1.82 kent return terminal_type; 1306 1.82 kent } 1307 1.82 kent /* 1308 1.82 kent * If the unit is connected to just one input terminal, 1309 1.82 kent * the class is UAC_INPUT. 1310 1.82 kent */ 1311 1.82 kent if (iot->inputs_size == 1 && iot->inputs[0] != NULL 1312 1.82 kent && iot->inputs[0]->size == 1) { 1313 1.82 kent mix->class = UAC_INPUT; 1314 1.82 kent return iot->inputs[0]->terminals[0]; 1315 1.82 kent } 1316 1.82 kent /* 1317 1.82 kent * Otherwise, the class is UAC_OUTPUT. 1318 1.82 kent */ 1319 1.82 kent mix->class = UAC_OUTPUT; 1320 1.82 kent return terminal_type; 1321 1.82 kent } 1322 1.82 kent 1323 1.86 kent Static const char * 1324 1.179 mlelstv uaudio_feature_name(const struct io_terminal *iot, 1325 1.179 mlelstv uint8_t class, int terminal_type) 1326 1.82 kent { 1327 1.82 kent 1328 1.179 mlelstv if (class == UAC_RECORD && terminal_type == 0) 1329 1.82 kent return AudioNmixerout; 1330 1.179 mlelstv 1331 1.122 mrg DPRINTF("terminal_type=%s\n", uaudio_get_terminal_name(terminal_type)); 1332 1.82 kent switch (terminal_type) { 1333 1.82 kent case UAT_STREAM: 1334 1.82 kent return AudioNdac; 1335 1.82 kent 1336 1.82 kent case UATI_MICROPHONE: 1337 1.82 kent case UATI_DESKMICROPHONE: 1338 1.82 kent case UATI_PERSONALMICROPHONE: 1339 1.82 kent case UATI_OMNIMICROPHONE: 1340 1.82 kent case UATI_MICROPHONEARRAY: 1341 1.82 kent case UATI_PROCMICROPHONEARR: 1342 1.82 kent return AudioNmicrophone; 1343 1.82 kent 1344 1.82 kent case UATO_SPEAKER: 1345 1.82 kent case UATO_DESKTOPSPEAKER: 1346 1.82 kent case UATO_ROOMSPEAKER: 1347 1.82 kent case UATO_COMMSPEAKER: 1348 1.82 kent return AudioNspeaker; 1349 1.82 kent 1350 1.82 kent case UATO_HEADPHONES: 1351 1.82 kent return AudioNheadphone; 1352 1.82 kent 1353 1.87 kent case UATO_SUBWOOFER: 1354 1.87 kent return AudioNlfe; 1355 1.87 kent 1356 1.87 kent /* telephony terminal types */ 1357 1.87 kent case UATT_UNDEFINED: 1358 1.87 kent case UATT_PHONELINE: 1359 1.87 kent case UATT_TELEPHONE: 1360 1.87 kent case UATT_DOWNLINEPHONE: 1361 1.87 kent return "phone"; 1362 1.87 kent 1363 1.82 kent case UATE_ANALOGCONN: 1364 1.82 kent case UATE_LINECONN: 1365 1.82 kent case UATE_LEGACYCONN: 1366 1.82 kent return AudioNline; 1367 1.82 kent 1368 1.82 kent case UATE_DIGITALAUIFC: 1369 1.82 kent case UATE_SPDIF: 1370 1.82 kent case UATE_1394DA: 1371 1.82 kent case UATE_1394DV: 1372 1.82 kent return AudioNaux; 1373 1.82 kent 1374 1.82 kent case UATF_CDPLAYER: 1375 1.82 kent return AudioNcd; 1376 1.82 kent 1377 1.82 kent case UATF_SYNTHESIZER: 1378 1.82 kent return AudioNfmsynth; 1379 1.82 kent 1380 1.82 kent case UATF_VIDEODISCAUDIO: 1381 1.82 kent case UATF_DVDAUDIO: 1382 1.82 kent case UATF_TVTUNERAUDIO: 1383 1.82 kent return AudioNvideo; 1384 1.82 kent 1385 1.82 kent case UAT_UNDEFINED: 1386 1.82 kent case UAT_VENDOR: 1387 1.82 kent case UATI_UNDEFINED: 1388 1.82 kent /* output terminal types */ 1389 1.82 kent case UATO_UNDEFINED: 1390 1.82 kent case UATO_DISPLAYAUDIO: 1391 1.82 kent /* bidir terminal types */ 1392 1.82 kent case UATB_UNDEFINED: 1393 1.82 kent case UATB_HANDSET: 1394 1.82 kent case UATB_HEADSET: 1395 1.82 kent case UATB_SPEAKERPHONE: 1396 1.82 kent case UATB_SPEAKERPHONEESUP: 1397 1.82 kent case UATB_SPEAKERPHONEECANC: 1398 1.82 kent /* external terminal types */ 1399 1.82 kent case UATE_UNDEFINED: 1400 1.82 kent /* embedded function terminal types */ 1401 1.82 kent case UATF_UNDEFINED: 1402 1.82 kent case UATF_CALIBNOISE: 1403 1.82 kent case UATF_EQUNOISE: 1404 1.82 kent case UATF_DAT: 1405 1.82 kent case UATF_DCC: 1406 1.82 kent case UATF_MINIDISK: 1407 1.82 kent case UATF_ANALOGTAPE: 1408 1.82 kent case UATF_PHONOGRAPH: 1409 1.82 kent case UATF_VCRAUDIO: 1410 1.82 kent case UATF_SATELLITE: 1411 1.82 kent case UATF_CABLETUNER: 1412 1.82 kent case UATF_DSS: 1413 1.82 kent case UATF_RADIORECV: 1414 1.82 kent case UATF_RADIOXMIT: 1415 1.82 kent case UATF_MULTITRACK: 1416 1.82 kent case 0xffff: 1417 1.82 kent default: 1418 1.164 christos DPRINTF("'master' for %#.4x\n", terminal_type); 1419 1.82 kent return AudioNmaster; 1420 1.82 kent } 1421 1.82 kent return AudioNmaster; 1422 1.82 kent } 1423 1.82 kent 1424 1.179 mlelstv static void 1425 1.179 mlelstv uaudio_add_feature_mixer(struct uaudio_softc *sc, const struct io_terminal *iot, 1426 1.179 mlelstv int unit, int ctl, struct mixerctl *mc) 1427 1.179 mlelstv { 1428 1.179 mlelstv const char *mixername, *attr = NULL; 1429 1.179 mlelstv int terminal_type; 1430 1.179 mlelstv 1431 1.179 mlelstv mc->wIndex = MAKE(unit, sc->sc_ac_iface); 1432 1.179 mlelstv terminal_type = uaudio_determine_class(iot, mc); 1433 1.179 mlelstv mixername = uaudio_feature_name(iot, mc->class, terminal_type); 1434 1.179 mlelstv switch (ctl) { 1435 1.179 mlelstv case MUTE_CONTROL: 1436 1.179 mlelstv mc->type = MIX_ON_OFF; 1437 1.179 mlelstv mc->ctlunit = ""; 1438 1.179 mlelstv attr = AudioNmute; 1439 1.179 mlelstv break; 1440 1.179 mlelstv case VOLUME_CONTROL: 1441 1.179 mlelstv mc->type = MIX_SIGNED_16; 1442 1.179 mlelstv mc->ctlunit = AudioNvolume; 1443 1.179 mlelstv attr = NULL; 1444 1.179 mlelstv break; 1445 1.179 mlelstv case BASS_CONTROL: 1446 1.179 mlelstv mc->type = MIX_SIGNED_8; 1447 1.179 mlelstv mc->ctlunit = AudioNbass; 1448 1.179 mlelstv attr = AudioNbass; 1449 1.179 mlelstv break; 1450 1.179 mlelstv case MID_CONTROL: 1451 1.179 mlelstv mc->type = MIX_SIGNED_8; 1452 1.179 mlelstv mc->ctlunit = AudioNmid; 1453 1.179 mlelstv attr = AudioNmid; 1454 1.179 mlelstv break; 1455 1.179 mlelstv case TREBLE_CONTROL: 1456 1.179 mlelstv mc->type = MIX_SIGNED_8; 1457 1.179 mlelstv mc->ctlunit = AudioNtreble; 1458 1.179 mlelstv attr = AudioNtreble; 1459 1.179 mlelstv break; 1460 1.179 mlelstv case GRAPHIC_EQUALIZER_CONTROL: 1461 1.179 mlelstv return; /* XXX don't add anything */ 1462 1.179 mlelstv break; 1463 1.179 mlelstv case AGC_CONTROL: 1464 1.179 mlelstv mc->type = MIX_ON_OFF; 1465 1.179 mlelstv mc->ctlunit = ""; 1466 1.179 mlelstv attr = AudioNagc; 1467 1.179 mlelstv break; 1468 1.179 mlelstv case DELAY_CONTROL: 1469 1.179 mlelstv mc->type = MIX_UNSIGNED_16; 1470 1.179 mlelstv mc->ctlunit = "4 ms"; 1471 1.179 mlelstv attr = AudioNdelay; 1472 1.179 mlelstv break; 1473 1.179 mlelstv case BASS_BOOST_CONTROL: 1474 1.179 mlelstv mc->type = MIX_ON_OFF; 1475 1.179 mlelstv mc->ctlunit = ""; 1476 1.179 mlelstv attr = AudioNbassboost; 1477 1.179 mlelstv break; 1478 1.179 mlelstv case LOUDNESS_CONTROL: 1479 1.179 mlelstv mc->type = MIX_ON_OFF; 1480 1.179 mlelstv mc->ctlunit = ""; 1481 1.179 mlelstv attr = AudioNloudness; 1482 1.179 mlelstv break; 1483 1.179 mlelstv case GAIN_CONTROL: 1484 1.179 mlelstv mc->type = MIX_SIGNED_16; 1485 1.179 mlelstv mc->ctlunit = "gain"; 1486 1.179 mlelstv attr = "gain";; 1487 1.179 mlelstv break; 1488 1.179 mlelstv case GAINPAD_CONTROL: 1489 1.179 mlelstv mc->type = MIX_SIGNED_16; 1490 1.179 mlelstv mc->ctlunit = "gainpad"; 1491 1.179 mlelstv attr = "gainpad";; 1492 1.179 mlelstv break; 1493 1.179 mlelstv case PHASEINV_CONTROL: 1494 1.179 mlelstv mc->type = MIX_ON_OFF; 1495 1.179 mlelstv mc->ctlunit = ""; 1496 1.179 mlelstv attr = "phaseinv";; 1497 1.179 mlelstv break; 1498 1.179 mlelstv case UNDERFLOW_CONTROL: 1499 1.179 mlelstv mc->type = MIX_ON_OFF; 1500 1.179 mlelstv mc->ctlunit = ""; 1501 1.179 mlelstv attr = "underflow";; 1502 1.179 mlelstv break; 1503 1.179 mlelstv case OVERFLOW_CONTROL: 1504 1.179 mlelstv mc->type = MIX_ON_OFF; 1505 1.179 mlelstv mc->ctlunit = ""; 1506 1.179 mlelstv attr = "overflow";; 1507 1.179 mlelstv break; 1508 1.179 mlelstv default: 1509 1.179 mlelstv return; /* XXX don't add anything */ 1510 1.179 mlelstv break; 1511 1.179 mlelstv } 1512 1.179 mlelstv 1513 1.179 mlelstv if (attr != NULL) { 1514 1.179 mlelstv snprintf(mc->ctlname, sizeof(mc->ctlname), 1515 1.179 mlelstv "%s.%s", mixername, attr); 1516 1.179 mlelstv } else { 1517 1.179 mlelstv snprintf(mc->ctlname, sizeof(mc->ctlname), 1518 1.179 mlelstv "%s", mixername); 1519 1.179 mlelstv } 1520 1.179 mlelstv 1521 1.179 mlelstv uaudio_mixer_add_ctl(sc, mc); 1522 1.179 mlelstv } 1523 1.179 mlelstv 1524 1.86 kent Static void 1525 1.82 kent uaudio_add_feature(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1526 1.1 augustss { 1527 1.179 mlelstv const union usb_audio_feature_unit *d; 1528 1.94 kent const uByte *ctls; 1529 1.179 mlelstv const uDWord *ctls2; 1530 1.94 kent int ctlsize; 1531 1.94 kent int nchan; 1532 1.1 augustss u_int fumask, mmask, cmask; 1533 1.1 augustss struct mixerctl mix; 1534 1.1 augustss int chan, ctl, i, unit; 1535 1.1 augustss 1536 1.179 mlelstv d = iot[id].d.fu; 1537 1.179 mlelstv 1538 1.179 mlelstv switch (sc->sc_version) { 1539 1.179 mlelstv case UAUDIO_VERSION1: 1540 1.179 mlelstv 1541 1.179 mlelstv #define GETV1(i) (ctls[(i)*ctlsize] | \ 1542 1.1 augustss (ctlsize > 1 ? ctls[(i)*ctlsize+1] << 8 : 0)) 1543 1.179 mlelstv 1544 1.179 mlelstv ctls = d->v1.bmaControls; 1545 1.179 mlelstv ctlsize = d->v1.bControlSize; 1546 1.179 mlelstv if (ctlsize == 0) { 1547 1.179 mlelstv DPRINTF("ignoring feature %d with controlSize of zero\n", id); 1548 1.179 mlelstv return; 1549 1.179 mlelstv } 1550 1.179 mlelstv 1551 1.179 mlelstv /* offsetof bmaControls + sizeof iFeature == 7 */ 1552 1.179 mlelstv nchan = (d->v1.bLength - 7) / ctlsize; 1553 1.179 mlelstv mmask = GETV1(0); 1554 1.179 mlelstv /* Figure out what we can control */ 1555 1.179 mlelstv for (cmask = 0, chan = 1; chan < nchan; chan++) { 1556 1.179 mlelstv DPRINTFN(9,"chan=%d mask=%x\n", 1557 1.179 mlelstv chan, GETV1(chan)); 1558 1.179 mlelstv cmask |= GETV1(chan); 1559 1.179 mlelstv } 1560 1.179 mlelstv 1561 1.179 mlelstv DPRINTFN(1,"bUnitId=%d, " 1562 1.179 mlelstv "%d channels, mmask=0x%04x, cmask=0x%04x\n", 1563 1.179 mlelstv d->v1.bUnitId, nchan, mmask, cmask); 1564 1.179 mlelstv 1565 1.179 mlelstv if (nchan > MIX_MAX_CHAN) 1566 1.179 mlelstv nchan = MIX_MAX_CHAN; 1567 1.179 mlelstv unit = d->v1.bUnitId; 1568 1.179 mlelstv 1569 1.179 mlelstv for (ctl = MUTE_CONTROL; ctl <= LOUDNESS_CONTROL; ctl++) { 1570 1.179 mlelstv fumask = FU_MASK(ctl); 1571 1.179 mlelstv DPRINTFN(4,"ctl=%d fumask=0x%04x\n", 1572 1.179 mlelstv ctl, fumask); 1573 1.179 mlelstv if (mmask & fumask) { 1574 1.179 mlelstv mix.nchan = 1; 1575 1.179 mlelstv mix.wValue[0] = MAKE(ctl, 0); 1576 1.179 mlelstv } else if (cmask & fumask) { 1577 1.179 mlelstv mix.nchan = nchan - 1; 1578 1.179 mlelstv for (i = 1; i < nchan; i++) { 1579 1.179 mlelstv if (GETV1(i) & fumask) 1580 1.179 mlelstv mix.wValue[i-1] = MAKE(ctl, i); 1581 1.179 mlelstv else 1582 1.179 mlelstv mix.wValue[i-1] = -1; 1583 1.179 mlelstv } 1584 1.179 mlelstv } else { 1585 1.179 mlelstv continue; 1586 1.1 augustss } 1587 1.179 mlelstv 1588 1.179 mlelstv uaudio_add_feature_mixer(sc, &iot[id], unit, ctl, &mix); 1589 1.179 mlelstv } 1590 1.179 mlelstv #undef GETV1 1591 1.179 mlelstv break; 1592 1.179 mlelstv 1593 1.179 mlelstv case UAUDIO_VERSION2: 1594 1.179 mlelstv 1595 1.179 mlelstv #define GETV2(i) UGETDW(ctls2[(i)]) 1596 1.179 mlelstv 1597 1.179 mlelstv ctls2 = d->v2.bmaControls; 1598 1.179 mlelstv 1599 1.179 mlelstv /* offsetof bmaControls + sizeof iFeature == 6 */ 1600 1.179 mlelstv nchan = (d->v2.bLength - 6) / 4; 1601 1.179 mlelstv if (nchan <= 0) { 1602 1.179 mlelstv DPRINTF("ignoring feature %d with no controls\n", id); 1603 1.179 mlelstv return; 1604 1.1 augustss } 1605 1.179 mlelstv 1606 1.179 mlelstv mmask = GETV2(0); 1607 1.179 mlelstv /* Figure out what we can control */ 1608 1.179 mlelstv for (cmask = 0, chan = 1; chan < nchan; chan++) { 1609 1.179 mlelstv DPRINTFN(9,"chan=%d mask=%x\n", 1610 1.179 mlelstv chan, GETV2(chan)); 1611 1.179 mlelstv cmask |= GETV2(chan); 1612 1.179 mlelstv } 1613 1.179 mlelstv 1614 1.179 mlelstv DPRINTFN(1,"bUnitId=%d, " 1615 1.179 mlelstv "%d channels, mmask=0x%04x, cmask=0x%04x\n", 1616 1.179 mlelstv d->v2.bUnitId, nchan, mmask, cmask); 1617 1.179 mlelstv 1618 1.179 mlelstv if (nchan > MIX_MAX_CHAN) 1619 1.179 mlelstv nchan = MIX_MAX_CHAN; 1620 1.179 mlelstv unit = d->v2.bUnitId; 1621 1.179 mlelstv 1622 1.179 mlelstv for (ctl = MUTE_CONTROL; ctl <= OVERFLOW_CONTROL; ctl++) { 1623 1.179 mlelstv fumask = V2_FU_MASK(ctl); 1624 1.179 mlelstv DPRINTFN(4,"ctl=%d fumask=0x%08x\n", 1625 1.179 mlelstv ctl, fumask); 1626 1.179 mlelstv 1627 1.179 mlelstv if (mmask & fumask) { 1628 1.179 mlelstv mix.nchan = 1; 1629 1.179 mlelstv mix.wValue[0] = MAKE(ctl, 0); 1630 1.179 mlelstv } else if (cmask & fumask) { 1631 1.179 mlelstv mix.nchan = nchan-1; 1632 1.179 mlelstv for (i = 1; i < nchan; ++i) { 1633 1.179 mlelstv if (GETV2(i) & fumask) 1634 1.179 mlelstv mix.wValue[i-1] = MAKE(ctl, i); 1635 1.179 mlelstv else 1636 1.179 mlelstv mix.wValue[i-1] = -1; 1637 1.179 mlelstv } 1638 1.179 mlelstv } else { 1639 1.179 mlelstv continue; 1640 1.179 mlelstv } 1641 1.179 mlelstv 1642 1.179 mlelstv uaudio_add_feature_mixer(sc, &iot[id], unit, ctl, &mix); 1643 1.1 augustss } 1644 1.179 mlelstv 1645 1.179 mlelstv #undef GETV2 1646 1.179 mlelstv break; 1647 1.1 augustss } 1648 1.1 augustss } 1649 1.1 augustss 1650 1.86 kent Static void 1651 1.78 kent uaudio_add_processing_updown(struct uaudio_softc *sc, 1652 1.82 kent const struct io_terminal *iot, int id) 1653 1.78 kent { 1654 1.94 kent const struct usb_audio_processing_unit *d; 1655 1.94 kent const struct usb_audio_processing_unit_1 *d1; 1656 1.94 kent const struct usb_audio_processing_unit_updown *ud; 1657 1.16 augustss struct mixerctl mix; 1658 1.16 augustss int i; 1659 1.16 augustss 1660 1.94 kent d = iot[id].d.pu; 1661 1.94 kent d1 = (const struct usb_audio_processing_unit_1 *) 1662 1.94 kent &d->baSourceId[d->bNrInPins]; 1663 1.94 kent ud = (const struct usb_audio_processing_unit_updown *) 1664 1.94 kent &d1->bmControls[d1->bControlSize]; 1665 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrModes=%d\n", 1666 1.122 mrg d->bUnitId, ud->bNrModes); 1667 1.16 augustss 1668 1.16 augustss if (!(d1->bmControls[0] & UA_PROC_MASK(UD_MODE_SELECT_CONTROL))) { 1669 1.122 mrg DPRINTF("%s", "no mode select\n"); 1670 1.16 augustss return; 1671 1.16 augustss } 1672 1.16 augustss 1673 1.16 augustss mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 1674 1.16 augustss mix.nchan = 1; 1675 1.16 augustss mix.wValue[0] = MAKE(UD_MODE_SELECT_CONTROL, 0); 1676 1.82 kent uaudio_determine_class(&iot[id], &mix); 1677 1.16 augustss mix.type = MIX_ON_OFF; /* XXX */ 1678 1.16 augustss mix.ctlunit = ""; 1679 1.70 itojun snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d-mode", d->bUnitId); 1680 1.16 augustss 1681 1.16 augustss for (i = 0; i < ud->bNrModes; i++) { 1682 1.164 christos DPRINTFN(2,"i=%d bm=%#x\n", 1683 1.122 mrg i, UGETW(ud->waModes[i])); 1684 1.16 augustss /* XXX */ 1685 1.16 augustss } 1686 1.16 augustss uaudio_mixer_add_ctl(sc, &mix); 1687 1.16 augustss } 1688 1.16 augustss 1689 1.86 kent Static void 1690 1.82 kent uaudio_add_processing(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1691 1.1 augustss { 1692 1.94 kent const struct usb_audio_processing_unit *d; 1693 1.94 kent const struct usb_audio_processing_unit_1 *d1; 1694 1.94 kent int ptype; 1695 1.15 augustss struct mixerctl mix; 1696 1.15 augustss 1697 1.94 kent d = iot[id].d.pu; 1698 1.94 kent d1 = (const struct usb_audio_processing_unit_1 *) 1699 1.94 kent &d->baSourceId[d->bNrInPins]; 1700 1.94 kent ptype = UGETW(d->wProcessType); 1701 1.122 mrg DPRINTFN(2,"wProcessType=%d bUnitId=%d " 1702 1.122 mrg "bNrInPins=%d\n", ptype, d->bUnitId, d->bNrInPins); 1703 1.15 augustss 1704 1.15 augustss if (d1->bmControls[0] & UA_PROC_ENABLE_MASK) { 1705 1.15 augustss mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 1706 1.15 augustss mix.nchan = 1; 1707 1.15 augustss mix.wValue[0] = MAKE(XX_ENABLE_CONTROL, 0); 1708 1.82 kent uaudio_determine_class(&iot[id], &mix); 1709 1.15 augustss mix.type = MIX_ON_OFF; 1710 1.15 augustss mix.ctlunit = ""; 1711 1.70 itojun snprintf(mix.ctlname, sizeof(mix.ctlname), "pro%d.%d-enable", 1712 1.70 itojun d->bUnitId, ptype); 1713 1.15 augustss uaudio_mixer_add_ctl(sc, &mix); 1714 1.15 augustss } 1715 1.1 augustss 1716 1.15 augustss switch(ptype) { 1717 1.15 augustss case UPDOWNMIX_PROCESS: 1718 1.82 kent uaudio_add_processing_updown(sc, iot, id); 1719 1.16 augustss break; 1720 1.15 augustss case DOLBY_PROLOGIC_PROCESS: 1721 1.15 augustss case P3D_STEREO_EXTENDER_PROCESS: 1722 1.15 augustss case REVERBATION_PROCESS: 1723 1.15 augustss case CHORUS_PROCESS: 1724 1.15 augustss case DYN_RANGE_COMP_PROCESS: 1725 1.15 augustss default: 1726 1.15 augustss #ifdef UAUDIO_DEBUG 1727 1.113 cube aprint_debug( 1728 1.113 cube "uaudio_add_processing: unit %d, type=%d not impl.\n", 1729 1.113 cube d->bUnitId, ptype); 1730 1.1 augustss #endif 1731 1.15 augustss break; 1732 1.15 augustss } 1733 1.1 augustss } 1734 1.1 augustss 1735 1.86 kent Static void 1736 1.175 mlelstv uaudio_add_effect(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1737 1.175 mlelstv { 1738 1.178 mlelstv 1739 1.178 mlelstv #ifdef UAUDIO_DEBUG 1740 1.178 mlelstv aprint_debug("uaudio_add_effect: not impl.\n"); 1741 1.178 mlelstv #endif 1742 1.175 mlelstv } 1743 1.175 mlelstv 1744 1.175 mlelstv Static void 1745 1.82 kent uaudio_add_extension(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1746 1.1 augustss { 1747 1.94 kent const struct usb_audio_extension_unit *d; 1748 1.94 kent const struct usb_audio_extension_unit_1 *d1; 1749 1.1 augustss struct mixerctl mix; 1750 1.1 augustss 1751 1.94 kent d = iot[id].d.eu; 1752 1.94 kent d1 = (const struct usb_audio_extension_unit_1 *) 1753 1.94 kent &d->baSourceId[d->bNrInPins]; 1754 1.122 mrg DPRINTFN(2,"bUnitId=%d bNrInPins=%d\n", 1755 1.122 mrg d->bUnitId, d->bNrInPins); 1756 1.28 augustss 1757 1.31 augustss if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_NO_XU) 1758 1.28 augustss return; 1759 1.1 augustss 1760 1.15 augustss if (d1->bmControls[0] & UA_EXT_ENABLE_MASK) { 1761 1.1 augustss mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface); 1762 1.1 augustss mix.nchan = 1; 1763 1.1 augustss mix.wValue[0] = MAKE(UA_EXT_ENABLE, 0); 1764 1.82 kent uaudio_determine_class(&iot[id], &mix); 1765 1.1 augustss mix.type = MIX_ON_OFF; 1766 1.1 augustss mix.ctlunit = ""; 1767 1.70 itojun snprintf(mix.ctlname, sizeof(mix.ctlname), "ext%d-enable", 1768 1.70 itojun d->bUnitId); 1769 1.1 augustss uaudio_mixer_add_ctl(sc, &mix); 1770 1.1 augustss } 1771 1.1 augustss } 1772 1.1 augustss 1773 1.175 mlelstv Static void 1774 1.175 mlelstv uaudio_add_clksrc(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1775 1.175 mlelstv { 1776 1.175 mlelstv const struct usb_audio_clksrc_unit *d; 1777 1.175 mlelstv struct mixerctl mix; 1778 1.175 mlelstv 1779 1.175 mlelstv d = iot[id].d.cu; 1780 1.178 mlelstv DPRINTFN(2,"bClockId=%d bmAttributes=%d bmControls=%d bAssocTerminal=%d iClockSource=%d\n", 1781 1.178 mlelstv d->bClockId, d->bmAttributes, d->bmControls, d->bAssocTerminal, d->iClockSource); 1782 1.178 mlelstv mix.wIndex = MAKE(d->bClockId, sc->sc_ac_iface); 1783 1.175 mlelstv uaudio_determine_class(&iot[id], &mix); 1784 1.175 mlelstv mix.nchan = 1; 1785 1.175 mlelstv mix.wValue[0] = MAKE(V2_CUR_CLKFREQ, 0); 1786 1.175 mlelstv mix.type = MIX_UNSIGNED_32; 1787 1.175 mlelstv mix.ctlunit = ""; 1788 1.175 mlelstv 1789 1.175 mlelstv uaudio_makename(sc, d->iClockSource, uaudio_clockname(d->bmAttributes), 1790 1.175 mlelstv d->bClockId, mix.ctlname, sizeof(mix.ctlname)); 1791 1.175 mlelstv uaudio_mixer_add_ctl(sc, &mix); 1792 1.175 mlelstv } 1793 1.175 mlelstv 1794 1.175 mlelstv Static void 1795 1.175 mlelstv uaudio_add_clksel(struct uaudio_softc *sc, const struct io_terminal *iot, int id) 1796 1.175 mlelstv { 1797 1.175 mlelstv const struct usb_audio_clksel_unit *d; 1798 1.175 mlelstv struct mixerctl mix; 1799 1.175 mlelstv int i, wp; 1800 1.175 mlelstv uByte sel; 1801 1.175 mlelstv 1802 1.175 mlelstv d = iot[id].d.lu; 1803 1.175 mlelstv sel = ((const uByte *)&d->baCSourceId[d->bNrInPins])[2]; /* iClockSelector */ 1804 1.176 mlelstv DPRINTFN(2,"bClockId=%d bNrInPins=%d iClockSelector=%d\n", 1805 1.176 mlelstv d->bClockId, d->bNrInPins, sel); 1806 1.175 mlelstv mix.wIndex = MAKE(d->bClockId, sc->sc_ac_iface); 1807 1.175 mlelstv uaudio_determine_class(&iot[id], &mix); 1808 1.175 mlelstv mix.nchan = 1; 1809 1.175 mlelstv mix.wValue[0] = MAKE(V2_CUR_CLKSEL, 0); 1810 1.175 mlelstv mix.type = MIX_SELECTOR; 1811 1.175 mlelstv mix.ctlunit = ""; 1812 1.175 mlelstv mix.range0.minval = 1; 1813 1.175 mlelstv mix.range0.maxval = d->bNrInPins; 1814 1.175 mlelstv mix.range0.resval = 1; 1815 1.175 mlelstv mix.mul = mix.range0.maxval - mix.range0.minval; 1816 1.175 mlelstv wp = uaudio_makename(sc, sel, "clksel", d->bClockId, mix.ctlname, MAX_AUDIO_DEV_LEN); 1817 1.175 mlelstv for (i = 1; i <= d->bNrInPins; i++) { 1818 1.175 mlelstv wp += snprintf(mix.ctlname + wp, MAX_AUDIO_DEV_LEN - wp, 1819 1.175 mlelstv "%si%d", i == 1 ? "-" : "", d->baCSourceId[i - 1]); 1820 1.175 mlelstv if (wp > MAX_AUDIO_DEV_LEN - 1) 1821 1.175 mlelstv break; 1822 1.175 mlelstv } 1823 1.175 mlelstv uaudio_mixer_add_ctl(sc, &mix); 1824 1.175 mlelstv } 1825 1.175 mlelstv 1826 1.86 kent Static struct terminal_list* 1827 1.82 kent uaudio_merge_terminal_list(const struct io_terminal *iot) 1828 1.82 kent { 1829 1.82 kent struct terminal_list *tml; 1830 1.82 kent uint16_t *ptm; 1831 1.82 kent int i, len; 1832 1.82 kent 1833 1.82 kent len = 0; 1834 1.82 kent if (iot->inputs == NULL) 1835 1.82 kent return NULL; 1836 1.82 kent for (i = 0; i < iot->inputs_size; i++) { 1837 1.82 kent if (iot->inputs[i] != NULL) 1838 1.82 kent len += iot->inputs[i]->size; 1839 1.82 kent } 1840 1.82 kent tml = malloc(TERMINAL_LIST_SIZE(len), M_TEMP, M_NOWAIT); 1841 1.82 kent if (tml == NULL) { 1842 1.113 cube aprint_error("uaudio_merge_terminal_list: no memory\n"); 1843 1.82 kent return NULL; 1844 1.82 kent } 1845 1.82 kent tml->size = 0; 1846 1.82 kent ptm = tml->terminals; 1847 1.82 kent for (i = 0; i < iot->inputs_size; i++) { 1848 1.82 kent if (iot->inputs[i] == NULL) 1849 1.82 kent continue; 1850 1.82 kent if (iot->inputs[i]->size > len) 1851 1.82 kent break; 1852 1.82 kent memcpy(ptm, iot->inputs[i]->terminals, 1853 1.82 kent iot->inputs[i]->size * sizeof(uint16_t)); 1854 1.82 kent tml->size += iot->inputs[i]->size; 1855 1.82 kent ptm += iot->inputs[i]->size; 1856 1.82 kent len -= iot->inputs[i]->size; 1857 1.82 kent } 1858 1.82 kent return tml; 1859 1.82 kent } 1860 1.82 kent 1861 1.86 kent Static struct terminal_list * 1862 1.178 mlelstv uaudio_io_terminaltype(struct uaudio_softc *sc, int outtype, struct io_terminal *iot, int id) 1863 1.82 kent { 1864 1.82 kent struct terminal_list *tml; 1865 1.82 kent struct io_terminal *it; 1866 1.82 kent int src_id, i; 1867 1.82 kent 1868 1.82 kent it = &iot[id]; 1869 1.82 kent if (it->output != NULL) { 1870 1.82 kent /* already has outtype? */ 1871 1.82 kent for (i = 0; i < it->output->size; i++) 1872 1.82 kent if (it->output->terminals[i] == outtype) 1873 1.82 kent return uaudio_merge_terminal_list(it); 1874 1.82 kent tml = malloc(TERMINAL_LIST_SIZE(it->output->size + 1), 1875 1.82 kent M_TEMP, M_NOWAIT); 1876 1.82 kent if (tml == NULL) { 1877 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1878 1.82 kent return uaudio_merge_terminal_list(it); 1879 1.82 kent } 1880 1.82 kent memcpy(tml, it->output, TERMINAL_LIST_SIZE(it->output->size)); 1881 1.82 kent tml->terminals[it->output->size] = outtype; 1882 1.82 kent tml->size++; 1883 1.82 kent free(it->output, M_TEMP); 1884 1.82 kent it->output = tml; 1885 1.82 kent if (it->inputs != NULL) { 1886 1.82 kent for (i = 0; i < it->inputs_size; i++) 1887 1.82 kent if (it->inputs[i] != NULL) 1888 1.82 kent free(it->inputs[i], M_TEMP); 1889 1.82 kent free(it->inputs, M_TEMP); 1890 1.82 kent } 1891 1.82 kent it->inputs_size = 0; 1892 1.82 kent it->inputs = NULL; 1893 1.82 kent } else { /* end `iot[id] != NULL' */ 1894 1.82 kent it->inputs_size = 0; 1895 1.82 kent it->inputs = NULL; 1896 1.82 kent it->output = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT); 1897 1.82 kent if (it->output == NULL) { 1898 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1899 1.82 kent return NULL; 1900 1.82 kent } 1901 1.82 kent it->output->terminals[0] = outtype; 1902 1.82 kent it->output->size = 1; 1903 1.82 kent it->direct = FALSE; 1904 1.82 kent } 1905 1.82 kent 1906 1.82 kent switch (it->d.desc->bDescriptorSubtype) { 1907 1.82 kent case UDESCSUB_AC_INPUT: 1908 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT); 1909 1.82 kent if (it->inputs == NULL) { 1910 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1911 1.82 kent return NULL; 1912 1.82 kent } 1913 1.82 kent tml = malloc(TERMINAL_LIST_SIZE(1), M_TEMP, M_NOWAIT); 1914 1.82 kent if (tml == NULL) { 1915 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1916 1.82 kent free(it->inputs, M_TEMP); 1917 1.82 kent it->inputs = NULL; 1918 1.82 kent return NULL; 1919 1.82 kent } 1920 1.82 kent it->inputs[0] = tml; 1921 1.178 mlelstv switch (sc->sc_version) { 1922 1.178 mlelstv case UAUDIO_VERSION1: 1923 1.178 mlelstv tml->terminals[0] = UGETW(it->d.it->v1.wTerminalType); 1924 1.178 mlelstv break; 1925 1.178 mlelstv case UAUDIO_VERSION2: 1926 1.178 mlelstv tml->terminals[0] = UGETW(it->d.it->v2.wTerminalType); 1927 1.178 mlelstv break; 1928 1.178 mlelstv default: 1929 1.178 mlelstv free(tml, M_TEMP); 1930 1.178 mlelstv free(it->inputs, M_TEMP); 1931 1.178 mlelstv it->inputs = NULL; 1932 1.178 mlelstv return NULL; 1933 1.178 mlelstv } 1934 1.82 kent tml->size = 1; 1935 1.82 kent it->inputs_size = 1; 1936 1.82 kent return uaudio_merge_terminal_list(it); 1937 1.82 kent case UDESCSUB_AC_FEATURE: 1938 1.179 mlelstv switch (sc->sc_version) { 1939 1.179 mlelstv case UAUDIO_VERSION1: 1940 1.179 mlelstv src_id = it->d.fu->v1.bSourceId; 1941 1.179 mlelstv break; 1942 1.179 mlelstv case UAUDIO_VERSION2: 1943 1.179 mlelstv src_id = it->d.fu->v2.bSourceId; 1944 1.179 mlelstv break; 1945 1.179 mlelstv default: 1946 1.179 mlelstv /* cannot happen */ 1947 1.179 mlelstv return NULL; 1948 1.179 mlelstv } 1949 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT); 1950 1.82 kent if (it->inputs == NULL) { 1951 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1952 1.178 mlelstv return uaudio_io_terminaltype(sc, outtype, iot, src_id); 1953 1.82 kent } 1954 1.178 mlelstv it->inputs[0] = uaudio_io_terminaltype(sc, outtype, iot, src_id); 1955 1.82 kent it->inputs_size = 1; 1956 1.82 kent return uaudio_merge_terminal_list(it); 1957 1.82 kent case UDESCSUB_AC_OUTPUT: 1958 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *), M_TEMP, M_NOWAIT); 1959 1.82 kent if (it->inputs == NULL) { 1960 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1961 1.82 kent return NULL; 1962 1.82 kent } 1963 1.178 mlelstv switch (sc->sc_version) { 1964 1.178 mlelstv case UAUDIO_VERSION1: 1965 1.178 mlelstv src_id = it->d.ot->v1.bSourceId; 1966 1.178 mlelstv break; 1967 1.178 mlelstv case UAUDIO_VERSION2: 1968 1.178 mlelstv src_id = it->d.ot->v2.bSourceId; 1969 1.178 mlelstv break; 1970 1.178 mlelstv default: 1971 1.178 mlelstv free(it->inputs, M_TEMP); 1972 1.178 mlelstv it->inputs = NULL; 1973 1.178 mlelstv return NULL; 1974 1.178 mlelstv } 1975 1.178 mlelstv it->inputs[0] = uaudio_io_terminaltype(sc, outtype, iot, src_id); 1976 1.82 kent it->inputs_size = 1; 1977 1.82 kent iot[src_id].direct = TRUE; 1978 1.82 kent return NULL; 1979 1.82 kent case UDESCSUB_AC_MIXER: 1980 1.82 kent it->inputs_size = 0; 1981 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *) 1982 1.82 kent * it->d.mu->bNrInPins, M_TEMP, M_NOWAIT); 1983 1.82 kent if (it->inputs == NULL) { 1984 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 1985 1.82 kent return NULL; 1986 1.82 kent } 1987 1.82 kent for (i = 0; i < it->d.mu->bNrInPins; i++) { 1988 1.82 kent src_id = it->d.mu->baSourceId[i]; 1989 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot, 1990 1.82 kent src_id); 1991 1.82 kent it->inputs_size++; 1992 1.82 kent } 1993 1.82 kent return uaudio_merge_terminal_list(it); 1994 1.82 kent case UDESCSUB_AC_SELECTOR: 1995 1.82 kent it->inputs_size = 0; 1996 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *) 1997 1.82 kent * it->d.su->bNrInPins, M_TEMP, M_NOWAIT); 1998 1.82 kent if (it->inputs == NULL) { 1999 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 2000 1.82 kent return NULL; 2001 1.82 kent } 2002 1.82 kent for (i = 0; i < it->d.su->bNrInPins; i++) { 2003 1.82 kent src_id = it->d.su->baSourceId[i]; 2004 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot, 2005 1.82 kent src_id); 2006 1.82 kent it->inputs_size++; 2007 1.82 kent } 2008 1.82 kent return uaudio_merge_terminal_list(it); 2009 1.82 kent case UDESCSUB_AC_PROCESSING: 2010 1.82 kent it->inputs_size = 0; 2011 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *) 2012 1.82 kent * it->d.pu->bNrInPins, M_TEMP, M_NOWAIT); 2013 1.82 kent if (it->inputs == NULL) { 2014 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 2015 1.82 kent return NULL; 2016 1.82 kent } 2017 1.82 kent for (i = 0; i < it->d.pu->bNrInPins; i++) { 2018 1.82 kent src_id = it->d.pu->baSourceId[i]; 2019 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot, 2020 1.82 kent src_id); 2021 1.82 kent it->inputs_size++; 2022 1.82 kent } 2023 1.82 kent return uaudio_merge_terminal_list(it); 2024 1.82 kent case UDESCSUB_AC_EXTENSION: 2025 1.82 kent it->inputs_size = 0; 2026 1.82 kent it->inputs = malloc(sizeof(struct terminal_list *) 2027 1.82 kent * it->d.eu->bNrInPins, M_TEMP, M_NOWAIT); 2028 1.82 kent if (it->inputs == NULL) { 2029 1.113 cube aprint_error("uaudio_io_terminaltype: no memory\n"); 2030 1.82 kent return NULL; 2031 1.82 kent } 2032 1.82 kent for (i = 0; i < it->d.eu->bNrInPins; i++) { 2033 1.82 kent src_id = it->d.eu->baSourceId[i]; 2034 1.178 mlelstv it->inputs[i] = uaudio_io_terminaltype(sc, outtype, iot, 2035 1.82 kent src_id); 2036 1.82 kent it->inputs_size++; 2037 1.82 kent } 2038 1.82 kent return uaudio_merge_terminal_list(it); 2039 1.82 kent case UDESCSUB_AC_HEADER: 2040 1.82 kent default: 2041 1.82 kent return NULL; 2042 1.82 kent } 2043 1.82 kent } 2044 1.82 kent 2045 1.86 kent Static usbd_status 2046 1.78 kent uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc) 2047 1.1 augustss { 2048 1.9 augustss usbd_status err; 2049 1.1 augustss 2050 1.9 augustss err = uaudio_identify_ac(sc, cdesc); 2051 1.9 augustss if (err) 2052 1.94 kent return err; 2053 1.175 mlelstv err = uaudio_identify_as(sc, cdesc); 2054 1.175 mlelstv if (err) 2055 1.175 mlelstv return err; 2056 1.175 mlelstv 2057 1.175 mlelstv uaudio_build_formats(sc); 2058 1.175 mlelstv return 0; 2059 1.1 augustss } 2060 1.1 augustss 2061 1.86 kent Static void 2062 1.78 kent uaudio_add_alt(struct uaudio_softc *sc, const struct as_info *ai) 2063 1.1 augustss { 2064 1.84 kent size_t len; 2065 1.84 kent struct as_info *nai; 2066 1.42 christos 2067 1.84 kent len = sizeof(*ai) * (sc->sc_nalts + 1); 2068 1.146 skrll nai = kmem_alloc(len, KM_SLEEP); 2069 1.84 kent /* Copy old data, if there was any */ 2070 1.84 kent if (sc->sc_nalts != 0) { 2071 1.84 kent memcpy(nai, sc->sc_alts, sizeof(*ai) * (sc->sc_nalts)); 2072 1.146 skrll kmem_free(sc->sc_alts, sizeof(*ai) * sc->sc_nalts); 2073 1.84 kent } 2074 1.42 christos sc->sc_alts = nai; 2075 1.122 mrg DPRINTFN(2,"adding alt=%d, enc=%d\n", 2076 1.122 mrg ai->alt, ai->encoding); 2077 1.1 augustss sc->sc_alts[sc->sc_nalts++] = *ai; 2078 1.1 augustss } 2079 1.1 augustss 2080 1.86 kent Static usbd_status 2081 1.99 christos uaudio_process_as(struct uaudio_softc *sc, const char *tbuf, int *offsp, 2082 1.78 kent int size, const usb_interface_descriptor_t *id) 2083 1.1 augustss { 2084 1.175 mlelstv const union usb_audio_streaming_interface_descriptor *asid; 2085 1.175 mlelstv const union usb_audio_streaming_type1_descriptor *asf1d; 2086 1.78 kent const usb_endpoint_descriptor_audio_t *ed; 2087 1.80 kent const usb_endpoint_descriptor_audio_t *epdesc1; 2088 1.78 kent const struct usb_audio_streaming_endpoint_descriptor *sed; 2089 1.179 mlelstv int format, chan __unused, prec, bps, enc, terminal; 2090 1.172 mlelstv int dir, type, sync, epcount; 2091 1.1 augustss struct as_info ai; 2092 1.138 martin const char *format_str __unused; 2093 1.172 mlelstv const uaudio_cs_descriptor_t *desc; 2094 1.172 mlelstv 2095 1.172 mlelstv DPRINTF("offset = %d < %d\n", *offsp, size); 2096 1.172 mlelstv 2097 1.172 mlelstv epcount = 0; 2098 1.172 mlelstv asid = NULL; 2099 1.172 mlelstv asf1d = NULL; 2100 1.172 mlelstv ed = NULL; 2101 1.172 mlelstv epdesc1 = NULL; 2102 1.172 mlelstv sed = NULL; 2103 1.1 augustss 2104 1.172 mlelstv while (*offsp < size) { 2105 1.172 mlelstv desc = (const uaudio_cs_descriptor_t *)(tbuf + *offsp); 2106 1.172 mlelstv if (*offsp + desc->bLength > size) 2107 1.172 mlelstv return USBD_INVAL; 2108 1.78 kent 2109 1.172 mlelstv switch (desc->bDescriptorType) { 2110 1.172 mlelstv case UDESC_CS_INTERFACE: 2111 1.172 mlelstv switch (desc->bDescriptorSubtype) { 2112 1.172 mlelstv case AS_GENERAL: 2113 1.172 mlelstv if (asid != NULL) 2114 1.172 mlelstv goto ignore; 2115 1.175 mlelstv asid = (const union usb_audio_streaming_interface_descriptor *) desc; 2116 1.176 mlelstv DPRINTF("asid: bTerminalLink=%d wFormatTag=%d bmFormats=0x%x bLength=%d\n", 2117 1.175 mlelstv asid->v1.bTerminalLink, UGETW(asid->v1.wFormatTag), 2118 1.176 mlelstv UGETDW(asid->v2.bmFormats), asid->v1.bLength); 2119 1.172 mlelstv break; 2120 1.172 mlelstv case FORMAT_TYPE: 2121 1.172 mlelstv if (asf1d != NULL) 2122 1.172 mlelstv goto ignore; 2123 1.175 mlelstv asf1d = (const union usb_audio_streaming_type1_descriptor *) desc; 2124 1.172 mlelstv DPRINTF("asf1d: bDescriptorType=%d bDescriptorSubtype=%d\n", 2125 1.175 mlelstv asf1d->v1.bDescriptorType, asf1d->v1.bDescriptorSubtype); 2126 1.175 mlelstv if (asf1d->v1.bFormatType != FORMAT_TYPE_I) { 2127 1.172 mlelstv aprint_normal_dev(sc->sc_dev, 2128 1.175 mlelstv "ignored setting with type %d format\n", asf1d->v1.bFormatType); 2129 1.172 mlelstv return USBD_NORMAL_COMPLETION; 2130 1.172 mlelstv } 2131 1.172 mlelstv break; 2132 1.172 mlelstv default: 2133 1.172 mlelstv goto ignore; 2134 1.172 mlelstv } 2135 1.172 mlelstv break; 2136 1.172 mlelstv case UDESC_ENDPOINT: 2137 1.172 mlelstv epcount++; 2138 1.172 mlelstv if (epcount > id->bNumEndpoints) 2139 1.172 mlelstv goto ignore; 2140 1.172 mlelstv switch (epcount) { 2141 1.172 mlelstv case 1: 2142 1.172 mlelstv ed = (const usb_endpoint_descriptor_audio_t *) desc; 2143 1.172 mlelstv DPRINTF("endpoint[0] bLength=%d bDescriptorType=%d " 2144 1.172 mlelstv "bEndpointAddress=%d bmAttributes=%#x wMaxPacketSize=%d " 2145 1.172 mlelstv "bInterval=%d bRefresh=%d bSynchAddress=%d\n", 2146 1.172 mlelstv ed->bLength, ed->bDescriptorType, ed->bEndpointAddress, 2147 1.172 mlelstv ed->bmAttributes, UGETW(ed->wMaxPacketSize), 2148 1.179 mlelstv ed->bInterval, 2149 1.179 mlelstv ed->bLength > 7 ? ed->bRefresh : 0, 2150 1.179 mlelstv ed->bLength > 8 ? ed->bSynchAddress : 0); 2151 1.172 mlelstv if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS) 2152 1.172 mlelstv return USBD_INVAL; 2153 1.172 mlelstv break; 2154 1.172 mlelstv case 2: 2155 1.172 mlelstv epdesc1 = (const usb_endpoint_descriptor_audio_t *) desc; 2156 1.172 mlelstv DPRINTF("endpoint[1] bLength=%d " 2157 1.172 mlelstv "bDescriptorType=%d bEndpointAddress=%d " 2158 1.172 mlelstv "bmAttributes=%#x wMaxPacketSize=%d bInterval=%d " 2159 1.172 mlelstv "bRefresh=%d bSynchAddress=%d\n", 2160 1.172 mlelstv epdesc1->bLength, epdesc1->bDescriptorType, 2161 1.172 mlelstv epdesc1->bEndpointAddress, epdesc1->bmAttributes, 2162 1.172 mlelstv UGETW(epdesc1->wMaxPacketSize), epdesc1->bInterval, 2163 1.179 mlelstv epdesc1->bLength > 7 ? epdesc1->bRefresh : 0, 2164 1.179 mlelstv epdesc1->bLength > 8 ? epdesc1->bSynchAddress : 0); 2165 1.175 mlelstv #if 0 2166 1.179 mlelstv if (epdesc1->bLength > 8 && epdesc1->bSynchAddress != 0) { 2167 1.172 mlelstv aprint_error_dev(sc->sc_dev, 2168 1.172 mlelstv "invalid endpoint: bSynchAddress=0\n"); 2169 1.172 mlelstv return USBD_INVAL; 2170 1.172 mlelstv } 2171 1.175 mlelstv #endif 2172 1.172 mlelstv if (UE_GET_XFERTYPE(epdesc1->bmAttributes) != UE_ISOCHRONOUS) { 2173 1.172 mlelstv aprint_error_dev(sc->sc_dev, 2174 1.172 mlelstv "invalid endpoint: bmAttributes=%#x\n", 2175 1.172 mlelstv epdesc1->bmAttributes); 2176 1.172 mlelstv return USBD_INVAL; 2177 1.172 mlelstv } 2178 1.175 mlelstv #if 0 2179 1.179 mlelstv if (ed->bLength > 8 && epdesc1->bEndpointAddress != ed->bSynchAddress) { 2180 1.172 mlelstv aprint_error_dev(sc->sc_dev, 2181 1.172 mlelstv "invalid endpoint addresses: " 2182 1.172 mlelstv "ep[0]->bSynchAddress=%#x " 2183 1.172 mlelstv "ep[1]->bEndpointAddress=%#x\n", 2184 1.172 mlelstv ed->bSynchAddress, epdesc1->bEndpointAddress); 2185 1.172 mlelstv return USBD_INVAL; 2186 1.172 mlelstv } 2187 1.175 mlelstv #endif 2188 1.172 mlelstv /* UE_GET_ADDR(epdesc1->bEndpointAddress), and epdesc1->bRefresh */ 2189 1.172 mlelstv break; 2190 1.172 mlelstv default: 2191 1.172 mlelstv goto ignore; 2192 1.172 mlelstv } 2193 1.172 mlelstv break; 2194 1.172 mlelstv case UDESC_CS_ENDPOINT: 2195 1.172 mlelstv switch (desc->bDescriptorSubtype) { 2196 1.172 mlelstv case AS_GENERAL: 2197 1.172 mlelstv if (sed != NULL) 2198 1.172 mlelstv goto ignore; 2199 1.172 mlelstv sed = (const struct usb_audio_streaming_endpoint_descriptor *) desc; 2200 1.182 andvar DPRINTF(" streaming_endpoint: offset=%d bLength=%d\n", *offsp, sed->bLength); 2201 1.172 mlelstv break; 2202 1.172 mlelstv default: 2203 1.172 mlelstv goto ignore; 2204 1.172 mlelstv } 2205 1.172 mlelstv break; 2206 1.172 mlelstv case UDESC_INTERFACE: 2207 1.172 mlelstv case UDESC_DEVICE: 2208 1.172 mlelstv goto leave; 2209 1.172 mlelstv default: 2210 1.172 mlelstv ignore: 2211 1.172 mlelstv aprint_normal_dev(sc->sc_dev, 2212 1.172 mlelstv "ignored descriptor type %d subtype %d\n", 2213 1.172 mlelstv desc->bDescriptorType, desc->bDescriptorSubtype); 2214 1.172 mlelstv break; 2215 1.172 mlelstv } 2216 1.1 augustss 2217 1.172 mlelstv *offsp += desc->bLength; 2218 1.3 augustss } 2219 1.172 mlelstv leave: 2220 1.3 augustss 2221 1.172 mlelstv if (asid == NULL) { 2222 1.172 mlelstv DPRINTF("%s", "No streaming interface descriptor found\n"); 2223 1.172 mlelstv return USBD_INVAL; 2224 1.172 mlelstv } 2225 1.172 mlelstv if (asf1d == NULL) { 2226 1.172 mlelstv DPRINTF("%s", "No format type descriptor found\n"); 2227 1.94 kent return USBD_INVAL; 2228 1.172 mlelstv } 2229 1.172 mlelstv if (ed == NULL) { 2230 1.172 mlelstv DPRINTF("%s", "No endpoint descriptor found\n"); 2231 1.94 kent return USBD_INVAL; 2232 1.172 mlelstv } 2233 1.172 mlelstv if (sed == NULL) { 2234 1.172 mlelstv DPRINTF("%s", "No streaming endpoint descriptor found\n"); 2235 1.94 kent return USBD_INVAL; 2236 1.172 mlelstv } 2237 1.5 augustss 2238 1.5 augustss dir = UE_GET_DIR(ed->bEndpointAddress); 2239 1.5 augustss type = UE_GET_ISO_TYPE(ed->bmAttributes); 2240 1.31 augustss if ((usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_AU_INP_ASYNC) && 2241 1.31 augustss dir == UE_DIR_IN && type == UE_ISO_ADAPT) 2242 1.31 augustss type = UE_ISO_ASYNC; 2243 1.40 augustss /* We can't handle endpoints that need a sync pipe yet. */ 2244 1.80 kent sync = FALSE; 2245 1.78 kent if (dir == UE_DIR_IN && type == UE_ISO_ADAPT) { 2246 1.80 kent sync = TRUE; 2247 1.80 kent #ifndef UAUDIO_MULTIPLE_ENDPOINTS 2248 1.156 nakayama aprint_normal_dev(sc->sc_dev, 2249 1.113 cube "ignored input endpoint of type adaptive\n"); 2250 1.94 kent return USBD_NORMAL_COMPLETION; 2251 1.80 kent #endif 2252 1.78 kent } 2253 1.78 kent if (dir != UE_DIR_IN && type == UE_ISO_ASYNC) { 2254 1.80 kent sync = TRUE; 2255 1.80 kent #ifndef UAUDIO_MULTIPLE_ENDPOINTS 2256 1.156 nakayama aprint_normal_dev(sc->sc_dev, 2257 1.113 cube "ignored output endpoint of type async\n"); 2258 1.94 kent return USBD_NORMAL_COMPLETION; 2259 1.80 kent #endif 2260 1.1 augustss } 2261 1.102 christos #ifdef UAUDIO_MULTIPLE_ENDPOINTS 2262 1.80 kent if (sync && id->bNumEndpoints <= 1) { 2263 1.113 cube aprint_error_dev(sc->sc_dev, 2264 1.113 cube "a sync-pipe endpoint but no other endpoint\n"); 2265 1.80 kent return USBD_INVAL; 2266 1.80 kent } 2267 1.102 christos #endif 2268 1.80 kent if (!sync && id->bNumEndpoints > 1) { 2269 1.113 cube aprint_error_dev(sc->sc_dev, 2270 1.113 cube "non sync-pipe endpoint but multiple endpoints\n"); 2271 1.80 kent return USBD_INVAL; 2272 1.80 kent } 2273 1.80 kent 2274 1.175 mlelstv switch (sc->sc_version) { 2275 1.175 mlelstv case UAUDIO_VERSION1: 2276 1.175 mlelstv format = UGETW(asid->v1.wFormatTag); 2277 1.175 mlelstv chan = asf1d->v1.bNrChannels; 2278 1.175 mlelstv prec = asf1d->v1.bBitResolution; 2279 1.175 mlelstv bps = asf1d->v1.bSubFrameSize; 2280 1.175 mlelstv break; 2281 1.175 mlelstv case UAUDIO_VERSION2: 2282 1.175 mlelstv format = UGETDW(asid->v2.bmFormats); 2283 1.175 mlelstv chan = asid->v2.bNrChannels; 2284 1.175 mlelstv prec = asf1d->v2.bBitResolution; 2285 1.175 mlelstv bps = asf1d->v2.bSubslotSize; 2286 1.175 mlelstv break; 2287 1.175 mlelstv default: 2288 1.175 mlelstv aprint_error_dev(sc->sc_dev, 2289 1.175 mlelstv "Unknown audio class %d\n", sc->sc_version); 2290 1.175 mlelstv return USBD_INVAL; 2291 1.175 mlelstv } 2292 1.175 mlelstv if ((prec != 8 && prec != 16 && prec != 24 && prec != 32) || (bps < 1 || bps > 4)) { 2293 1.156 nakayama aprint_normal_dev(sc->sc_dev, 2294 1.175 mlelstv "ignored setting with precision %d bps %d\n", prec, bps); 2295 1.94 kent return USBD_NORMAL_COMPLETION; 2296 1.1 augustss } 2297 1.175 mlelstv enc = AUDIO_ENCODING_NONE; 2298 1.175 mlelstv switch (sc->sc_version) { 2299 1.175 mlelstv case UAUDIO_VERSION1: 2300 1.179 mlelstv terminal = 0; 2301 1.175 mlelstv switch (format) { 2302 1.175 mlelstv case UA_FMT_PCM: 2303 1.175 mlelstv if (prec == 8) { 2304 1.175 mlelstv sc->sc_altflags |= HAS_8; 2305 1.175 mlelstv } else if (prec == 16) { 2306 1.175 mlelstv sc->sc_altflags |= HAS_16; 2307 1.175 mlelstv } else if (prec == 24) { 2308 1.175 mlelstv sc->sc_altflags |= HAS_24; 2309 1.175 mlelstv } else if (prec == 32) { 2310 1.175 mlelstv sc->sc_altflags |= HAS_32; 2311 1.175 mlelstv } 2312 1.175 mlelstv enc = AUDIO_ENCODING_SLINEAR_LE; 2313 1.175 mlelstv format_str = "pcm"; 2314 1.175 mlelstv break; 2315 1.175 mlelstv case UA_FMT_PCM8: 2316 1.175 mlelstv enc = AUDIO_ENCODING_ULINEAR_LE; 2317 1.175 mlelstv sc->sc_altflags |= HAS_8U; 2318 1.175 mlelstv format_str = "pcm8"; 2319 1.175 mlelstv break; 2320 1.175 mlelstv case UA_FMT_ALAW: 2321 1.175 mlelstv enc = AUDIO_ENCODING_ALAW; 2322 1.175 mlelstv sc->sc_altflags |= HAS_ALAW; 2323 1.175 mlelstv format_str = "alaw"; 2324 1.175 mlelstv break; 2325 1.175 mlelstv case UA_FMT_MULAW: 2326 1.175 mlelstv enc = AUDIO_ENCODING_ULAW; 2327 1.175 mlelstv sc->sc_altflags |= HAS_MULAW; 2328 1.175 mlelstv format_str = "mulaw"; 2329 1.175 mlelstv break; 2330 1.175 mlelstv #ifdef notyet 2331 1.175 mlelstv case UA_FMT_IEEE_FLOAT: 2332 1.175 mlelstv break; 2333 1.175 mlelstv #endif 2334 1.51 kent } 2335 1.1 augustss break; 2336 1.175 mlelstv case UAUDIO_VERSION2: 2337 1.179 mlelstv terminal = asid->v2.bTerminalLink; 2338 1.175 mlelstv if (format & UA_V2_FMT_PCM) { 2339 1.175 mlelstv if (prec == 8) { 2340 1.175 mlelstv sc->sc_altflags |= HAS_8; 2341 1.175 mlelstv } else if (prec == 16) { 2342 1.175 mlelstv sc->sc_altflags |= HAS_16; 2343 1.175 mlelstv } else if (prec == 24) { 2344 1.175 mlelstv sc->sc_altflags |= HAS_24; 2345 1.175 mlelstv } else if (prec == 32) { 2346 1.175 mlelstv sc->sc_altflags |= HAS_32; 2347 1.175 mlelstv } 2348 1.175 mlelstv enc = AUDIO_ENCODING_SLINEAR_LE; 2349 1.175 mlelstv format_str = "pcm"; 2350 1.175 mlelstv } else if (format & UA_V2_FMT_PCM8) { 2351 1.175 mlelstv enc = AUDIO_ENCODING_ULINEAR_LE; 2352 1.175 mlelstv sc->sc_altflags |= HAS_8U; 2353 1.175 mlelstv format_str = "pcm8"; 2354 1.175 mlelstv } else if (format & UA_V2_FMT_ALAW) { 2355 1.175 mlelstv enc = AUDIO_ENCODING_ALAW; 2356 1.175 mlelstv sc->sc_altflags |= HAS_ALAW; 2357 1.175 mlelstv format_str = "alaw"; 2358 1.175 mlelstv } else if (format & UA_V2_FMT_MULAW) { 2359 1.175 mlelstv enc = AUDIO_ENCODING_ULAW; 2360 1.175 mlelstv sc->sc_altflags |= HAS_MULAW; 2361 1.175 mlelstv format_str = "mulaw"; 2362 1.175 mlelstv #ifdef notyet 2363 1.175 mlelstv } else if (format & UA_V2_FMT_IEEE_FLOAT) { 2364 1.175 mlelstv #endif 2365 1.175 mlelstv } 2366 1.1 augustss break; 2367 1.175 mlelstv } 2368 1.175 mlelstv if (enc == AUDIO_ENCODING_NONE) { 2369 1.156 nakayama aprint_normal_dev(sc->sc_dev, 2370 1.175 mlelstv "ignored setting with format 0x%08x\n", format); 2371 1.94 kent return USBD_NORMAL_COMPLETION; 2372 1.1 augustss } 2373 1.78 kent #ifdef UAUDIO_DEBUG 2374 1.179 mlelstv aprint_debug_dev(sc->sc_dev, "%s: %dch, %d/%dbit, %s,", 2375 1.179 mlelstv dir == UE_DIR_IN ? "recording" : "playback", 2376 1.179 mlelstv chan, prec, bps * 8, format_str); 2377 1.176 mlelstv switch (sc->sc_version) { 2378 1.176 mlelstv case UAUDIO_VERSION1: 2379 1.176 mlelstv if (asf1d->v1.bSamFreqType == UA_SAMP_CONTINUOUS) { 2380 1.176 mlelstv aprint_debug(" %d-%dHz\n", UA_SAMP_LO(&asf1d->v1), 2381 1.176 mlelstv UA_SAMP_HI(&asf1d->v1)); 2382 1.176 mlelstv } else { 2383 1.176 mlelstv int r; 2384 1.176 mlelstv aprint_debug(" %d", UA_GETSAMP(&asf1d->v1, 0)); 2385 1.176 mlelstv for (r = 1; r < asf1d->v1.bSamFreqType; r++) 2386 1.176 mlelstv aprint_debug(",%d", UA_GETSAMP(&asf1d->v1, r)); 2387 1.176 mlelstv aprint_debug("Hz\n"); 2388 1.176 mlelstv } 2389 1.176 mlelstv break; 2390 1.179 mlelstv /* UAUDIO_VERSION2 has no frequency information in the format */ 2391 1.78 kent } 2392 1.78 kent #endif 2393 1.1 augustss ai.alt = id->bAlternateSetting; 2394 1.1 augustss ai.encoding = enc; 2395 1.50 kent ai.attributes = sed->bmAttributes; 2396 1.1 augustss ai.idesc = id; 2397 1.1 augustss ai.edesc = ed; 2398 1.80 kent ai.edesc1 = epdesc1; 2399 1.1 augustss ai.asf1desc = asf1d; 2400 1.50 kent ai.sc_busy = 0; 2401 1.175 mlelstv ai.nchan = chan; 2402 1.103 mrg ai.aformat = NULL; 2403 1.103 mrg ai.ifaceh = NULL; 2404 1.179 mlelstv ai.terminal = terminal; 2405 1.1 augustss uaudio_add_alt(sc, &ai); 2406 1.50 kent #ifdef UAUDIO_DEBUG 2407 1.78 kent if (ai.attributes & UA_SED_FREQ_CONTROL) 2408 1.122 mrg DPRINTFN(1, "%s", "FREQ_CONTROL\n"); 2409 1.78 kent if (ai.attributes & UA_SED_PITCH_CONTROL) 2410 1.122 mrg DPRINTFN(1, "%s", "PITCH_CONTROL\n"); 2411 1.50 kent #endif 2412 1.47 jdolecek sc->sc_mode |= (dir == UE_DIR_OUT) ? AUMODE_PLAY : AUMODE_RECORD; 2413 1.47 jdolecek 2414 1.94 kent return USBD_NORMAL_COMPLETION; 2415 1.1 augustss } 2416 1.56 kent 2417 1.86 kent Static usbd_status 2418 1.78 kent uaudio_identify_as(struct uaudio_softc *sc, 2419 1.78 kent const usb_config_descriptor_t *cdesc) 2420 1.1 augustss { 2421 1.78 kent const usb_interface_descriptor_t *id; 2422 1.99 christos const char *tbuf; 2423 1.1 augustss int size, offs; 2424 1.1 augustss 2425 1.1 augustss size = UGETW(cdesc->wTotalLength); 2426 1.99 christos tbuf = (const char *)cdesc; 2427 1.1 augustss 2428 1.1 augustss /* Locate the AudioStreaming interface descriptor. */ 2429 1.1 augustss offs = 0; 2430 1.99 christos id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOSTREAM); 2431 1.9 augustss if (id == NULL) 2432 1.94 kent return USBD_INVAL; 2433 1.1 augustss 2434 1.1 augustss /* Loop through all the alternate settings. */ 2435 1.1 augustss while (offs <= size) { 2436 1.122 mrg DPRINTFN(2, "interface=%d offset=%d\n", 2437 1.122 mrg id->bInterfaceNumber, offs); 2438 1.1 augustss switch (id->bNumEndpoints) { 2439 1.1 augustss case 0: 2440 1.122 mrg DPRINTFN(2, "AS null alt=%d\n", 2441 1.122 mrg id->bAlternateSetting); 2442 1.1 augustss sc->sc_nullalt = id->bAlternateSetting; 2443 1.1 augustss break; 2444 1.1 augustss case 1: 2445 1.80 kent #ifdef UAUDIO_MULTIPLE_ENDPOINTS 2446 1.80 kent case 2: 2447 1.80 kent #endif 2448 1.99 christos uaudio_process_as(sc, tbuf, &offs, size, id); 2449 1.1 augustss break; 2450 1.1 augustss default: 2451 1.113 cube aprint_error_dev(sc->sc_dev, 2452 1.113 cube "ignored audio interface with %d endpoints\n", 2453 1.113 cube id->bNumEndpoints); 2454 1.1 augustss break; 2455 1.1 augustss } 2456 1.168 ryoon id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOSTREAM); 2457 1.9 augustss if (id == NULL) 2458 1.1 augustss break; 2459 1.1 augustss } 2460 1.1 augustss if (offs > size) 2461 1.94 kent return USBD_INVAL; 2462 1.122 mrg DPRINTF("%d alts available\n", sc->sc_nalts); 2463 1.47 jdolecek 2464 1.74 mycroft if (sc->sc_mode == 0) { 2465 1.113 cube aprint_error_dev(sc->sc_dev, "no usable endpoint found\n"); 2466 1.94 kent return USBD_INVAL; 2467 1.5 augustss } 2468 1.47 jdolecek 2469 1.175 mlelstv if (sc->sc_nalts == 0) { 2470 1.175 mlelstv aprint_error_dev(sc->sc_dev, "no audio formats found\n"); 2471 1.175 mlelstv return USBD_INVAL; 2472 1.175 mlelstv } 2473 1.175 mlelstv 2474 1.175 mlelstv return USBD_NORMAL_COMPLETION; 2475 1.175 mlelstv } 2476 1.175 mlelstv 2477 1.175 mlelstv 2478 1.175 mlelstv Static u_int 2479 1.178 mlelstv uaudio_get_rates(struct uaudio_softc *sc, int mode, u_int *freqs, u_int len) 2480 1.175 mlelstv { 2481 1.175 mlelstv struct mixerctl *mc; 2482 1.180 mlelstv u_int freq, start, end, step; 2483 1.180 mlelstv u_int i, n; 2484 1.180 mlelstv u_int k, count; 2485 1.180 mlelstv int j; 2486 1.175 mlelstv 2487 1.180 mlelstv /* 2488 1.180 mlelstv * With UAC2 the sample rate isn't part of the data format, 2489 1.180 mlelstv * instead, you have separate clock sources that may be 2490 1.180 mlelstv * assigned to individual terminals (inputs, outputs). 2491 1.180 mlelstv * 2492 1.180 mlelstv * For audio(4) we only distinguish between input and output 2493 1.180 mlelstv * formats and collect the unique rates from all possible clock 2494 1.180 mlelstv * sources. 2495 1.180 mlelstv */ 2496 1.175 mlelstv n = 0; 2497 1.175 mlelstv for (j = 0; j < sc->sc_nratectls; ++j) { 2498 1.178 mlelstv 2499 1.178 mlelstv /* 2500 1.178 mlelstv * skip rates not associated with a terminal 2501 1.178 mlelstv * of the required mode (record/play) 2502 1.178 mlelstv */ 2503 1.178 mlelstv if ((sc->sc_ratemode[j] & mode) == 0) 2504 1.178 mlelstv continue; 2505 1.178 mlelstv 2506 1.175 mlelstv mc = &sc->sc_ctls[sc->sc_ratectls[j]]; 2507 1.175 mlelstv count = mc->nranges ? mc->nranges : 1; 2508 1.175 mlelstv for (k = 0; k < count; ++k) { 2509 1.175 mlelstv start = (u_int) mc->ranges[k].minval; 2510 1.175 mlelstv end = (u_int) mc->ranges[k].maxval; 2511 1.175 mlelstv step = (u_int) mc->ranges[k].resval; 2512 1.175 mlelstv for (freq = start; freq <= end; freq += step) { 2513 1.180 mlelstv /* remove duplicates */ 2514 1.180 mlelstv for (i = 0; i < n; ++i) { 2515 1.180 mlelstv if (freqs[i] == freq) 2516 1.180 mlelstv break; 2517 1.180 mlelstv } 2518 1.180 mlelstv if (i < n) { 2519 1.180 mlelstv if (step == 0) 2520 1.180 mlelstv break; 2521 1.180 mlelstv continue; 2522 1.180 mlelstv } 2523 1.180 mlelstv 2524 1.180 mlelstv /* store or count */ 2525 1.175 mlelstv if (len != 0) { 2526 1.175 mlelstv if (n >= len) 2527 1.175 mlelstv goto done; 2528 1.175 mlelstv freqs[n] = freq; 2529 1.175 mlelstv } 2530 1.175 mlelstv ++n; 2531 1.175 mlelstv if (step == 0) 2532 1.175 mlelstv break; 2533 1.175 mlelstv } 2534 1.175 mlelstv } 2535 1.175 mlelstv } 2536 1.175 mlelstv 2537 1.175 mlelstv done: 2538 1.175 mlelstv return n; 2539 1.175 mlelstv } 2540 1.175 mlelstv 2541 1.175 mlelstv Static void 2542 1.175 mlelstv uaudio_build_formats(struct uaudio_softc *sc) 2543 1.175 mlelstv { 2544 1.175 mlelstv struct audio_format *auf; 2545 1.175 mlelstv const struct as_info *as; 2546 1.175 mlelstv const union usb_audio_streaming_type1_descriptor *t1desc; 2547 1.175 mlelstv int i, j; 2548 1.175 mlelstv 2549 1.92 kent /* build audio_format array */ 2550 1.162 isaki sc->sc_formats = kmem_zalloc(sizeof(struct audio_format) * sc->sc_nalts, 2551 1.146 skrll KM_SLEEP); 2552 1.92 kent sc->sc_nformats = sc->sc_nalts; 2553 1.175 mlelstv 2554 1.92 kent for (i = 0; i < sc->sc_nalts; i++) { 2555 1.92 kent auf = &sc->sc_formats[i]; 2556 1.175 mlelstv as = &sc->sc_alts[i]; 2557 1.175 mlelstv t1desc = as->asf1desc; 2558 1.175 mlelstv if (UE_GET_DIR(as->edesc->bEndpointAddress) == UE_DIR_OUT) 2559 1.92 kent auf->mode = AUMODE_PLAY; 2560 1.92 kent else 2561 1.92 kent auf->mode = AUMODE_RECORD; 2562 1.175 mlelstv auf->encoding = as->encoding; 2563 1.92 kent auf->channel_mask = sc->sc_channel_config; 2564 1.175 mlelstv 2565 1.175 mlelstv switch (sc->sc_version) { 2566 1.175 mlelstv case UAUDIO_VERSION1: 2567 1.175 mlelstv auf->validbits = t1desc->v1.bBitResolution; 2568 1.175 mlelstv auf->precision = t1desc->v1.bSubFrameSize * 8; 2569 1.175 mlelstv auf->channels = t1desc->v1.bNrChannels; 2570 1.175 mlelstv 2571 1.175 mlelstv auf->frequency_type = t1desc->v1.bSamFreqType; 2572 1.175 mlelstv if (t1desc->v1.bSamFreqType == UA_SAMP_CONTINUOUS) { 2573 1.175 mlelstv auf->frequency[0] = UA_SAMP_LO(&t1desc->v1); 2574 1.175 mlelstv auf->frequency[1] = UA_SAMP_HI(&t1desc->v1); 2575 1.175 mlelstv } else { 2576 1.175 mlelstv for (j = 0; j < t1desc->v1.bSamFreqType; j++) { 2577 1.175 mlelstv if (j >= AUFMT_MAX_FREQUENCIES) { 2578 1.175 mlelstv aprint_error("%s: please increase " 2579 1.175 mlelstv "AUFMT_MAX_FREQUENCIES to %d\n", 2580 1.175 mlelstv __func__, t1desc->v1.bSamFreqType); 2581 1.175 mlelstv auf->frequency_type = 2582 1.175 mlelstv AUFMT_MAX_FREQUENCIES; 2583 1.175 mlelstv break; 2584 1.175 mlelstv } 2585 1.175 mlelstv auf->frequency[j] = UA_GETSAMP(&t1desc->v1, j); 2586 1.130 bouyer } 2587 1.92 kent } 2588 1.175 mlelstv break; 2589 1.175 mlelstv case UAUDIO_VERSION2: 2590 1.175 mlelstv auf->validbits = t1desc->v2.bBitResolution; 2591 1.175 mlelstv auf->precision = t1desc->v2.bSubslotSize * 8; 2592 1.175 mlelstv auf->channels = as->nchan; 2593 1.175 mlelstv 2594 1.175 mlelstv #if 0 2595 1.178 mlelstv auf->frequency_type = uaudio_get_rates(sc, auf->mode, NULL, 0); 2596 1.175 mlelstv if (auf->frequency_type >= AUFMT_MAX_FREQUENCIES) { 2597 1.175 mlelstv aprint_error("%s: please increase " 2598 1.175 mlelstv "AUFMT_MAX_FREQUENCIES to %d\n", 2599 1.175 mlelstv __func__, auf->frequency_type); 2600 1.175 mlelstv } 2601 1.175 mlelstv #endif 2602 1.175 mlelstv 2603 1.178 mlelstv auf->frequency_type = uaudio_get_rates(sc, 2604 1.178 mlelstv auf->mode, auf->frequency, AUFMT_MAX_FREQUENCIES); 2605 1.178 mlelstv 2606 1.178 mlelstv /* 2607 1.178 mlelstv * if rate query failed, guess a rate 2608 1.178 mlelstv */ 2609 1.178 mlelstv if (auf->frequency_type == UA_SAMP_CONTINUOUS) { 2610 1.178 mlelstv auf->frequency[0] = 48000; 2611 1.178 mlelstv auf->frequency[1] = 48000; 2612 1.178 mlelstv } 2613 1.178 mlelstv 2614 1.175 mlelstv break; 2615 1.92 kent } 2616 1.175 mlelstv 2617 1.179 mlelstv DPRINTF("alt[%d] = %d/%d %dch %u[%u,%u,...] alt %u\n", i, 2618 1.179 mlelstv auf->validbits, auf->precision, auf->channels, auf->frequency_type, 2619 1.179 mlelstv auf->frequency[0], auf->frequency[1], 2620 1.179 mlelstv as->idesc->bAlternateSetting); 2621 1.179 mlelstv 2622 1.92 kent sc->sc_alts[i].aformat = auf; 2623 1.92 kent } 2624 1.1 augustss } 2625 1.1 augustss 2626 1.142 gson #ifdef UAUDIO_DEBUG 2627 1.142 gson Static void 2628 1.142 gson uaudio_dump_tml(struct terminal_list *tml) { 2629 1.142 gson if (tml == NULL) { 2630 1.142 gson printf("NULL"); 2631 1.142 gson } else { 2632 1.142 gson int i; 2633 1.142 gson for (i = 0; i < tml->size; i++) 2634 1.142 gson printf("%s ", uaudio_get_terminal_name 2635 1.142 gson (tml->terminals[i])); 2636 1.142 gson } 2637 1.142 gson printf("\n"); 2638 1.142 gson } 2639 1.142 gson #endif 2640 1.142 gson 2641 1.86 kent Static usbd_status 2642 1.78 kent uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc) 2643 1.1 augustss { 2644 1.82 kent struct io_terminal* iot; 2645 1.78 kent const usb_interface_descriptor_t *id; 2646 1.78 kent const struct usb_audio_control_descriptor *acdp; 2647 1.109 drochner const uaudio_cs_descriptor_t *dp; 2648 1.178 mlelstv const union usb_audio_output_terminal *pot; 2649 1.82 kent struct terminal_list *tml; 2650 1.99 christos const char *tbuf, *ibuf, *ibufend; 2651 1.120 jakllsch int size, offs, ndps, i, j; 2652 1.1 augustss 2653 1.1 augustss size = UGETW(cdesc->wTotalLength); 2654 1.99 christos tbuf = (const char *)cdesc; 2655 1.1 augustss 2656 1.1 augustss /* Locate the AudioControl interface descriptor. */ 2657 1.1 augustss offs = 0; 2658 1.99 christos id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOCONTROL); 2659 1.14 augustss if (id == NULL) 2660 1.94 kent return USBD_INVAL; 2661 1.146 skrll if (offs + sizeof(*acdp) > size) 2662 1.94 kent return USBD_INVAL; 2663 1.1 augustss sc->sc_ac_iface = id->bInterfaceNumber; 2664 1.122 mrg DPRINTFN(2,"AC interface is %d\n", sc->sc_ac_iface); 2665 1.1 augustss 2666 1.1 augustss /* A class-specific AC interface header should follow. */ 2667 1.99 christos ibuf = tbuf + offs; 2668 1.120 jakllsch ibufend = tbuf + size; 2669 1.78 kent acdp = (const struct usb_audio_control_descriptor *)ibuf; 2670 1.1 augustss if (acdp->bDescriptorType != UDESC_CS_INTERFACE || 2671 1.1 augustss acdp->bDescriptorSubtype != UDESCSUB_AC_HEADER) 2672 1.94 kent return USBD_INVAL; 2673 1.5 augustss 2674 1.175 mlelstv if (!(usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_BAD_ADC)) { 2675 1.175 mlelstv sc->sc_version = UGETW(acdp->bcdADC); 2676 1.175 mlelstv } else { 2677 1.175 mlelstv sc->sc_version = UAUDIO_VERSION1; 2678 1.175 mlelstv } 2679 1.175 mlelstv 2680 1.175 mlelstv switch (sc->sc_version) { 2681 1.175 mlelstv case UAUDIO_VERSION1: 2682 1.175 mlelstv case UAUDIO_VERSION2: 2683 1.175 mlelstv break; 2684 1.175 mlelstv default: 2685 1.94 kent return USBD_INVAL; 2686 1.175 mlelstv } 2687 1.1 augustss 2688 1.7 augustss sc->sc_audio_rev = UGETW(acdp->bcdADC); 2689 1.122 mrg DPRINTFN(2, "found AC header, vers=%03x\n", sc->sc_audio_rev); 2690 1.1 augustss 2691 1.1 augustss sc->sc_nullalt = -1; 2692 1.1 augustss 2693 1.1 augustss /* Scan through all the AC specific descriptors */ 2694 1.109 drochner dp = (const uaudio_cs_descriptor_t *)ibuf; 2695 1.1 augustss ndps = 0; 2696 1.82 kent iot = malloc(sizeof(struct io_terminal) * 256, M_TEMP, M_NOWAIT | M_ZERO); 2697 1.82 kent if (iot == NULL) { 2698 1.113 cube aprint_error("%s: no memory\n", __func__); 2699 1.82 kent return USBD_NOMEM; 2700 1.82 kent } 2701 1.1 augustss for (;;) { 2702 1.1 augustss ibuf += dp->bLength; 2703 1.1 augustss if (ibuf >= ibufend) 2704 1.1 augustss break; 2705 1.109 drochner dp = (const uaudio_cs_descriptor_t *)ibuf; 2706 1.97 martin if (ibuf + dp->bLength > ibufend) { 2707 1.97 martin free(iot, M_TEMP); 2708 1.94 kent return USBD_INVAL; 2709 1.97 martin } 2710 1.120 jakllsch if (dp->bDescriptorType != UDESC_CS_INTERFACE) 2711 1.120 jakllsch break; 2712 1.178 mlelstv switch (sc->sc_version) { 2713 1.178 mlelstv case UAUDIO_VERSION1: 2714 1.178 mlelstv i = ((const union usb_audio_input_terminal *)dp)->v1.bTerminalId; 2715 1.178 mlelstv break; 2716 1.178 mlelstv case UAUDIO_VERSION2: 2717 1.178 mlelstv i = ((const union usb_audio_input_terminal *)dp)->v2.bTerminalId; 2718 1.178 mlelstv break; 2719 1.178 mlelstv default: 2720 1.178 mlelstv free(iot, M_TEMP); 2721 1.178 mlelstv return USBD_INVAL; 2722 1.178 mlelstv } 2723 1.82 kent iot[i].d.desc = dp; 2724 1.1 augustss if (i > ndps) 2725 1.1 augustss ndps = i; 2726 1.1 augustss } 2727 1.1 augustss ndps++; 2728 1.1 augustss 2729 1.82 kent /* construct io_terminal */ 2730 1.82 kent for (i = 0; i < ndps; i++) { 2731 1.82 kent dp = iot[i].d.desc; 2732 1.82 kent if (dp == NULL) 2733 1.82 kent continue; 2734 1.82 kent if (dp->bDescriptorSubtype != UDESCSUB_AC_OUTPUT) 2735 1.82 kent continue; 2736 1.82 kent pot = iot[i].d.ot; 2737 1.178 mlelstv switch (sc->sc_version) { 2738 1.178 mlelstv case UAUDIO_VERSION1: 2739 1.178 mlelstv tml = uaudio_io_terminaltype(sc, UGETW(pot->v1.wTerminalType), iot, i); 2740 1.178 mlelstv break; 2741 1.178 mlelstv case UAUDIO_VERSION2: 2742 1.178 mlelstv tml = uaudio_io_terminaltype(sc, UGETW(pot->v2.wTerminalType), iot, i); 2743 1.178 mlelstv break; 2744 1.178 mlelstv default: 2745 1.178 mlelstv tml = NULL; 2746 1.178 mlelstv break; 2747 1.178 mlelstv } 2748 1.82 kent if (tml != NULL) 2749 1.82 kent free(tml, M_TEMP); 2750 1.82 kent } 2751 1.82 kent 2752 1.82 kent #ifdef UAUDIO_DEBUG 2753 1.82 kent for (i = 0; i < 256; i++) { 2754 1.178 mlelstv union usb_audio_cluster cluster; 2755 1.91 kent 2756 1.82 kent if (iot[i].d.desc == NULL) 2757 1.82 kent continue; 2758 1.118 dyoung printf("id %d:\t", i); 2759 1.82 kent switch (iot[i].d.desc->bDescriptorSubtype) { 2760 1.82 kent case UDESCSUB_AC_INPUT: 2761 1.118 dyoung printf("AC_INPUT type=%s\n", uaudio_get_terminal_name 2762 1.178 mlelstv (UGETW(iot[i].d.it->v1.wTerminalType))); 2763 1.118 dyoung printf("\t"); 2764 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot); 2765 1.178 mlelstv uaudio_dump_cluster(sc, &cluster); 2766 1.118 dyoung printf("\n"); 2767 1.82 kent break; 2768 1.82 kent case UDESCSUB_AC_OUTPUT: 2769 1.118 dyoung printf("AC_OUTPUT type=%s ", uaudio_get_terminal_name 2770 1.178 mlelstv (UGETW(iot[i].d.ot->v1.wTerminalType))); 2771 1.178 mlelstv printf("src=%d\n", iot[i].d.ot->v1.bSourceId); 2772 1.82 kent break; 2773 1.82 kent case UDESCSUB_AC_MIXER: 2774 1.118 dyoung printf("AC_MIXER src="); 2775 1.82 kent for (j = 0; j < iot[i].d.mu->bNrInPins; j++) 2776 1.118 dyoung printf("%d ", iot[i].d.mu->baSourceId[j]); 2777 1.118 dyoung printf("\n\t"); 2778 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot); 2779 1.178 mlelstv uaudio_dump_cluster(sc, &cluster); 2780 1.118 dyoung printf("\n"); 2781 1.82 kent break; 2782 1.82 kent case UDESCSUB_AC_SELECTOR: 2783 1.118 dyoung printf("AC_SELECTOR src="); 2784 1.82 kent for (j = 0; j < iot[i].d.su->bNrInPins; j++) 2785 1.118 dyoung printf("%d ", iot[i].d.su->baSourceId[j]); 2786 1.118 dyoung printf("\n"); 2787 1.82 kent break; 2788 1.82 kent case UDESCSUB_AC_FEATURE: 2789 1.179 mlelstv switch (sc->sc_version) { 2790 1.179 mlelstv case UAUDIO_VERSION1: 2791 1.179 mlelstv printf("AC_FEATURE src=%d\n", iot[i].d.fu->v1.bSourceId); 2792 1.179 mlelstv break; 2793 1.179 mlelstv case UAUDIO_VERSION2: 2794 1.179 mlelstv printf("AC_FEATURE src=%d\n", iot[i].d.fu->v2.bSourceId); 2795 1.179 mlelstv break; 2796 1.179 mlelstv } 2797 1.82 kent break; 2798 1.175 mlelstv case UDESCSUB_AC_EFFECT: 2799 1.179 mlelstv switch (sc->sc_version) { 2800 1.179 mlelstv case UAUDIO_VERSION1: 2801 1.179 mlelstv printf("AC_EFFECT src=%d\n", iot[i].d.fu->v1.bSourceId); 2802 1.179 mlelstv break; 2803 1.179 mlelstv case UAUDIO_VERSION2: 2804 1.179 mlelstv printf("AC_EFFECT src=%d\n", iot[i].d.fu->v2.bSourceId); 2805 1.179 mlelstv break; 2806 1.179 mlelstv } 2807 1.175 mlelstv break; 2808 1.82 kent case UDESCSUB_AC_PROCESSING: 2809 1.118 dyoung printf("AC_PROCESSING src="); 2810 1.82 kent for (j = 0; j < iot[i].d.pu->bNrInPins; j++) 2811 1.118 dyoung printf("%d ", iot[i].d.pu->baSourceId[j]); 2812 1.118 dyoung printf("\n\t"); 2813 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot); 2814 1.178 mlelstv uaudio_dump_cluster(sc, &cluster); 2815 1.118 dyoung printf("\n"); 2816 1.82 kent break; 2817 1.82 kent case UDESCSUB_AC_EXTENSION: 2818 1.118 dyoung printf("AC_EXTENSION src="); 2819 1.82 kent for (j = 0; j < iot[i].d.eu->bNrInPins; j++) 2820 1.118 dyoung printf("%d ", iot[i].d.eu->baSourceId[j]); 2821 1.118 dyoung printf("\n\t"); 2822 1.178 mlelstv cluster = uaudio_get_cluster(sc, i, iot); 2823 1.178 mlelstv uaudio_dump_cluster(sc, &cluster); 2824 1.118 dyoung printf("\n"); 2825 1.82 kent break; 2826 1.175 mlelstv case UDESCSUB_AC_CLKSRC: 2827 1.176 mlelstv printf("AC_CLKSRC src=%d\n", iot[i].d.cu->iClockSource); 2828 1.175 mlelstv break; 2829 1.175 mlelstv case UDESCSUB_AC_CLKSEL: 2830 1.175 mlelstv printf("AC_CLKSEL src="); 2831 1.175 mlelstv for (j = 0; j < iot[i].d.su->bNrInPins; j++) 2832 1.176 mlelstv printf("%d ", iot[i].d.su->baSourceId[j]); 2833 1.175 mlelstv printf("\n"); 2834 1.175 mlelstv break; 2835 1.175 mlelstv case UDESCSUB_AC_CLKMULT: 2836 1.175 mlelstv printf("AC_CLKMULT not supported\n"); 2837 1.175 mlelstv break; 2838 1.175 mlelstv case UDESCSUB_AC_RATECONV: 2839 1.175 mlelstv printf("AC_RATEVONC not supported\n"); 2840 1.175 mlelstv break; 2841 1.82 kent default: 2842 1.118 dyoung printf("unknown audio control (subtype=%d)\n", 2843 1.89 kent iot[i].d.desc->bDescriptorSubtype); 2844 1.82 kent } 2845 1.82 kent for (j = 0; j < iot[i].inputs_size; j++) { 2846 1.118 dyoung printf("\tinput%d: ", j); 2847 1.142 gson uaudio_dump_tml(iot[i].inputs[j]); 2848 1.82 kent } 2849 1.118 dyoung printf("\toutput: "); 2850 1.142 gson uaudio_dump_tml(iot[i].output); 2851 1.82 kent } 2852 1.82 kent #endif 2853 1.82 kent 2854 1.175 mlelstv sc->sc_nratectls = 0; 2855 1.1 augustss for (i = 0; i < ndps; i++) { 2856 1.82 kent dp = iot[i].d.desc; 2857 1.14 augustss if (dp == NULL) 2858 1.1 augustss continue; 2859 1.122 mrg DPRINTF("id=%d subtype=%d\n", i, dp->bDescriptorSubtype); 2860 1.1 augustss switch (dp->bDescriptorSubtype) { 2861 1.1 augustss case UDESCSUB_AC_HEADER: 2862 1.113 cube aprint_error("uaudio_identify_ac: unexpected AC header\n"); 2863 1.1 augustss break; 2864 1.1 augustss case UDESCSUB_AC_INPUT: 2865 1.82 kent uaudio_add_input(sc, iot, i); 2866 1.1 augustss break; 2867 1.1 augustss case UDESCSUB_AC_OUTPUT: 2868 1.82 kent uaudio_add_output(sc, iot, i); 2869 1.1 augustss break; 2870 1.1 augustss case UDESCSUB_AC_MIXER: 2871 1.82 kent uaudio_add_mixer(sc, iot, i); 2872 1.1 augustss break; 2873 1.1 augustss case UDESCSUB_AC_SELECTOR: 2874 1.82 kent uaudio_add_selector(sc, iot, i); 2875 1.1 augustss break; 2876 1.1 augustss case UDESCSUB_AC_FEATURE: 2877 1.82 kent uaudio_add_feature(sc, iot, i); 2878 1.1 augustss break; 2879 1.175 mlelstv case UDESCSUB_AC_EFFECT: 2880 1.175 mlelstv uaudio_add_effect(sc, iot, i); 2881 1.175 mlelstv break; 2882 1.1 augustss case UDESCSUB_AC_PROCESSING: 2883 1.82 kent uaudio_add_processing(sc, iot, i); 2884 1.1 augustss break; 2885 1.1 augustss case UDESCSUB_AC_EXTENSION: 2886 1.82 kent uaudio_add_extension(sc, iot, i); 2887 1.1 augustss break; 2888 1.175 mlelstv case UDESCSUB_AC_CLKSRC: 2889 1.175 mlelstv uaudio_add_clksrc(sc, iot, i); 2890 1.175 mlelstv /* record ids of clock sources */ 2891 1.175 mlelstv if (sc->sc_nratectls < AUFMT_MAX_FREQUENCIES) 2892 1.175 mlelstv sc->sc_ratectls[sc->sc_nratectls++] = sc->sc_nctls - 1; 2893 1.175 mlelstv break; 2894 1.175 mlelstv case UDESCSUB_AC_CLKSEL: 2895 1.175 mlelstv uaudio_add_clksel(sc, iot, i); 2896 1.175 mlelstv break; 2897 1.175 mlelstv case UDESCSUB_AC_CLKMULT: 2898 1.175 mlelstv /* not yet */ 2899 1.175 mlelstv break; 2900 1.175 mlelstv case UDESCSUB_AC_RATECONV: 2901 1.175 mlelstv /* not yet */ 2902 1.175 mlelstv break; 2903 1.1 augustss default: 2904 1.113 cube aprint_error( 2905 1.165 christos "uaudio_identify_ac: bad AC desc subtype=0x%02x\n", 2906 1.113 cube dp->bDescriptorSubtype); 2907 1.1 augustss break; 2908 1.1 augustss } 2909 1.1 augustss } 2910 1.82 kent 2911 1.178 mlelstv switch (sc->sc_version) { 2912 1.178 mlelstv case UAUDIO_VERSION2: 2913 1.178 mlelstv /* 2914 1.178 mlelstv * UAC2 has separate rate controls which effectively creates 2915 1.178 mlelstv * a set of audio_formats per input and output and their 2916 1.178 mlelstv * associated clock sources. 2917 1.178 mlelstv * 2918 1.178 mlelstv * audio(4) can only handle audio_formats per direction. 2919 1.178 mlelstv * - ignore stream terminals 2920 1.178 mlelstv * - mark rates for record or play if associated with an input 2921 1.178 mlelstv * or output terminal respectively. 2922 1.178 mlelstv */ 2923 1.178 mlelstv for (j = 0; j < sc->sc_nratectls; ++j) { 2924 1.178 mlelstv uint16_t wi = sc->sc_ctls[sc->sc_ratectls[j]].wIndex; 2925 1.178 mlelstv sc->sc_ratemode[j] = 0; 2926 1.178 mlelstv for (i = 0; i < ndps; i++) { 2927 1.178 mlelstv dp = iot[i].d.desc; 2928 1.178 mlelstv if (dp == NULL) 2929 1.178 mlelstv continue; 2930 1.178 mlelstv switch (dp->bDescriptorSubtype) { 2931 1.178 mlelstv case UDESCSUB_AC_INPUT: 2932 1.178 mlelstv if (UGETW(iot[i].d.it->v2.wTerminalType) != UAT_STREAM && 2933 1.179 mlelstv wi == MAKE(iot[i].d.it->v2.bCSourceId, sc->sc_ac_iface)) { 2934 1.178 mlelstv sc->sc_ratemode[j] |= AUMODE_RECORD; 2935 1.179 mlelstv } 2936 1.178 mlelstv break; 2937 1.178 mlelstv case UDESCSUB_AC_OUTPUT: 2938 1.178 mlelstv if (UGETW(iot[i].d.it->v2.wTerminalType) != UAT_STREAM && 2939 1.179 mlelstv wi == MAKE(iot[i].d.ot->v2.bCSourceId, sc->sc_ac_iface)) { 2940 1.178 mlelstv sc->sc_ratemode[j] |= AUMODE_PLAY; 2941 1.179 mlelstv } 2942 1.178 mlelstv break; 2943 1.178 mlelstv } 2944 1.178 mlelstv } 2945 1.178 mlelstv } 2946 1.178 mlelstv break; 2947 1.178 mlelstv } 2948 1.178 mlelstv 2949 1.82 kent /* delete io_terminal */ 2950 1.82 kent for (i = 0; i < 256; i++) { 2951 1.82 kent if (iot[i].d.desc == NULL) 2952 1.82 kent continue; 2953 1.82 kent if (iot[i].inputs != NULL) { 2954 1.82 kent for (j = 0; j < iot[i].inputs_size; j++) { 2955 1.82 kent if (iot[i].inputs[j] != NULL) 2956 1.82 kent free(iot[i].inputs[j], M_TEMP); 2957 1.82 kent } 2958 1.82 kent free(iot[i].inputs, M_TEMP); 2959 1.82 kent } 2960 1.82 kent if (iot[i].output != NULL) 2961 1.82 kent free(iot[i].output, M_TEMP); 2962 1.82 kent iot[i].d.desc = NULL; 2963 1.82 kent } 2964 1.82 kent free(iot, M_TEMP); 2965 1.82 kent 2966 1.94 kent return USBD_NORMAL_COMPLETION; 2967 1.1 augustss } 2968 1.1 augustss 2969 1.86 kent Static int 2970 1.26 augustss uaudio_query_devinfo(void *addr, mixer_devinfo_t *mi) 2971 1.1 augustss { 2972 1.94 kent struct uaudio_softc *sc; 2973 1.1 augustss struct mixerctl *mc; 2974 1.79 kent int n, nctls, i; 2975 1.1 augustss 2976 1.133 mrg DPRINTFN(7, "index=%d\n", mi->index); 2977 1.94 kent sc = addr; 2978 1.1 augustss if (sc->sc_dying) 2979 1.94 kent return EIO; 2980 1.56 kent 2981 1.1 augustss n = mi->index; 2982 1.1 augustss nctls = sc->sc_nctls; 2983 1.1 augustss 2984 1.63 augustss switch (n) { 2985 1.63 augustss case UAC_OUTPUT: 2986 1.63 augustss mi->type = AUDIO_MIXER_CLASS; 2987 1.63 augustss mi->mixer_class = UAC_OUTPUT; 2988 1.63 augustss mi->next = mi->prev = AUDIO_MIXER_LAST; 2989 1.71 itojun strlcpy(mi->label.name, AudioCoutputs, sizeof(mi->label.name)); 2990 1.94 kent return 0; 2991 1.63 augustss case UAC_INPUT: 2992 1.63 augustss mi->type = AUDIO_MIXER_CLASS; 2993 1.63 augustss mi->mixer_class = UAC_INPUT; 2994 1.63 augustss mi->next = mi->prev = AUDIO_MIXER_LAST; 2995 1.71 itojun strlcpy(mi->label.name, AudioCinputs, sizeof(mi->label.name)); 2996 1.94 kent return 0; 2997 1.63 augustss case UAC_EQUAL: 2998 1.63 augustss mi->type = AUDIO_MIXER_CLASS; 2999 1.63 augustss mi->mixer_class = UAC_EQUAL; 3000 1.63 augustss mi->next = mi->prev = AUDIO_MIXER_LAST; 3001 1.71 itojun strlcpy(mi->label.name, AudioCequalization, 3002 1.71 itojun sizeof(mi->label.name)); 3003 1.94 kent return 0; 3004 1.82 kent case UAC_RECORD: 3005 1.82 kent mi->type = AUDIO_MIXER_CLASS; 3006 1.82 kent mi->mixer_class = UAC_RECORD; 3007 1.82 kent mi->next = mi->prev = AUDIO_MIXER_LAST; 3008 1.82 kent strlcpy(mi->label.name, AudioCrecord, sizeof(mi->label.name)); 3009 1.82 kent return 0; 3010 1.63 augustss default: 3011 1.63 augustss break; 3012 1.1 augustss } 3013 1.63 augustss 3014 1.63 augustss n -= UAC_NCLASSES; 3015 1.63 augustss if (n < 0 || n >= nctls) 3016 1.94 kent return ENXIO; 3017 1.63 augustss 3018 1.1 augustss mc = &sc->sc_ctls[n]; 3019 1.71 itojun strlcpy(mi->label.name, mc->ctlname, sizeof(mi->label.name)); 3020 1.1 augustss mi->mixer_class = mc->class; 3021 1.1 augustss mi->next = mi->prev = AUDIO_MIXER_LAST; /* XXX */ 3022 1.1 augustss switch (mc->type) { 3023 1.1 augustss case MIX_ON_OFF: 3024 1.1 augustss mi->type = AUDIO_MIXER_ENUM; 3025 1.1 augustss mi->un.e.num_mem = 2; 3026 1.71 itojun strlcpy(mi->un.e.member[0].label.name, AudioNoff, 3027 1.71 itojun sizeof(mi->un.e.member[0].label.name)); 3028 1.1 augustss mi->un.e.member[0].ord = 0; 3029 1.71 itojun strlcpy(mi->un.e.member[1].label.name, AudioNon, 3030 1.71 itojun sizeof(mi->un.e.member[1].label.name)); 3031 1.1 augustss mi->un.e.member[1].ord = 1; 3032 1.1 augustss break; 3033 1.79 kent case MIX_SELECTOR: 3034 1.175 mlelstv n = uimin(mc->ranges[0].maxval - mc->ranges[0].minval + 1, 3035 1.175 mlelstv __arraycount(mi->un.e.member)); 3036 1.79 kent mi->type = AUDIO_MIXER_ENUM; 3037 1.175 mlelstv mi->un.e.num_mem = n; 3038 1.175 mlelstv for (i = 0; i < n; i++) { 3039 1.79 kent snprintf(mi->un.e.member[i].label.name, 3040 1.79 kent sizeof(mi->un.e.member[i].label.name), 3041 1.175 mlelstv "%d", i + mc->ranges[0].minval); 3042 1.175 mlelstv mi->un.e.member[i].ord = i + mc->ranges[0].minval; 3043 1.79 kent } 3044 1.79 kent break; 3045 1.1 augustss default: 3046 1.1 augustss mi->type = AUDIO_MIXER_VALUE; 3047 1.1 augustss strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN); 3048 1.1 augustss mi->un.v.num_channels = mc->nchan; 3049 1.33 augustss mi->un.v.delta = mc->delta; 3050 1.1 augustss break; 3051 1.1 augustss } 3052 1.94 kent return 0; 3053 1.1 augustss } 3054 1.1 augustss 3055 1.86 kent Static int 3056 1.26 augustss uaudio_open(void *addr, int flags) 3057 1.1 augustss { 3058 1.94 kent struct uaudio_softc *sc; 3059 1.1 augustss 3060 1.95 dsainty sc = addr; 3061 1.122 mrg DPRINTF("sc=%p\n", sc); 3062 1.1 augustss if (sc->sc_dying) 3063 1.94 kent return EIO; 3064 1.1 augustss 3065 1.77 mycroft if ((flags & FWRITE) && !(sc->sc_mode & AUMODE_PLAY)) 3066 1.94 kent return EACCES; 3067 1.77 mycroft if ((flags & FREAD) && !(sc->sc_mode & AUMODE_RECORD)) 3068 1.94 kent return EACCES; 3069 1.1 augustss 3070 1.94 kent return 0; 3071 1.1 augustss } 3072 1.1 augustss 3073 1.86 kent Static int 3074 1.26 augustss uaudio_halt_out_dma(void *addr) 3075 1.1 augustss { 3076 1.121 jmcneill struct uaudio_softc *sc = addr; 3077 1.1 augustss 3078 1.122 mrg DPRINTF("%s", "enter\n"); 3079 1.121 jmcneill 3080 1.146 skrll mutex_exit(&sc->sc_intr_lock); 3081 1.166 jdc uaudio_halt_out_dma_unlocked(sc); 3082 1.166 jdc mutex_enter(&sc->sc_intr_lock); 3083 1.166 jdc 3084 1.166 jdc return 0; 3085 1.166 jdc } 3086 1.166 jdc 3087 1.166 jdc Static void 3088 1.166 jdc uaudio_halt_out_dma_unlocked(struct uaudio_softc *sc) 3089 1.166 jdc { 3090 1.47 jdolecek if (sc->sc_playchan.pipe != NULL) { 3091 1.146 skrll uaudio_chan_abort(sc, &sc->sc_playchan); 3092 1.146 skrll uaudio_chan_free_buffers(sc, &sc->sc_playchan); 3093 1.47 jdolecek uaudio_chan_close(sc, &sc->sc_playchan); 3094 1.74 mycroft sc->sc_playchan.intr = NULL; 3095 1.1 augustss } 3096 1.1 augustss } 3097 1.1 augustss 3098 1.86 kent Static int 3099 1.26 augustss uaudio_halt_in_dma(void *addr) 3100 1.1 augustss { 3101 1.121 jmcneill struct uaudio_softc *sc = addr; 3102 1.1 augustss 3103 1.122 mrg DPRINTF("%s", "enter\n"); 3104 1.121 jmcneill 3105 1.146 skrll mutex_exit(&sc->sc_intr_lock); 3106 1.166 jdc uaudio_halt_in_dma_unlocked(sc); 3107 1.166 jdc mutex_enter(&sc->sc_intr_lock); 3108 1.166 jdc 3109 1.166 jdc return 0; 3110 1.166 jdc } 3111 1.166 jdc 3112 1.166 jdc Static void 3113 1.166 jdc uaudio_halt_in_dma_unlocked(struct uaudio_softc *sc) 3114 1.166 jdc { 3115 1.47 jdolecek if (sc->sc_recchan.pipe != NULL) { 3116 1.146 skrll uaudio_chan_abort(sc, &sc->sc_recchan); 3117 1.146 skrll uaudio_chan_free_buffers(sc, &sc->sc_recchan); 3118 1.47 jdolecek uaudio_chan_close(sc, &sc->sc_recchan); 3119 1.74 mycroft sc->sc_recchan.intr = NULL; 3120 1.5 augustss } 3121 1.1 augustss } 3122 1.1 augustss 3123 1.86 kent Static int 3124 1.26 augustss uaudio_getdev(void *addr, struct audio_device *retp) 3125 1.1 augustss { 3126 1.94 kent struct uaudio_softc *sc; 3127 1.1 augustss 3128 1.122 mrg DPRINTF("%s", "\n"); 3129 1.94 kent sc = addr; 3130 1.1 augustss if (sc->sc_dying) 3131 1.94 kent return EIO; 3132 1.56 kent 3133 1.119 jmcneill *retp = sc->sc_adev; 3134 1.94 kent return 0; 3135 1.1 augustss } 3136 1.1 augustss 3137 1.1 augustss /* 3138 1.1 augustss * Make sure the block size is large enough to hold all outstanding transfers. 3139 1.1 augustss */ 3140 1.86 kent Static int 3141 1.93 kent uaudio_round_blocksize(void *addr, int blk, 3142 1.93 kent int mode, const audio_params_t *param) 3143 1.1 augustss { 3144 1.94 kent struct uaudio_softc *sc; 3145 1.184 mlelstv struct chan *ch; 3146 1.96 kent int b; 3147 1.1 augustss 3148 1.94 kent sc = addr; 3149 1.122 mrg DPRINTF("blk=%d mode=%s\n", blk, 3150 1.122 mrg mode == AUMODE_PLAY ? "AUMODE_PLAY" : "AUMODE_RECORD"); 3151 1.96 kent 3152 1.184 mlelstv ch = mode == AUMODE_PLAY ? &sc->sc_playchan : &sc->sc_recchan; 3153 1.184 mlelstv 3154 1.96 kent /* chan.bytes_per_frame can be 0. */ 3155 1.184 mlelstv if (mode == AUMODE_PLAY || ch->bytes_per_frame <= 0) { 3156 1.184 mlelstv b = param->sample_rate * ch->nframes * ch->nchanbufs; 3157 1.96 kent 3158 1.96 kent /* 3159 1.96 kent * This does not make accurate value in the case 3160 1.179 mlelstv * of b % usb_frames_per_second != 0 3161 1.96 kent */ 3162 1.179 mlelstv b /= sc->sc_usb_frames_per_second; 3163 1.96 kent 3164 1.96 kent b *= param->precision / 8 * param->channels; 3165 1.47 jdolecek } else { 3166 1.96 kent /* 3167 1.96 kent * use wMaxPacketSize in bytes_per_frame. 3168 1.160 isaki * See uaudio_set_format() and uaudio_chan_init() 3169 1.96 kent */ 3170 1.184 mlelstv b = ch->bytes_per_frame * ch->nframes * ch->nchanbufs; 3171 1.47 jdolecek } 3172 1.1 augustss 3173 1.96 kent if (b <= 0) 3174 1.96 kent b = 1; 3175 1.96 kent blk = blk <= b ? b : blk / b * b; 3176 1.1 augustss 3177 1.5 augustss #ifdef DIAGNOSTIC 3178 1.5 augustss if (blk <= 0) { 3179 1.113 cube aprint_debug("uaudio_round_blocksize: blk=%d\n", blk); 3180 1.5 augustss blk = 512; 3181 1.5 augustss } 3182 1.5 augustss #endif 3183 1.5 augustss 3184 1.122 mrg DPRINTF("resultant blk=%d\n", blk); 3185 1.94 kent return blk; 3186 1.1 augustss } 3187 1.1 augustss 3188 1.86 kent Static int 3189 1.107 christos uaudio_get_props(void *addr) 3190 1.1 augustss { 3191 1.161 isaki struct uaudio_softc *sc; 3192 1.161 isaki int props; 3193 1.161 isaki 3194 1.161 isaki sc = addr; 3195 1.161 isaki props = 0; 3196 1.161 isaki if ((sc->sc_mode & AUMODE_PLAY)) 3197 1.161 isaki props |= AUDIO_PROP_PLAYBACK; 3198 1.161 isaki if ((sc->sc_mode & AUMODE_RECORD)) 3199 1.161 isaki props |= AUDIO_PROP_CAPTURE; 3200 1.161 isaki 3201 1.161 isaki /* XXX I'm not sure all bidirectional devices support FULLDUP&INDEP */ 3202 1.161 isaki if (props == (AUDIO_PROP_PLAYBACK | AUDIO_PROP_CAPTURE)) 3203 1.161 isaki props |= AUDIO_PROP_FULLDUPLEX | AUDIO_PROP_INDEPENDENT; 3204 1.1 augustss 3205 1.161 isaki return props; 3206 1.1 augustss } 3207 1.1 augustss 3208 1.121 jmcneill Static void 3209 1.121 jmcneill uaudio_get_locks(void *addr, kmutex_t **intr, kmutex_t **thread) 3210 1.121 jmcneill { 3211 1.121 jmcneill struct uaudio_softc *sc; 3212 1.121 jmcneill 3213 1.121 jmcneill sc = addr; 3214 1.121 jmcneill *intr = &sc->sc_intr_lock; 3215 1.121 jmcneill *thread = &sc->sc_lock; 3216 1.121 jmcneill } 3217 1.121 jmcneill 3218 1.86 kent Static int 3219 1.27 augustss uaudio_get(struct uaudio_softc *sc, int which, int type, int wValue, 3220 1.26 augustss int wIndex, int len) 3221 1.1 augustss { 3222 1.1 augustss usb_device_request_t req; 3223 1.146 skrll uint8_t data[4]; 3224 1.9 augustss usbd_status err; 3225 1.1 augustss int val; 3226 1.1 augustss 3227 1.1 augustss if (wValue == -1) 3228 1.94 kent return 0; 3229 1.1 augustss 3230 1.1 augustss req.bmRequestType = type; 3231 1.1 augustss req.bRequest = which; 3232 1.1 augustss USETW(req.wValue, wValue); 3233 1.1 augustss USETW(req.wIndex, wIndex); 3234 1.1 augustss USETW(req.wLength, len); 3235 1.165 christos DPRINTFN(2,"type=0x%02x req=0x%02x wValue=0x%04x " 3236 1.165 christos "wIndex=0x%04x len=%d\n", 3237 1.122 mrg type, which, wValue, wIndex, len); 3238 1.47 jdolecek err = usbd_do_request(sc->sc_udev, &req, data); 3239 1.9 augustss if (err) { 3240 1.122 mrg DPRINTF("err=%s\n", usbd_errstr(err)); 3241 1.94 kent return -1; 3242 1.1 augustss } 3243 1.1 augustss switch (len) { 3244 1.1 augustss case 1: 3245 1.1 augustss val = data[0]; 3246 1.1 augustss break; 3247 1.1 augustss case 2: 3248 1.175 mlelstv val = data[0]; 3249 1.175 mlelstv val |= data[1] << 8; 3250 1.175 mlelstv break; 3251 1.175 mlelstv case 3: 3252 1.175 mlelstv val = data[0]; 3253 1.175 mlelstv val |= data[1] << 8; 3254 1.175 mlelstv val |= data[2] << 16; 3255 1.175 mlelstv break; 3256 1.175 mlelstv case 4: 3257 1.175 mlelstv val = data[0]; 3258 1.175 mlelstv val |= data[1] << 8; 3259 1.175 mlelstv val |= data[2] << 16; 3260 1.175 mlelstv val |= data[3] << 24; 3261 1.1 augustss break; 3262 1.1 augustss default: 3263 1.122 mrg DPRINTF("bad length=%d\n", len); 3264 1.94 kent return -1; 3265 1.1 augustss } 3266 1.122 mrg DPRINTFN(2,"val=%d\n", val); 3267 1.94 kent return val; 3268 1.1 augustss } 3269 1.1 augustss 3270 1.175 mlelstv Static int 3271 1.175 mlelstv uaudio_getbuf(struct uaudio_softc *sc, int which, int type, int wValue, 3272 1.175 mlelstv int wIndex, int len, uint8_t *data) 3273 1.175 mlelstv { 3274 1.175 mlelstv usb_device_request_t req; 3275 1.175 mlelstv usbd_status err; 3276 1.175 mlelstv 3277 1.175 mlelstv req.bmRequestType = type; 3278 1.175 mlelstv req.bRequest = which; 3279 1.175 mlelstv USETW(req.wValue, wValue); 3280 1.175 mlelstv USETW(req.wIndex, wIndex); 3281 1.175 mlelstv USETW(req.wLength, len); 3282 1.175 mlelstv DPRINTFN(2,"type=0x%02x req=0x%02x wValue=0x%04x " 3283 1.175 mlelstv "wIndex=0x%04x len=%d\n", 3284 1.175 mlelstv type, which, wValue, wIndex, len); 3285 1.175 mlelstv err = usbd_do_request(sc->sc_udev, &req, data); 3286 1.175 mlelstv if (err) { 3287 1.175 mlelstv DPRINTF("err=%s\n", usbd_errstr(err)); 3288 1.175 mlelstv return -1; 3289 1.175 mlelstv } 3290 1.175 mlelstv 3291 1.175 mlelstv DPRINTFN(2,"val@%p\n", data); 3292 1.175 mlelstv return 0; 3293 1.175 mlelstv } 3294 1.175 mlelstv 3295 1.86 kent Static void 3296 1.27 augustss uaudio_set(struct uaudio_softc *sc, int which, int type, int wValue, 3297 1.26 augustss int wIndex, int len, int val) 3298 1.1 augustss { 3299 1.1 augustss usb_device_request_t req; 3300 1.146 skrll uint8_t data[4]; 3301 1.138 martin int err __unused; 3302 1.1 augustss 3303 1.1 augustss if (wValue == -1) 3304 1.1 augustss return; 3305 1.1 augustss 3306 1.1 augustss req.bmRequestType = type; 3307 1.1 augustss req.bRequest = which; 3308 1.1 augustss USETW(req.wValue, wValue); 3309 1.1 augustss USETW(req.wIndex, wIndex); 3310 1.1 augustss USETW(req.wLength, len); 3311 1.175 mlelstv 3312 1.175 mlelstv data[0] = val; 3313 1.175 mlelstv data[1] = val >> 8; 3314 1.175 mlelstv data[2] = val >> 16; 3315 1.175 mlelstv data[3] = val >> 24; 3316 1.175 mlelstv 3317 1.165 christos DPRINTFN(2,"type=0x%02x req=0x%02x wValue=0x%04x " 3318 1.165 christos "wIndex=0x%04x len=%d, val=%d\n", 3319 1.175 mlelstv type, which, wValue, wIndex, len, val); 3320 1.47 jdolecek err = usbd_do_request(sc->sc_udev, &req, data); 3321 1.4 augustss #ifdef UAUDIO_DEBUG 3322 1.12 augustss if (err) 3323 1.179 mlelstv DPRINTF("err=%s\n", usbd_errstr(err)); 3324 1.1 augustss #endif 3325 1.1 augustss } 3326 1.1 augustss 3327 1.86 kent Static int 3328 1.26 augustss uaudio_signext(int type, int val) 3329 1.1 augustss { 3330 1.175 mlelstv if (MIX_UNSIGNED(type)) { 3331 1.175 mlelstv switch (MIX_SIZE(type)) { 3332 1.175 mlelstv case 1: 3333 1.175 mlelstv val = (uint8_t)val; 3334 1.175 mlelstv break; 3335 1.175 mlelstv case 2: 3336 1.175 mlelstv val = (uint16_t)val; 3337 1.175 mlelstv break; 3338 1.175 mlelstv case 3: 3339 1.175 mlelstv val = ((uint32_t)val << 8) >> 8; 3340 1.175 mlelstv break; 3341 1.175 mlelstv case 4: 3342 1.175 mlelstv val = (uint32_t)val; 3343 1.175 mlelstv break; 3344 1.175 mlelstv } 3345 1.175 mlelstv } else { 3346 1.175 mlelstv switch (MIX_SIZE(type)) { 3347 1.175 mlelstv case 1: 3348 1.175 mlelstv val = (int8_t)val; 3349 1.175 mlelstv break; 3350 1.175 mlelstv case 2: 3351 1.1 augustss val = (int16_t)val; 3352 1.175 mlelstv break; 3353 1.175 mlelstv case 3: 3354 1.175 mlelstv val = ((int32_t)val << 8) >> 8; 3355 1.175 mlelstv break; 3356 1.175 mlelstv case 4: 3357 1.175 mlelstv val = (int32_t)val; 3358 1.175 mlelstv break; 3359 1.175 mlelstv } 3360 1.1 augustss } 3361 1.94 kent return val; 3362 1.1 augustss } 3363 1.1 augustss 3364 1.86 kent Static int 3365 1.26 augustss uaudio_value2bsd(struct mixerctl *mc, int val) 3366 1.1 augustss { 3367 1.122 mrg DPRINTFN(5, "type=%03x val=%d min=%d max=%d ", 3368 1.175 mlelstv mc->type, val, mc->ranges[0].minval, mc->ranges[0].maxval); 3369 1.79 kent if (mc->type == MIX_ON_OFF) { 3370 1.47 jdolecek val = (val != 0); 3371 1.79 kent } else if (mc->type == MIX_SELECTOR) { 3372 1.179 mlelstv if (val < mc->ranges[0].minval) 3373 1.175 mlelstv val = mc->ranges[0].minval; 3374 1.179 mlelstv if (val > mc->ranges[0].maxval) 3375 1.179 mlelstv val = mc->ranges[0].maxval; 3376 1.179 mlelstv } else if (mc->mul > 0) { 3377 1.179 mlelstv val = ((uaudio_signext(mc->type, val) - mc->ranges[0].minval) 3378 1.179 mlelstv * 255 + mc->mul - 1) / mc->mul; 3379 1.79 kent } else 3380 1.179 mlelstv val = 0; 3381 1.122 mrg DPRINTFN_CLEAN(5, "val'=%d\n", val); 3382 1.94 kent return val; 3383 1.1 augustss } 3384 1.1 augustss 3385 1.175 mlelstv Static int 3386 1.26 augustss uaudio_bsd2value(struct mixerctl *mc, int val) 3387 1.1 augustss { 3388 1.179 mlelstv int i; 3389 1.179 mlelstv 3390 1.122 mrg DPRINTFN(5,"type=%03x val=%d min=%d max=%d ", 3391 1.175 mlelstv mc->type, val, mc->ranges[0].minval, mc->ranges[0].maxval); 3392 1.79 kent if (mc->type == MIX_ON_OFF) { 3393 1.47 jdolecek val = (val != 0); 3394 1.79 kent } else if (mc->type == MIX_SELECTOR) { 3395 1.179 mlelstv if (val < mc->ranges[0].minval) 3396 1.175 mlelstv val = mc->ranges[0].minval; 3397 1.179 mlelstv if (val > mc->ranges[0].maxval) 3398 1.179 mlelstv val = mc->ranges[0].maxval; 3399 1.175 mlelstv } else { 3400 1.175 mlelstv if (val < 0) 3401 1.175 mlelstv val = 0; 3402 1.179 mlelstv else if (val > 255) 3403 1.179 mlelstv val = 255; 3404 1.175 mlelstv 3405 1.179 mlelstv val = val * (mc->mul + 1) / 256 + mc->ranges[0].minval; 3406 1.175 mlelstv 3407 1.179 mlelstv for (i=0; i<mc->nranges; ++i) { 3408 1.179 mlelstv struct range *r = &mc->ranges[i]; 3409 1.175 mlelstv 3410 1.179 mlelstv if (r->resval == 0) 3411 1.179 mlelstv continue; 3412 1.179 mlelstv if (val > r->maxval) 3413 1.179 mlelstv continue; 3414 1.179 mlelstv if (val < r->minval) 3415 1.179 mlelstv val = r->minval; 3416 1.179 mlelstv val = (val - r->minval + r->resval/2) 3417 1.179 mlelstv / r->resval * r->resval 3418 1.179 mlelstv + r->minval; 3419 1.179 mlelstv break; 3420 1.175 mlelstv } 3421 1.175 mlelstv } 3422 1.122 mrg DPRINTFN_CLEAN(5, "val'=%d\n", val); 3423 1.94 kent return val; 3424 1.1 augustss } 3425 1.1 augustss 3426 1.175 mlelstv Static const char * 3427 1.175 mlelstv uaudio_clockname(u_int attr) 3428 1.175 mlelstv { 3429 1.175 mlelstv static const char *names[] = { 3430 1.179 mlelstv "clkext", 3431 1.179 mlelstv "clkfixed", 3432 1.179 mlelstv "clkvar", 3433 1.179 mlelstv "clkprog" 3434 1.175 mlelstv }; 3435 1.175 mlelstv 3436 1.175 mlelstv return names[attr & 3]; 3437 1.175 mlelstv } 3438 1.175 mlelstv 3439 1.175 mlelstv Static int 3440 1.175 mlelstv uaudio_makename(struct uaudio_softc *sc, uByte idx, const char *defname, uByte id, char *buf, size_t len) 3441 1.175 mlelstv { 3442 1.175 mlelstv char *tmp; 3443 1.175 mlelstv int err, count; 3444 1.175 mlelstv 3445 1.175 mlelstv tmp = kmem_alloc(USB_MAX_ENCODED_STRING_LEN, KM_SLEEP); 3446 1.175 mlelstv err = usbd_get_string0(sc->sc_udev, idx, tmp, true); 3447 1.179 mlelstv 3448 1.179 mlelstv if (id != 0 || err) 3449 1.179 mlelstv count = snprintf(buf, len, "%s%d", err ? defname : tmp, id); 3450 1.179 mlelstv else 3451 1.179 mlelstv count = snprintf(buf, len, "%s", err ? defname : tmp); 3452 1.179 mlelstv 3453 1.175 mlelstv kmem_free(tmp, USB_MAX_ENCODED_STRING_LEN); 3454 1.175 mlelstv 3455 1.175 mlelstv return count; 3456 1.175 mlelstv } 3457 1.175 mlelstv 3458 1.175 mlelstv 3459 1.86 kent Static int 3460 1.56 kent uaudio_ctl_get(struct uaudio_softc *sc, int which, struct mixerctl *mc, 3461 1.26 augustss int chan) 3462 1.1 augustss { 3463 1.1 augustss int val; 3464 1.1 augustss 3465 1.179 mlelstv DPRINTFN(5,"which=%d chan=%d ctl=%s type=%d\n", which, chan, mc->ctlname, mc->type); 3466 1.133 mrg mutex_exit(&sc->sc_lock); 3467 1.1 augustss val = uaudio_get(sc, which, UT_READ_CLASS_INTERFACE, mc->wValue[chan], 3468 1.1 augustss mc->wIndex, MIX_SIZE(mc->type)); 3469 1.133 mrg mutex_enter(&sc->sc_lock); 3470 1.94 kent return uaudio_value2bsd(mc, val); 3471 1.1 augustss } 3472 1.1 augustss 3473 1.86 kent Static void 3474 1.26 augustss uaudio_ctl_set(struct uaudio_softc *sc, int which, struct mixerctl *mc, 3475 1.26 augustss int chan, int val) 3476 1.1 augustss { 3477 1.124 mrg 3478 1.179 mlelstv DPRINTFN(5,"which=%d chan=%d ctl=%s type=%d\n", which, chan, mc->ctlname, mc->type); 3479 1.1 augustss val = uaudio_bsd2value(mc, val); 3480 1.133 mrg mutex_exit(&sc->sc_lock); 3481 1.1 augustss uaudio_set(sc, which, UT_WRITE_CLASS_INTERFACE, mc->wValue[chan], 3482 1.1 augustss mc->wIndex, MIX_SIZE(mc->type), val); 3483 1.133 mrg mutex_enter(&sc->sc_lock); 3484 1.1 augustss } 3485 1.1 augustss 3486 1.86 kent Static int 3487 1.26 augustss uaudio_mixer_get_port(void *addr, mixer_ctrl_t *cp) 3488 1.1 augustss { 3489 1.94 kent struct uaudio_softc *sc; 3490 1.1 augustss struct mixerctl *mc; 3491 1.1 augustss int i, n, vals[MIX_MAX_CHAN], val; 3492 1.179 mlelstv int req; 3493 1.1 augustss 3494 1.122 mrg DPRINTFN(2, "index=%d\n", cp->dev); 3495 1.94 kent sc = addr; 3496 1.1 augustss if (sc->sc_dying) 3497 1.94 kent return EIO; 3498 1.56 kent 3499 1.179 mlelstv req = sc->sc_version == UAUDIO_VERSION2 ? V2_CUR : GET_CUR; 3500 1.179 mlelstv 3501 1.63 augustss n = cp->dev - UAC_NCLASSES; 3502 1.1 augustss if (n < 0 || n >= sc->sc_nctls) 3503 1.94 kent return ENXIO; 3504 1.1 augustss mc = &sc->sc_ctls[n]; 3505 1.1 augustss 3506 1.1 augustss if (mc->type == MIX_ON_OFF) { 3507 1.1 augustss if (cp->type != AUDIO_MIXER_ENUM) 3508 1.94 kent return EINVAL; 3509 1.179 mlelstv cp->un.ord = uaudio_ctl_get(sc, req, mc, 0); 3510 1.79 kent } else if (mc->type == MIX_SELECTOR) { 3511 1.79 kent if (cp->type != AUDIO_MIXER_ENUM) 3512 1.94 kent return EINVAL; 3513 1.179 mlelstv cp->un.ord = uaudio_ctl_get(sc, req, mc, 0); 3514 1.1 augustss } else { 3515 1.1 augustss if (cp->type != AUDIO_MIXER_VALUE) 3516 1.94 kent return EINVAL; 3517 1.1 augustss if (cp->un.value.num_channels != 1 && 3518 1.1 augustss cp->un.value.num_channels != mc->nchan) 3519 1.94 kent return EINVAL; 3520 1.1 augustss for (i = 0; i < mc->nchan; i++) 3521 1.179 mlelstv vals[i] = uaudio_ctl_get(sc, req, mc, i); 3522 1.1 augustss if (cp->un.value.num_channels == 1 && mc->nchan != 1) { 3523 1.1 augustss for (val = 0, i = 0; i < mc->nchan; i++) 3524 1.1 augustss val += vals[i]; 3525 1.1 augustss vals[0] = val / mc->nchan; 3526 1.1 augustss } 3527 1.1 augustss for (i = 0; i < cp->un.value.num_channels; i++) 3528 1.1 augustss cp->un.value.level[i] = vals[i]; 3529 1.1 augustss } 3530 1.1 augustss 3531 1.94 kent return 0; 3532 1.1 augustss } 3533 1.56 kent 3534 1.86 kent Static int 3535 1.26 augustss uaudio_mixer_set_port(void *addr, mixer_ctrl_t *cp) 3536 1.1 augustss { 3537 1.94 kent struct uaudio_softc *sc; 3538 1.1 augustss struct mixerctl *mc; 3539 1.1 augustss int i, n, vals[MIX_MAX_CHAN]; 3540 1.179 mlelstv int req; 3541 1.1 augustss 3542 1.122 mrg DPRINTFN(2, "index = %d\n", cp->dev); 3543 1.94 kent sc = addr; 3544 1.1 augustss if (sc->sc_dying) 3545 1.94 kent return EIO; 3546 1.56 kent 3547 1.179 mlelstv req = sc->sc_version == UAUDIO_VERSION2 ? V2_CUR : SET_CUR; 3548 1.179 mlelstv 3549 1.63 augustss n = cp->dev - UAC_NCLASSES; 3550 1.1 augustss if (n < 0 || n >= sc->sc_nctls) 3551 1.94 kent return ENXIO; 3552 1.1 augustss mc = &sc->sc_ctls[n]; 3553 1.1 augustss 3554 1.1 augustss if (mc->type == MIX_ON_OFF) { 3555 1.1 augustss if (cp->type != AUDIO_MIXER_ENUM) 3556 1.94 kent return EINVAL; 3557 1.179 mlelstv uaudio_ctl_set(sc, req, mc, 0, cp->un.ord); 3558 1.79 kent } else if (mc->type == MIX_SELECTOR) { 3559 1.79 kent if (cp->type != AUDIO_MIXER_ENUM) 3560 1.94 kent return EINVAL; 3561 1.179 mlelstv uaudio_ctl_set(sc, req, mc, 0, cp->un.ord); 3562 1.1 augustss } else { 3563 1.1 augustss if (cp->type != AUDIO_MIXER_VALUE) 3564 1.94 kent return EINVAL; 3565 1.1 augustss if (cp->un.value.num_channels == 1) 3566 1.1 augustss for (i = 0; i < mc->nchan; i++) 3567 1.1 augustss vals[i] = cp->un.value.level[0]; 3568 1.1 augustss else if (cp->un.value.num_channels == mc->nchan) 3569 1.1 augustss for (i = 0; i < mc->nchan; i++) 3570 1.1 augustss vals[i] = cp->un.value.level[i]; 3571 1.1 augustss else 3572 1.94 kent return EINVAL; 3573 1.1 augustss for (i = 0; i < mc->nchan; i++) 3574 1.179 mlelstv uaudio_ctl_set(sc, req, mc, i, vals[i]); 3575 1.1 augustss } 3576 1.94 kent return 0; 3577 1.1 augustss } 3578 1.1 augustss 3579 1.86 kent Static int 3580 1.26 augustss uaudio_trigger_input(void *addr, void *start, void *end, int blksize, 3581 1.26 augustss void (*intr)(void *), void *arg, 3582 1.107 christos const audio_params_t *param) 3583 1.1 augustss { 3584 1.94 kent struct uaudio_softc *sc; 3585 1.94 kent struct chan *ch; 3586 1.9 augustss usbd_status err; 3587 1.133 mrg int i; 3588 1.1 augustss 3589 1.94 kent sc = addr; 3590 1.1 augustss if (sc->sc_dying) 3591 1.94 kent return EIO; 3592 1.1 augustss 3593 1.173 mlelstv mutex_exit(&sc->sc_intr_lock); 3594 1.173 mlelstv 3595 1.122 mrg DPRINTFN(3, "sc=%p start=%p end=%p " 3596 1.122 mrg "blksize=%d\n", sc, start, end, blksize); 3597 1.94 kent ch = &sc->sc_recchan; 3598 1.54 kent uaudio_chan_set_param(ch, start, end, blksize); 3599 1.122 mrg DPRINTFN(3, "sample_size=%d bytes/frame=%d " 3600 1.5 augustss "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, 3601 1.122 mrg ch->fraction); 3602 1.5 augustss 3603 1.146 skrll err = uaudio_chan_open(sc, ch); 3604 1.121 jmcneill if (err) { 3605 1.173 mlelstv mutex_enter(&sc->sc_intr_lock); 3606 1.173 mlelstv device_printf(sc->sc_dev,"%s open channel err=%s\n",__func__, usbd_errstr(err)); 3607 1.94 kent return EIO; 3608 1.121 jmcneill } 3609 1.5 augustss 3610 1.146 skrll err = uaudio_chan_alloc_buffers(sc, ch); 3611 1.9 augustss if (err) { 3612 1.146 skrll uaudio_chan_close(sc, ch); 3613 1.173 mlelstv device_printf(sc->sc_dev,"%s alloc buffers err=%s\n",__func__, usbd_errstr(err)); 3614 1.173 mlelstv mutex_enter(&sc->sc_intr_lock); 3615 1.94 kent return EIO; 3616 1.5 augustss } 3617 1.5 augustss 3618 1.146 skrll 3619 1.47 jdolecek ch->intr = intr; 3620 1.47 jdolecek ch->arg = arg; 3621 1.5 augustss 3622 1.154 nat /* 3623 1.154 nat * Start as half as many channels for recording as for playback. 3624 1.154 nat * This stops playback from stuttering in full-duplex operation. 3625 1.154 nat */ 3626 1.179 mlelstv for (i = 0; i < ch->nchanbufs / 2; i++) { 3627 1.5 augustss uaudio_chan_rtransfer(ch); 3628 1.146 skrll } 3629 1.146 skrll 3630 1.173 mlelstv mutex_enter(&sc->sc_intr_lock); 3631 1.173 mlelstv 3632 1.94 kent return 0; 3633 1.1 augustss } 3634 1.56 kent 3635 1.86 kent Static int 3636 1.26 augustss uaudio_trigger_output(void *addr, void *start, void *end, int blksize, 3637 1.26 augustss void (*intr)(void *), void *arg, 3638 1.107 christos const audio_params_t *param) 3639 1.1 augustss { 3640 1.94 kent struct uaudio_softc *sc; 3641 1.94 kent struct chan *ch; 3642 1.9 augustss usbd_status err; 3643 1.133 mrg int i; 3644 1.1 augustss 3645 1.94 kent sc = addr; 3646 1.1 augustss if (sc->sc_dying) 3647 1.94 kent return EIO; 3648 1.1 augustss 3649 1.173 mlelstv mutex_exit(&sc->sc_intr_lock); 3650 1.173 mlelstv 3651 1.122 mrg DPRINTFN(3, "sc=%p start=%p end=%p " 3652 1.122 mrg "blksize=%d\n", sc, start, end, blksize); 3653 1.94 kent ch = &sc->sc_playchan; 3654 1.54 kent uaudio_chan_set_param(ch, start, end, blksize); 3655 1.122 mrg DPRINTFN(3, "sample_size=%d bytes/frame=%d " 3656 1.1 augustss "fraction=0.%03d\n", ch->sample_size, ch->bytes_per_frame, 3657 1.122 mrg ch->fraction); 3658 1.1 augustss 3659 1.146 skrll err = uaudio_chan_open(sc, ch); 3660 1.121 jmcneill if (err) { 3661 1.173 mlelstv mutex_enter(&sc->sc_intr_lock); 3662 1.173 mlelstv device_printf(sc->sc_dev,"%s open channel err=%s\n",__func__, usbd_errstr(err)); 3663 1.94 kent return EIO; 3664 1.121 jmcneill } 3665 1.1 augustss 3666 1.146 skrll err = uaudio_chan_alloc_buffers(sc, ch); 3667 1.9 augustss if (err) { 3668 1.146 skrll uaudio_chan_close(sc, ch); 3669 1.173 mlelstv device_printf(sc->sc_dev,"%s alloc buffers err=%s\n",__func__, usbd_errstr(err)); 3670 1.173 mlelstv mutex_enter(&sc->sc_intr_lock); 3671 1.94 kent return EIO; 3672 1.1 augustss } 3673 1.1 augustss 3674 1.47 jdolecek ch->intr = intr; 3675 1.47 jdolecek ch->arg = arg; 3676 1.1 augustss 3677 1.179 mlelstv for (i = 0; i < ch->nchanbufs; i++) 3678 1.5 augustss uaudio_chan_ptransfer(ch); 3679 1.1 augustss 3680 1.173 mlelstv mutex_enter(&sc->sc_intr_lock); 3681 1.173 mlelstv 3682 1.94 kent return 0; 3683 1.1 augustss } 3684 1.1 augustss 3685 1.1 augustss /* Set up a pipe for a channel. */ 3686 1.86 kent Static usbd_status 3687 1.26 augustss uaudio_chan_open(struct uaudio_softc *sc, struct chan *ch) 3688 1.1 augustss { 3689 1.94 kent struct as_info *as; 3690 1.131 jakllsch usb_device_descriptor_t *ddesc; 3691 1.179 mlelstv int endpt, clkid; 3692 1.9 augustss usbd_status err; 3693 1.1 augustss 3694 1.94 kent as = &sc->sc_alts[ch->altidx]; 3695 1.94 kent endpt = as->edesc->bEndpointAddress; 3696 1.179 mlelstv clkid = sc->sc_clock[as->terminal]; 3697 1.179 mlelstv DPRINTF("endpt=0x%02x, clkid=%d, speed=%d, alt=%d\n", 3698 1.179 mlelstv endpt, clkid, ch->sample_rate, as->alt); 3699 1.1 augustss 3700 1.1 augustss /* Set alternate interface corresponding to the mode. */ 3701 1.37 mycroft err = usbd_set_interface(as->ifaceh, as->alt); 3702 1.9 augustss if (err) 3703 1.94 kent return err; 3704 1.1 augustss 3705 1.90 kent /* 3706 1.90 kent * Roland SD-90 freezes by a SAMPLING_FREQ_CONTROL request. 3707 1.90 kent */ 3708 1.131 jakllsch ddesc = usbd_get_device_descriptor(sc->sc_udev); 3709 1.131 jakllsch if ((UGETW(ddesc->idVendor) != USB_VENDOR_ROLAND) && 3710 1.131 jakllsch (UGETW(ddesc->idProduct) != USB_PRODUCT_ROLAND_SD90)) { 3711 1.179 mlelstv err = uaudio_set_speed(sc, endpt, clkid, ch->sample_rate); 3712 1.105 christos if (err) { 3713 1.122 mrg DPRINTF("set_speed failed err=%s\n", usbd_errstr(err)); 3714 1.105 christos } 3715 1.90 kent } 3716 1.1 augustss 3717 1.165 christos DPRINTF("create pipe to 0x%02x\n", endpt); 3718 1.134 jmcneill err = usbd_open_pipe(as->ifaceh, endpt, USBD_MPSAFE, &ch->pipe); 3719 1.83 kent if (err) 3720 1.83 kent return err; 3721 1.83 kent if (as->edesc1 != NULL) { 3722 1.83 kent endpt = as->edesc1->bEndpointAddress; 3723 1.175 mlelstv if (endpt != 0) { 3724 1.175 mlelstv DPRINTF("create sync-pipe to 0x%02x\n", endpt); 3725 1.175 mlelstv err = usbd_open_pipe(as->ifaceh, endpt, USBD_MPSAFE, 3726 1.175 mlelstv &ch->sync_pipe); 3727 1.175 mlelstv } 3728 1.83 kent } 3729 1.175 mlelstv 3730 1.83 kent return err; 3731 1.1 augustss } 3732 1.1 augustss 3733 1.86 kent Static void 3734 1.146 skrll uaudio_chan_abort(struct uaudio_softc *sc, struct chan *ch) 3735 1.1 augustss { 3736 1.146 skrll struct usbd_pipe *pipe; 3737 1.94 kent struct as_info *as; 3738 1.37 mycroft 3739 1.94 kent as = &sc->sc_alts[ch->altidx]; 3740 1.58 kent as->sc_busy = 0; 3741 1.1 augustss if (sc->sc_nullalt >= 0) { 3742 1.122 mrg DPRINTF("set null alt=%d\n", sc->sc_nullalt); 3743 1.37 mycroft usbd_set_interface(as->ifaceh, sc->sc_nullalt); 3744 1.1 augustss } 3745 1.146 skrll pipe = ch->pipe; 3746 1.146 skrll if (pipe) { 3747 1.146 skrll usbd_abort_pipe(pipe); 3748 1.146 skrll } 3749 1.146 skrll pipe = ch->sync_pipe; 3750 1.146 skrll if (pipe) { 3751 1.146 skrll usbd_abort_pipe(pipe); 3752 1.146 skrll } 3753 1.146 skrll } 3754 1.146 skrll 3755 1.146 skrll Static void 3756 1.146 skrll uaudio_chan_close(struct uaudio_softc *sc, struct chan *ch) 3757 1.146 skrll { 3758 1.146 skrll struct usbd_pipe *pipe; 3759 1.146 skrll 3760 1.136 wiz pipe = atomic_swap_ptr(&ch->pipe, NULL); 3761 1.136 wiz if (pipe) { 3762 1.136 wiz usbd_close_pipe(pipe); 3763 1.136 wiz } 3764 1.136 wiz pipe = atomic_swap_ptr(&ch->sync_pipe, NULL); 3765 1.136 wiz if (pipe) { 3766 1.136 wiz usbd_close_pipe(pipe); 3767 1.83 kent } 3768 1.1 augustss } 3769 1.1 augustss 3770 1.86 kent Static usbd_status 3771 1.26 augustss uaudio_chan_alloc_buffers(struct uaudio_softc *sc, struct chan *ch) 3772 1.1 augustss { 3773 1.1 augustss int i, size; 3774 1.1 augustss 3775 1.179 mlelstv size = (ch->bytes_per_frame + ch->sample_size) * ch->nframes; 3776 1.179 mlelstv for (i = 0; i < ch->nchanbufs; i++) { 3777 1.146 skrll struct usbd_xfer *xfer; 3778 1.146 skrll 3779 1.179 mlelstv int err = usbd_create_xfer(ch->pipe, size, 0, ch->nframes, 3780 1.146 skrll &xfer); 3781 1.146 skrll if (err) 3782 1.1 augustss goto bad; 3783 1.146 skrll 3784 1.9 augustss ch->chanbufs[i].xfer = xfer; 3785 1.146 skrll ch->chanbufs[i].buffer = usbd_get_buffer(xfer); 3786 1.1 augustss ch->chanbufs[i].chan = ch; 3787 1.1 augustss } 3788 1.1 augustss 3789 1.94 kent return USBD_NORMAL_COMPLETION; 3790 1.1 augustss 3791 1.1 augustss bad: 3792 1.1 augustss while (--i >= 0) 3793 1.1 augustss /* implicit buffer free */ 3794 1.146 skrll usbd_destroy_xfer(ch->chanbufs[i].xfer); 3795 1.94 kent return USBD_NOMEM; 3796 1.1 augustss } 3797 1.1 augustss 3798 1.86 kent Static void 3799 1.107 christos uaudio_chan_free_buffers(struct uaudio_softc *sc, struct chan *ch) 3800 1.1 augustss { 3801 1.1 augustss int i; 3802 1.1 augustss 3803 1.179 mlelstv for (i = 0; i < ch->nchanbufs; i++) 3804 1.146 skrll usbd_destroy_xfer(ch->chanbufs[i].xfer); 3805 1.1 augustss } 3806 1.1 augustss 3807 1.86 kent Static void 3808 1.26 augustss uaudio_chan_ptransfer(struct chan *ch) 3809 1.1 augustss { 3810 1.179 mlelstv struct uaudio_softc *sc = ch->sc; 3811 1.1 augustss struct chanbuf *cb; 3812 1.1 augustss int i, n, size, residue, total; 3813 1.1 augustss 3814 1.179 mlelstv if (sc->sc_dying) 3815 1.8 augustss return; 3816 1.8 augustss 3817 1.1 augustss /* Pick the next channel buffer. */ 3818 1.1 augustss cb = &ch->chanbufs[ch->curchanbuf]; 3819 1.179 mlelstv if (++ch->curchanbuf >= ch->nchanbufs) 3820 1.1 augustss ch->curchanbuf = 0; 3821 1.1 augustss 3822 1.1 augustss /* Compute the size of each frame in the next transfer. */ 3823 1.1 augustss residue = ch->residue; 3824 1.1 augustss total = 0; 3825 1.179 mlelstv for (i = 0; i < ch->nframes; i++) { 3826 1.1 augustss size = ch->bytes_per_frame; 3827 1.1 augustss residue += ch->fraction; 3828 1.179 mlelstv if (residue >= sc->sc_usb_frames_per_second) { 3829 1.179 mlelstv if ((sc->sc_altflags & UA_NOFRAC) == 0) 3830 1.31 augustss size += ch->sample_size; 3831 1.179 mlelstv residue -= sc->sc_usb_frames_per_second; 3832 1.1 augustss } 3833 1.1 augustss cb->sizes[i] = size; 3834 1.1 augustss total += size; 3835 1.1 augustss } 3836 1.1 augustss ch->residue = residue; 3837 1.1 augustss cb->size = total; 3838 1.1 augustss 3839 1.56 kent /* 3840 1.1 augustss * Transfer data from upper layer buffer to channel buffer, taking 3841 1.1 augustss * care of wrapping the upper layer buffer. 3842 1.1 augustss */ 3843 1.157 riastrad n = uimin(total, ch->end - ch->cur); 3844 1.1 augustss memcpy(cb->buffer, ch->cur, n); 3845 1.1 augustss ch->cur += n; 3846 1.1 augustss if (ch->cur >= ch->end) 3847 1.1 augustss ch->cur = ch->start; 3848 1.1 augustss if (total > n) { 3849 1.1 augustss total -= n; 3850 1.1 augustss memcpy(cb->buffer + n, ch->cur, total); 3851 1.1 augustss ch->cur += total; 3852 1.1 augustss } 3853 1.1 augustss 3854 1.4 augustss #ifdef UAUDIO_DEBUG 3855 1.1 augustss if (uaudiodebug > 8) { 3856 1.122 mrg DPRINTF("buffer=%p, residue=0.%03d\n", cb->buffer, ch->residue); 3857 1.179 mlelstv for (i = 0; i < ch->nframes; i++) { 3858 1.122 mrg DPRINTF(" [%d] length %d\n", i, cb->sizes[i]); 3859 1.1 augustss } 3860 1.1 augustss } 3861 1.1 augustss #endif 3862 1.1 augustss 3863 1.124 mrg //DPRINTFN(5, "ptransfer xfer=%p\n", cb->xfer); 3864 1.1 augustss /* Fill the request */ 3865 1.179 mlelstv usbd_setup_isoc_xfer(cb->xfer, cb, cb->sizes, ch->nframes, 0, 3866 1.146 skrll uaudio_chan_pintr); 3867 1.1 augustss 3868 1.173 mlelstv usbd_status err = usbd_transfer(cb->xfer); 3869 1.173 mlelstv if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) 3870 1.179 mlelstv device_printf(sc->sc_dev, "ptransfer error %d\n", err); 3871 1.1 augustss } 3872 1.1 augustss 3873 1.86 kent Static void 3874 1.146 skrll uaudio_chan_pintr(struct usbd_xfer *xfer, void *priv, 3875 1.26 augustss usbd_status status) 3876 1.1 augustss { 3877 1.179 mlelstv struct uaudio_softc *sc; 3878 1.94 kent struct chanbuf *cb; 3879 1.94 kent struct chan *ch; 3880 1.94 kent uint32_t count; 3881 1.1 augustss 3882 1.94 kent cb = priv; 3883 1.94 kent ch = cb->chan; 3884 1.179 mlelstv sc = ch->sc; 3885 1.1 augustss /* Return if we are aborting. */ 3886 1.1 augustss if (status == USBD_CANCELLED) 3887 1.1 augustss return; 3888 1.1 augustss 3889 1.173 mlelstv if (status != USBD_NORMAL_COMPLETION) 3890 1.179 mlelstv device_printf(sc->sc_dev, "pintr error: %s\n", 3891 1.173 mlelstv usbd_errstr(status)); 3892 1.173 mlelstv 3893 1.18 augustss usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 3894 1.122 mrg DPRINTFN(5, "count=%d, transferred=%d\n", 3895 1.122 mrg count, ch->transferred); 3896 1.5 augustss #ifdef DIAGNOSTIC 3897 1.5 augustss if (count != cb->size) { 3898 1.179 mlelstv device_printf(sc->sc_dev, 3899 1.171 mlelstv "uaudio_chan_pintr: count(%d) != size(%d), status(%d)\n", 3900 1.171 mlelstv count, cb->size, status); 3901 1.5 augustss } 3902 1.5 augustss #endif 3903 1.5 augustss 3904 1.179 mlelstv mutex_enter(&sc->sc_intr_lock); 3905 1.5 augustss ch->transferred += cb->size; 3906 1.1 augustss /* Call back to upper layer */ 3907 1.5 augustss while (ch->transferred >= ch->blksize) { 3908 1.5 augustss ch->transferred -= ch->blksize; 3909 1.122 mrg DPRINTFN(5, "call %p(%p)\n", ch->intr, ch->arg); 3910 1.5 augustss ch->intr(ch->arg); 3911 1.5 augustss } 3912 1.179 mlelstv mutex_exit(&sc->sc_intr_lock); 3913 1.5 augustss 3914 1.5 augustss /* start next transfer */ 3915 1.5 augustss uaudio_chan_ptransfer(ch); 3916 1.5 augustss } 3917 1.5 augustss 3918 1.86 kent Static void 3919 1.26 augustss uaudio_chan_rtransfer(struct chan *ch) 3920 1.5 augustss { 3921 1.179 mlelstv struct uaudio_softc *sc = ch->sc; 3922 1.5 augustss struct chanbuf *cb; 3923 1.5 augustss int i, size, residue, total; 3924 1.8 augustss 3925 1.179 mlelstv if (sc->sc_dying) 3926 1.8 augustss return; 3927 1.5 augustss 3928 1.5 augustss /* Pick the next channel buffer. */ 3929 1.5 augustss cb = &ch->chanbufs[ch->curchanbuf]; 3930 1.179 mlelstv if (++ch->curchanbuf >= ch->nchanbufs) 3931 1.5 augustss ch->curchanbuf = 0; 3932 1.5 augustss 3933 1.5 augustss /* Compute the size of each frame in the next transfer. */ 3934 1.5 augustss residue = ch->residue; 3935 1.5 augustss total = 0; 3936 1.179 mlelstv for (i = 0; i < ch->nframes; i++) { 3937 1.5 augustss size = ch->bytes_per_frame; 3938 1.179 mlelstv #if 0 3939 1.179 mlelstv residue += ch->fraction; 3940 1.179 mlelstv if (residue >= sc->sc_usb_frames_per_second) { 3941 1.179 mlelstv if ((sc->sc_altflags & UA_NOFRAC) == 0) 3942 1.179 mlelstv size += ch->sample_size; 3943 1.179 mlelstv residue -= sc->sc_usb_frames_per_second; 3944 1.179 mlelstv } 3945 1.179 mlelstv #endif 3946 1.5 augustss cb->sizes[i] = size; 3947 1.62 toshii cb->offsets[i] = total; 3948 1.5 augustss total += size; 3949 1.5 augustss } 3950 1.5 augustss ch->residue = residue; 3951 1.5 augustss cb->size = total; 3952 1.5 augustss 3953 1.5 augustss #ifdef UAUDIO_DEBUG 3954 1.5 augustss if (uaudiodebug > 8) { 3955 1.122 mrg DPRINTF("buffer=%p, residue=0.%03d\n", cb->buffer, ch->residue); 3956 1.179 mlelstv for (i = 0; i < ch->nframes; i++) { 3957 1.122 mrg DPRINTF(" [%d] length %d\n", i, cb->sizes[i]); 3958 1.5 augustss } 3959 1.5 augustss } 3960 1.5 augustss #endif 3961 1.5 augustss 3962 1.122 mrg DPRINTFN(5, "transfer xfer=%p\n", cb->xfer); 3963 1.5 augustss /* Fill the request */ 3964 1.179 mlelstv usbd_setup_isoc_xfer(cb->xfer, cb, cb->sizes, ch->nframes, 0, 3965 1.146 skrll uaudio_chan_rintr); 3966 1.5 augustss 3967 1.173 mlelstv usbd_status err = usbd_transfer(cb->xfer); 3968 1.173 mlelstv if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) 3969 1.179 mlelstv device_printf(sc->sc_dev, "rtransfer error %d\n", err); 3970 1.5 augustss } 3971 1.5 augustss 3972 1.86 kent Static void 3973 1.146 skrll uaudio_chan_rintr(struct usbd_xfer *xfer, void *priv, 3974 1.26 augustss usbd_status status) 3975 1.5 augustss { 3976 1.179 mlelstv struct uaudio_softc *sc; 3977 1.94 kent struct chanbuf *cb; 3978 1.94 kent struct chan *ch; 3979 1.94 kent uint32_t count; 3980 1.121 jmcneill int i, n, frsize; 3981 1.5 augustss 3982 1.94 kent cb = priv; 3983 1.94 kent ch = cb->chan; 3984 1.179 mlelstv sc = ch->sc; 3985 1.5 augustss /* Return if we are aborting. */ 3986 1.5 augustss if (status == USBD_CANCELLED) 3987 1.5 augustss return; 3988 1.5 augustss 3989 1.173 mlelstv if (status != USBD_NORMAL_COMPLETION && status != USBD_SHORT_XFER) 3990 1.179 mlelstv device_printf(sc->sc_dev, "rintr error: %s\n", 3991 1.173 mlelstv usbd_errstr(status)); 3992 1.173 mlelstv 3993 1.18 augustss usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 3994 1.122 mrg DPRINTFN(5, "count=%d, transferred=%d\n", count, ch->transferred); 3995 1.31 augustss 3996 1.62 toshii /* count < cb->size is normal for asynchronous source */ 3997 1.1 augustss #ifdef DIAGNOSTIC 3998 1.62 toshii if (count > cb->size) { 3999 1.179 mlelstv device_printf(sc->sc_dev, 4000 1.171 mlelstv "uaudio_chan_rintr: count(%d) > size(%d) status(%d)\n", 4001 1.171 mlelstv count, cb->size, status); 4002 1.1 augustss } 4003 1.1 augustss #endif 4004 1.1 augustss 4005 1.56 kent /* 4006 1.5 augustss * Transfer data from channel buffer to upper layer buffer, taking 4007 1.5 augustss * care of wrapping the upper layer buffer. 4008 1.5 augustss */ 4009 1.179 mlelstv for (i = 0; i < ch->nframes; i++) { 4010 1.62 toshii frsize = cb->sizes[i]; 4011 1.157 riastrad n = uimin(frsize, ch->end - ch->cur); 4012 1.62 toshii memcpy(ch->cur, cb->buffer + cb->offsets[i], n); 4013 1.62 toshii ch->cur += n; 4014 1.62 toshii if (ch->cur >= ch->end) 4015 1.62 toshii ch->cur = ch->start; 4016 1.62 toshii if (frsize > n) { 4017 1.62 toshii memcpy(ch->cur, cb->buffer + cb->offsets[i] + n, 4018 1.62 toshii frsize - n); 4019 1.62 toshii ch->cur += frsize - n; 4020 1.62 toshii } 4021 1.5 augustss } 4022 1.5 augustss 4023 1.5 augustss /* Call back to upper layer */ 4024 1.179 mlelstv mutex_enter(&sc->sc_intr_lock); 4025 1.62 toshii ch->transferred += count; 4026 1.1 augustss while (ch->transferred >= ch->blksize) { 4027 1.1 augustss ch->transferred -= ch->blksize; 4028 1.122 mrg DPRINTFN(5, "call %p(%p)\n", ch->intr, ch->arg); 4029 1.1 augustss ch->intr(ch->arg); 4030 1.1 augustss } 4031 1.179 mlelstv mutex_exit(&sc->sc_intr_lock); 4032 1.1 augustss 4033 1.1 augustss /* start next transfer */ 4034 1.5 augustss uaudio_chan_rtransfer(ch); 4035 1.1 augustss } 4036 1.1 augustss 4037 1.86 kent Static void 4038 1.179 mlelstv uaudio_chan_init(struct chan *ch, int altidx, 4039 1.179 mlelstv const struct audio_params *param, int maxpktsize, bool isrecord) 4040 1.1 augustss { 4041 1.179 mlelstv struct uaudio_softc *sc = ch->sc; 4042 1.1 augustss int samples_per_frame, sample_size; 4043 1.1 augustss 4044 1.179 mlelstv DPRINTFN(5, "altidx=%d, %d/%d %dch %dHz ufps %u max %d\n", 4045 1.179 mlelstv altidx, param->validbits, param->precision, param->channels, 4046 1.179 mlelstv param->sample_rate, sc->sc_usb_frames_per_second, maxpktsize); 4047 1.179 mlelstv 4048 1.54 kent ch->altidx = altidx; 4049 1.93 kent sample_size = param->precision * param->channels / 8; 4050 1.179 mlelstv 4051 1.179 mlelstv if (isrecord) { 4052 1.179 mlelstv if (maxpktsize >= sample_size) 4053 1.179 mlelstv samples_per_frame = maxpktsize / sample_size; 4054 1.179 mlelstv else 4055 1.179 mlelstv samples_per_frame = param->sample_rate / sc->sc_usb_frames_per_second 4056 1.179 mlelstv + param->channels; 4057 1.179 mlelstv ch->fraction = 0; 4058 1.179 mlelstv } else { 4059 1.179 mlelstv samples_per_frame = param->sample_rate / sc->sc_usb_frames_per_second; 4060 1.179 mlelstv ch->fraction = param->sample_rate % sc->sc_usb_frames_per_second; 4061 1.179 mlelstv } 4062 1.179 mlelstv 4063 1.1 augustss ch->sample_size = sample_size; 4064 1.93 kent ch->sample_rate = param->sample_rate; 4065 1.179 mlelstv ch->bytes_per_frame = samples_per_frame * sample_size; 4066 1.179 mlelstv 4067 1.179 mlelstv if (maxpktsize > 0 && ch->bytes_per_frame > maxpktsize) { 4068 1.179 mlelstv samples_per_frame = maxpktsize / sample_size; 4069 1.65 toshii ch->bytes_per_frame = samples_per_frame * sample_size; 4070 1.65 toshii } 4071 1.179 mlelstv 4072 1.1 augustss ch->residue = 0; 4073 1.54 kent } 4074 1.1 augustss 4075 1.86 kent Static void 4076 1.54 kent uaudio_chan_set_param(struct chan *ch, u_char *start, u_char *end, int blksize) 4077 1.54 kent { 4078 1.94 kent 4079 1.1 augustss ch->start = start; 4080 1.1 augustss ch->end = end; 4081 1.1 augustss ch->cur = start; 4082 1.1 augustss ch->blksize = blksize; 4083 1.1 augustss ch->transferred = 0; 4084 1.1 augustss ch->curchanbuf = 0; 4085 1.1 augustss } 4086 1.1 augustss 4087 1.86 kent Static int 4088 1.160 isaki uaudio_set_format(void *addr, int setmode, 4089 1.160 isaki const audio_params_t *play, const audio_params_t *rec, 4090 1.160 isaki audio_filter_reg_t *pfil, audio_filter_reg_t *rfil) 4091 1.1 augustss { 4092 1.94 kent struct uaudio_softc *sc; 4093 1.94 kent int paltidx, raltidx; 4094 1.1 augustss 4095 1.94 kent sc = addr; 4096 1.94 kent paltidx = -1; 4097 1.94 kent raltidx = -1; 4098 1.1 augustss if (sc->sc_dying) 4099 1.94 kent return EIO; 4100 1.1 augustss 4101 1.160 isaki if ((setmode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) { 4102 1.47 jdolecek sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 0; 4103 1.92 kent } 4104 1.160 isaki if ((setmode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) { 4105 1.47 jdolecek sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 0; 4106 1.92 kent } 4107 1.47 jdolecek 4108 1.76 mycroft /* Some uaudio devices are unidirectional. Don't try to find a 4109 1.76 mycroft matching mode for the unsupported direction. */ 4110 1.76 mycroft setmode &= sc->sc_mode; 4111 1.76 mycroft 4112 1.73 mycroft if ((setmode & AUMODE_PLAY)) { 4113 1.160 isaki paltidx = audio_indexof_format(sc->sc_formats, sc->sc_nformats, 4114 1.160 isaki AUMODE_PLAY, play); 4115 1.160 isaki /* Transfer should have halted */ 4116 1.179 mlelstv uaudio_chan_init(&sc->sc_playchan, paltidx, play, 4117 1.179 mlelstv UGETW(sc->sc_alts[paltidx].edesc->wMaxPacketSize), false); 4118 1.47 jdolecek } 4119 1.73 mycroft if ((setmode & AUMODE_RECORD)) { 4120 1.160 isaki raltidx = audio_indexof_format(sc->sc_formats, sc->sc_nformats, 4121 1.160 isaki AUMODE_RECORD, rec); 4122 1.160 isaki /* Transfer should have halted */ 4123 1.169 isaki uaudio_chan_init(&sc->sc_recchan, raltidx, rec, 4124 1.179 mlelstv UGETW(sc->sc_alts[raltidx].edesc->wMaxPacketSize), true); 4125 1.47 jdolecek } 4126 1.47 jdolecek 4127 1.160 isaki if ((setmode & AUMODE_PLAY) && sc->sc_playchan.altidx != -1) { 4128 1.73 mycroft sc->sc_alts[sc->sc_playchan.altidx].sc_busy = 1; 4129 1.92 kent } 4130 1.160 isaki if ((setmode & AUMODE_RECORD) && sc->sc_recchan.altidx != -1) { 4131 1.73 mycroft sc->sc_alts[sc->sc_recchan.altidx].sc_busy = 1; 4132 1.92 kent } 4133 1.73 mycroft 4134 1.122 mrg DPRINTF("use altidx=p%d/r%d, altno=p%d/r%d\n", 4135 1.56 kent sc->sc_playchan.altidx, sc->sc_recchan.altidx, 4136 1.47 jdolecek (sc->sc_playchan.altidx >= 0) 4137 1.47 jdolecek ?sc->sc_alts[sc->sc_playchan.altidx].idesc->bAlternateSetting 4138 1.47 jdolecek : -1, 4139 1.47 jdolecek (sc->sc_recchan.altidx >= 0) 4140 1.47 jdolecek ? sc->sc_alts[sc->sc_recchan.altidx].idesc->bAlternateSetting 4141 1.122 mrg : -1); 4142 1.56 kent 4143 1.94 kent return 0; 4144 1.1 augustss } 4145 1.1 augustss 4146 1.86 kent Static usbd_status 4147 1.179 mlelstv uaudio_speed(struct uaudio_softc *sc, int endpt, int clkid, 4148 1.179 mlelstv uint8_t *data, int set) 4149 1.1 augustss { 4150 1.1 augustss usb_device_request_t req; 4151 1.175 mlelstv 4152 1.175 mlelstv switch (sc->sc_version) { 4153 1.175 mlelstv case UAUDIO_VERSION1: 4154 1.179 mlelstv req.bmRequestType = set ? 4155 1.179 mlelstv UT_WRITE_CLASS_ENDPOINT 4156 1.179 mlelstv : UT_READ_CLASS_ENDPOINT; 4157 1.179 mlelstv req.bRequest = set ? 4158 1.179 mlelstv SET_CUR 4159 1.179 mlelstv : GET_CUR; 4160 1.175 mlelstv USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0); 4161 1.175 mlelstv USETW(req.wIndex, endpt); 4162 1.175 mlelstv USETW(req.wLength, 3); 4163 1.175 mlelstv break; 4164 1.175 mlelstv case UAUDIO_VERSION2: 4165 1.179 mlelstv req.bmRequestType = set ? 4166 1.179 mlelstv UT_WRITE_CLASS_INTERFACE 4167 1.179 mlelstv : UT_READ_CLASS_INTERFACE; 4168 1.175 mlelstv req.bRequest = V2_CUR; 4169 1.175 mlelstv USETW2(req.wValue, SAMPLING_FREQ_CONTROL, 0); 4170 1.179 mlelstv USETW2(req.wIndex, clkid, sc->sc_ac_iface); 4171 1.175 mlelstv USETW(req.wLength, 4); 4172 1.175 mlelstv break; 4173 1.175 mlelstv } 4174 1.1 augustss 4175 1.179 mlelstv return usbd_do_request(sc->sc_udev, &req, data); 4176 1.179 mlelstv } 4177 1.179 mlelstv 4178 1.179 mlelstv Static usbd_status 4179 1.179 mlelstv uaudio_set_speed(struct uaudio_softc *sc, int endpt, int clkid, u_int speed) 4180 1.179 mlelstv { 4181 1.179 mlelstv uint8_t data[4]; 4182 1.179 mlelstv 4183 1.179 mlelstv DPRINTFN(5, "endpt=%d clkid=%u speed=%u\n", endpt, clkid, speed); 4184 1.179 mlelstv 4185 1.179 mlelstv data[0] = speed; 4186 1.179 mlelstv data[1] = speed >> 8; 4187 1.179 mlelstv data[2] = speed >> 16; 4188 1.179 mlelstv data[3] = speed >> 24; 4189 1.121 jmcneill 4190 1.179 mlelstv return uaudio_speed(sc, endpt, clkid, data, 1); 4191 1.1 augustss } 4192 1.114 kent 4193 1.179 mlelstv #ifdef UAUDIO_DEBUG 4194 1.179 mlelstv SYSCTL_SETUP(sysctl_hw_uaudio_setup, "sysctl hw.uaudio setup") 4195 1.179 mlelstv { 4196 1.179 mlelstv int err; 4197 1.179 mlelstv const struct sysctlnode *rnode; 4198 1.179 mlelstv const struct sysctlnode *cnode; 4199 1.179 mlelstv 4200 1.179 mlelstv err = sysctl_createv(clog, 0, NULL, &rnode, 4201 1.179 mlelstv CTLFLAG_PERMANENT, CTLTYPE_NODE, "uaudio", 4202 1.179 mlelstv SYSCTL_DESCR("uaudio global controls"), 4203 1.179 mlelstv NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL); 4204 1.179 mlelstv 4205 1.179 mlelstv if (err) 4206 1.179 mlelstv goto fail; 4207 1.179 mlelstv 4208 1.179 mlelstv /* control debugging printfs */ 4209 1.179 mlelstv err = sysctl_createv(clog, 0, &rnode, &cnode, 4210 1.179 mlelstv CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, 4211 1.179 mlelstv "debug", SYSCTL_DESCR("Enable debugging output"), 4212 1.179 mlelstv NULL, 0, &uaudiodebug, sizeof(uaudiodebug), CTL_CREATE, CTL_EOL); 4213 1.179 mlelstv if (err) 4214 1.179 mlelstv goto fail; 4215 1.179 mlelstv 4216 1.179 mlelstv return; 4217 1.179 mlelstv fail: 4218 1.179 mlelstv aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err); 4219 1.179 mlelstv } 4220 1.179 mlelstv #endif 4221 1.179 mlelstv 4222 1.114 kent #ifdef _MODULE 4223 1.114 kent 4224 1.114 kent MODULE(MODULE_CLASS_DRIVER, uaudio, NULL); 4225 1.114 kent 4226 1.114 kent static const struct cfiattrdata audiobuscf_iattrdata = { 4227 1.114 kent "audiobus", 0, { { NULL, NULL, 0 }, } 4228 1.114 kent }; 4229 1.114 kent static const struct cfiattrdata * const uaudio_attrs[] = { 4230 1.114 kent &audiobuscf_iattrdata, NULL 4231 1.114 kent }; 4232 1.114 kent CFDRIVER_DECL(uaudio, DV_DULL, uaudio_attrs); 4233 1.114 kent extern struct cfattach uaudio_ca; 4234 1.114 kent static int uaudioloc[6/*USBIFIFCF_NLOCS*/] = { 4235 1.114 kent -1/*USBIFIFCF_PORT_DEFAULT*/, 4236 1.114 kent -1/*USBIFIFCF_CONFIGURATION_DEFAULT*/, 4237 1.114 kent -1/*USBIFIFCF_INTERFACE_DEFAULT*/, 4238 1.114 kent -1/*USBIFIFCF_VENDOR_DEFAULT*/, 4239 1.114 kent -1/*USBIFIFCF_PRODUCT_DEFAULT*/, 4240 1.114 kent -1/*USBIFIFCF_RELEASE_DEFAULT*/}; 4241 1.114 kent static struct cfparent uhubparent = { 4242 1.114 kent "usbifif", NULL, DVUNIT_ANY 4243 1.114 kent }; 4244 1.114 kent static struct cfdata uaudio_cfdata[] = { 4245 1.114 kent { 4246 1.114 kent .cf_name = "uaudio", 4247 1.114 kent .cf_atname = "uaudio", 4248 1.114 kent .cf_unit = 0, 4249 1.114 kent .cf_fstate = FSTATE_STAR, 4250 1.114 kent .cf_loc = uaudioloc, 4251 1.114 kent .cf_flags = 0, 4252 1.114 kent .cf_pspec = &uhubparent, 4253 1.114 kent }, 4254 1.114 kent { NULL } 4255 1.114 kent }; 4256 1.114 kent 4257 1.114 kent static int 4258 1.114 kent uaudio_modcmd(modcmd_t cmd, void *arg) 4259 1.114 kent { 4260 1.114 kent int err; 4261 1.114 kent 4262 1.114 kent switch (cmd) { 4263 1.114 kent case MODULE_CMD_INIT: 4264 1.114 kent err = config_cfdriver_attach(&uaudio_cd); 4265 1.114 kent if (err) { 4266 1.114 kent return err; 4267 1.114 kent } 4268 1.114 kent err = config_cfattach_attach("uaudio", &uaudio_ca); 4269 1.114 kent if (err) { 4270 1.114 kent config_cfdriver_detach(&uaudio_cd); 4271 1.114 kent return err; 4272 1.114 kent } 4273 1.114 kent err = config_cfdata_attach(uaudio_cfdata, 1); 4274 1.114 kent if (err) { 4275 1.114 kent config_cfattach_detach("uaudio", &uaudio_ca); 4276 1.114 kent config_cfdriver_detach(&uaudio_cd); 4277 1.114 kent return err; 4278 1.114 kent } 4279 1.114 kent return 0; 4280 1.114 kent case MODULE_CMD_FINI: 4281 1.114 kent err = config_cfdata_detach(uaudio_cfdata); 4282 1.114 kent if (err) 4283 1.114 kent return err; 4284 1.114 kent config_cfattach_detach("uaudio", &uaudio_ca); 4285 1.114 kent config_cfdriver_detach(&uaudio_cd); 4286 1.114 kent return 0; 4287 1.114 kent default: 4288 1.114 kent return ENOTTY; 4289 1.114 kent } 4290 1.114 kent } 4291 1.114 kent 4292 1.114 kent #endif 4293