Subject: kern/26538: Source Selector for USB Audio (uaudio.c)
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <kazuhito@ph.noda.tus.ac.jp>
List: netbsd-bugs
Date: 08/03/2004 16:19:58
>Number: 26538
>Category: kern
>Synopsis: Source Selector for USB Audio (uaudio.c)
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Aug 03 18:45:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: Kazuhito HONDA
>Release: NetBSD 2.0G
>Organization:
>Environment:
NetBSD kaoru 2.0G NetBSD 2.0G #250: Sat Jul 31 04:00:15 JST 2004 root@kaoru:/sys/arch/i386/compile/KAORU.2.0G.1 i386
>Description:
This is a suggestion for a improvement.
I have USB audio device, Sound Blaster Digital Music (SBDM).
This has a source selector for recording.
But NetBSD don't have its controller.
So I added codes to uaudio.c in order to control it.
Because I roughly referred to other codes of audio devices only,
I can't recognize that the codes are strictly correct.
But I haven't had any problem.
For example, using SBDM, mixerctl -av wrote:
outputs.fea8-i10i11i12=1 [ 1 2 3 ]
This is a variable for selector control.
In this case, users can select one source from feature 10, 11 and 12.
Values of feature 10 11 and 12 are 1, 2 and 3 respectively.
The codes don't use the feature numbers for variable value,
because it may be difficult
and the feature numbers must be indirect
and senseless for general users, too.
>How-To-Repeat:
>Fix:
--- uaudio.c.orig 2004-07-17 07:39:23.000000000 +0900
+++ uaudio.c 2004-08-04 02:48:15.000000000 +0900
@@ -97,6 +97,7 @@
#define MIX_SIGNED_16 2
#define MIX_UNSIGNED_16 3
#define MIX_SIGNED_8 4
+#define MIX_SELECTOR 5
#define MIX_SIZE(n) ((n) == MIX_SIGNED_16 || (n) == MIX_UNSIGNED_16 ? 2 : 1)
#define MIX_UNSIGNED(n) ((n) == MIX_UNSIGNED_16)
int minval, maxval;
@@ -579,7 +580,12 @@
sc->sc_ctls = nmc;
mc->delta = 0;
- if (mc->type != MIX_ON_OFF) {
+ if (mc->type == MIX_ON_OFF) {
+ mc->minval = 0;
+ mc->maxval = 1;
+ } else if (mc->type == MIX_SELECTOR) {
+ ;
+ } else {
/* Determine min and max values. */
mc->minval = uaudio_signext(mc->type,
uaudio_get(sc, GET_MIN, UT_READ_CLASS_INTERFACE,
@@ -597,9 +603,6 @@
MIX_SIZE(mc->type));
if (res > 0)
mc->delta = (res * 255 + mc->mul/2) / mc->mul;
- } else {
- mc->minval = 0;
- mc->maxval = 1;
}
sc->sc_ctls[sc->sc_nctls++] = *mc;
@@ -800,14 +803,34 @@
uaudio_add_selector(struct uaudio_softc *sc, usb_descriptor_t *v,
usb_descriptor_t **dps)
{
-#ifdef UAUDIO_DEBUG
struct usb_audio_selector_unit *d =
(struct usb_audio_selector_unit *)v;
+ int i, srcId;
+ struct mixerctl mix;
+ char ctlname[MAX_AUDIO_DEV_LEN];
+#ifdef UAUDIO_DEBUG
DPRINTFN(2,("uaudio_add_selector: bUnitId=%d bNrInPins=%d\n",
d->bUnitId, d->bNrInPins));
#endif
- printf("uaudio_add_selector: NOT IMPLEMENTED\n");
+ mix.wIndex = MAKE(d->bUnitId, sc->sc_ac_iface);
+ mix.wValue[0] = MAKE(0, 0);
+ mix.class = UAC_OUTPUT;
+ mix.nchan = 1;
+ mix.type = MIX_SELECTOR;
+ mix.ctlunit = "";
+ mix.minval = 1;
+ mix.maxval = d->bNrInPins;
+ mix.mul = mix.maxval - mix.minval;
+ snprintf(mix.ctlname, MAX_AUDIO_DEV_LEN, "fea%d-", d->bUnitId);
+ for (i = 1; i <= d->bNrInPins; i++) {
+ srcId = d->baSourceId[i - 1];
+ snprintf(ctlname, MAX_AUDIO_DEV_LEN, "i%d", srcId);
+ if (strlen(mix.ctlname) + strlen(ctlname) > MAX_AUDIO_DEV_LEN - 1)
+ break;
+ strcat(mix.ctlname, ctlname);
+ }
+ uaudio_mixer_add_ctl(sc, &mix);
}
void
@@ -1386,7 +1409,7 @@
{
struct uaudio_softc *sc = addr;
struct mixerctl *mc;
- int n, nctls;
+ int n, nctls, i;
DPRINTFN(2,("uaudio_query_devinfo: index=%d\n", mi->index));
if (sc->sc_dying)
@@ -1438,6 +1461,14 @@
sizeof(mi->un.e.member[1].label.name));
mi->un.e.member[1].ord = 1;
break;
+ case MIX_SELECTOR:
+ mi->type = AUDIO_MIXER_ENUM;
+ mi->un.e.num_mem = mc->maxval - mc->minval + 1;
+ for (i = 0; i <= mc->maxval - mc->minval; i++) {
+ snprintf(mi->un.e.member[i].label.name, sizeof(mi->un.e.member[i].label.name),"%d", i + mc->minval);
+ mi->un.e.member[i].ord = i + mc->minval;
+ }
+ break;
default:
mi->type = AUDIO_MIXER_VALUE;
strncpy(mi->un.v.units.name, mc->ctlunit, MAX_AUDIO_DEV_LEN);
@@ -1667,7 +1698,10 @@
mc->type, val, mc->minval, mc->maxval));
if (mc->type == MIX_ON_OFF)
val = (val != 0);
- else
+ else if (mc->type == MIX_SELECTOR) {
+ if (val < mc->minval || val > mc->maxval)
+ val = mc->minval;
+ } else
val = ((uaudio_signext(mc->type, val) - mc->minval) * 255
+ mc->mul/2) / mc->mul;
DPRINTFN(5, ("val'=%d\n", val));
@@ -1681,7 +1715,10 @@
mc->type, val, mc->minval, mc->maxval));
if (mc->type == MIX_ON_OFF)
val = (val != 0);
- else
+ else if (mc->type == MIX_SELECTOR) {
+ if (val < mc->minval || val > mc->maxval)
+ val = mc->minval;
+ } else
val = (val + mc->delta/2) * mc->mul / 255 + mc->minval;
DPRINTFN(5, ("val'=%d\n", val));
return (val);
@@ -1729,6 +1766,10 @@
if (cp->type != AUDIO_MIXER_ENUM)
return (EINVAL);
cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
+ } else if (mc->type == MIX_SELECTOR) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return (EINVAL);
+ cp->un.ord = uaudio_ctl_get(sc, GET_CUR, mc, 0);
} else {
if (cp->type != AUDIO_MIXER_VALUE)
return (EINVAL);
@@ -1769,6 +1810,10 @@
if (cp->type != AUDIO_MIXER_ENUM)
return (EINVAL);
uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
+ } else if (mc->type == MIX_SELECTOR) {
+ if (cp->type != AUDIO_MIXER_ENUM)
+ return (EINVAL);
+ uaudio_ctl_set(sc, SET_CUR, mc, 0, cp->un.ord);
} else {
if (cp->type != AUDIO_MIXER_VALUE)
return (EINVAL);
>Release-Note:
>Audit-Trail:
>Unformatted: