PERFORCE change 99801 for review
Ryan Beasley
ryanb at FreeBSD.org
Thu Jun 22 07:41:22 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=99801
Change 99801 by ryanb at ryanb_yuki on 2006/06/22 07:40:26
Added support for the following ioctls, which are mostly wrappers around
the current mixer API:
- SNDCTL_DSP_{GET,SET}{REC,PLAY}VOL
- SNDCTL_DSP_GET_RECSRC_NAMES
- SNDCTL_DSP_{GET,SET}_RECSRC
Affected files ...
.. //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/dsp.c#6 edit
.. //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/mixer.c#5 edit
.. //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/mixer.h#4 edit
.. //depot/projects/soc2006/rbeasley_sound/sys/sys/soundcard.h#6 edit
Differences ...
==== //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/dsp.c#6 (text+ko) ====
@@ -407,6 +407,11 @@
struct snddev_info *d;
int kill;
int ret = 0, *arg_i = (int *)arg, tmp;
+#ifdef OSSV4_EXPERIMENT
+ int xcmd;
+
+ xcmd = 0;
+#endif
/*
* this is an evil hack to allow broken apps to perform mixer ioctls
@@ -1039,6 +1044,44 @@
case SNDCTL_AUDIOINFO:
ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg);
break;
+
+ /*
+ * The following four ioctls are simple wrappers around mixer_ioctl
+ * with no further processing. xcmd is short for "translated
+ * command".
+ */
+ case SNDCTL_DSP_GETRECVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_READ_RECLEV;
+ /* FALLTHROUGH */
+ case SNDCTL_DSP_SETRECVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_WRITE_RECLEV;
+ /* FALLTHROUGH */
+ case SNDCTL_DSP_GETPLAYVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_READ_PCM;
+ /* FALLTHROUGH */
+ case SNDCTL_DSP_SETPLAYVOL:
+ if (xcmd == 0)
+ xcmd = SOUND_MIXER_WRITE_PCM;
+
+ if (d->mixer_dev != NULL)
+ ret = mixer_ioctl(d->mixer_dev, xcmd, arg, -1, td);
+ else
+ /** @todo verify that this is the correct error */
+ ret = ENOTSUP;
+ break;
+
+ case SNDCTL_DSP_GET_RECSRC_NAMES:
+ case SNDCTL_DSP_GET_RECSRC:
+ case SNDCTL_DSP_SET_RECSRC:
+ if (d->mixer_dev != NULL)
+ ret = mixer_ioctl(d->mixer_dev, cmd, arg, -1, td);
+ else
+ /** @todo verify error correctness */
+ ret = EINVAL;
+ break;
#endif /* !OSSV4_EXPERIMENT */
case SNDCTL_DSP_MAPINBUF:
case SNDCTL_DSP_MAPOUTBUF:
==== //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/mixer.c#5 (text+ko) ====
@@ -49,6 +49,9 @@
u_int16_t level[32];
char name[MIXER_NAMELEN];
struct mtx *lock;
+#ifdef OSSV4_EXPERIMENT
+ oss_mixer_enuminfo enuminfo;
+#endif
};
static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = {
@@ -188,6 +191,85 @@
return mixer->recsrc;
}
+#ifdef OSSV4_EXPERIMENT
+/**
+ * @brief Retrieve the route number of the current recording device
+ *
+ * OSSv4 assigns routing numbers to recording devices, unlike the previous
+ * API which relied on a fixed table of device numbers and names. This
+ * function returns the routing number of the device currently selected
+ * for recording.
+ *
+ * For now, this function is kind of a goofy compatibility stub atop the
+ * existing sound system. (For example, in theory, the old sound system
+ * allows multiple recording devices to be specified via a bitmask.)
+ *
+ * @param m mixer context container thing
+ *
+ * @retval 0 success
+ * @retval EIDRM no recording device found (generally not possible)
+ * @todo Ask about error code
+ */
+static int
+mixer_get_recroute(struct snd_mixer *m, int *route)
+{
+ int i, cnt;
+
+ cnt = 0;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ /** @todo can user set a multi-device mask? (== or &?) */
+ if ((1 << i) == m->recsrc)
+ break;
+ if ((1 << i) & m->recdevs)
+ ++cnt;
+ }
+
+ if (i == SOUND_MIXER_NRDEVICES)
+ return EIDRM;
+
+ *route = cnt;
+ return 0;
+}
+
+/**
+ * @brief Select a device for recording
+ *
+ * This function sets a recording source based on a recording device's
+ * routing number. Said number is translated to an old school recdev
+ * mask and passed over mixer_setrecsrc.
+ *
+ * @param m mixer context container thing
+ *
+ * @retval 0 success(?)
+ * @retval EINVAL User specified an invalid device number
+ * @retval otherwise error from mixer_setrecsrc
+ */
+static int
+mixer_set_recroute(struct snd_mixer *m, int route)
+{
+ int i, cnt, ret;
+
+ ret = 0;
+ cnt = 0;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1 << i) & m->recdevs) {
+ if (route == cnt)
+ break;
+ ++cnt;
+ }
+ }
+
+ if (i == SOUND_MIXER_NRDEVICES)
+ ret = EINVAL;
+ else
+ ret = mixer_setrecsrc(m, (1 << i));
+
+ return ret;
+}
+#endif /* !OSSV4_EXPERIMENT */
+
void
mix_setdevs(struct snd_mixer *m, u_int32_t v)
{
@@ -197,9 +279,70 @@
m->devs = v;
}
+/**
+ * @brief Record mask of available recording devices
+ *
+ * Calling functions are responsible for defining the mask of available
+ * recording devices. This function records that value in a structure
+ * used by the rest of the mixer code.
+ *
+ * This function also populates a structure used by the SNDCTL_DSP_*RECSRC*
+ * family of ioctls that are part of OSSV4. All recording device labels
+ * are concatenated in ascending order corresponding to their routing
+ * numbers. (Ex: a system might have 0 => 'vol', 1 => 'cd', 2 => 'line',
+ * etc.) For now, these labels are just the standard recording device
+ * names (cd, line1, etc.), but will eventually be fully dynamic and user
+ * controlled.
+ *
+ * @param m mixer device context container thing
+ * @param v mask of recording devices
+ */
void
mix_setrecdevs(struct snd_mixer *m, u_int32_t v)
{
+#ifdef OSSV4_EXPERIMENT
+ oss_mixer_enuminfo *ei;
+ char *loc;
+ int i, nvalues, nwrote, nleft, ncopied;
+
+ ei = &m->enuminfo;
+
+ nvalues = 0;
+ nwrote = 0;
+ nleft = sizeof(ei->strings);
+ loc = ei->strings;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if ((1 << i) & v) {
+ ei->strindex[nvalues] = nwrote;
+ ncopied = strlcpy(loc, snd_mixernames[i], nleft) + 1;
+ /* strlcpy retval doesn't include terminator */
+
+ nwrote += ncopied;
+ nleft -= ncopied;
+ nvalues++;
+
+ /*
+ * XXX I don't think this should ever be possible.
+ * Even with a move to dynamic device/channel names,
+ * each label is limited to ~16 characters, so that'd
+ * take a LOT to fill this buffer. panic()?
+ */
+ if ((nleft <= 0) || (nvalues >= OSS_ENUM_MAXVALUE)) {
+ printf("mix_setrecdevs: enuminfo too small");
+ break;
+ }
+
+ loc = &ei->strings[nwrote];
+ }
+ }
+
+ /*
+ * NB: The SNDCTL_DSP_GET_RECSRC_NAMES ioctl ignores the dev
+ * and ctrl fields.
+ */
+ ei->nvalues = nvalues;
+#endif /* !OSSV4_EXPERIMENT */
m->recdevs = v;
}
@@ -528,19 +671,34 @@
snd_mtxunlock(m->lock);
return (v != -1)? 0 : ENXIO;
}
+
+ ret = 0;
+
+ switch (cmd) {
#ifdef OSSV4_EXPERIMENT
- if (cmd == SNDCTL_SYSINFO) {
+ /** @todo Double check return values, error codes. */
+ case SNDCTL_SYSINFO:
sound_oss_sysinfo((oss_sysinfo *)arg);
- snd_mtxunlock(m->lock);
- return 0;
- } else if (cmd == SNDCTL_AUDIOINFO) {
+ break;
+ case SNDCTL_AUDIOINFO:
ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg);
- snd_mtxunlock(m->lock);
- return ret;
+ break;
+ case SNDCTL_DSP_GET_RECSRC_NAMES:
+ bcopy((void *)&m->enuminfo, arg, sizeof(oss_mixer_enuminfo));
+ break;
+ case SNDCTL_DSP_GET_RECSRC:
+ ret = mixer_get_recroute(m, arg_i);
+ break;
+ case SNDCTL_DSP_SET_RECSRC:
+ ret = mixer_set_recroute(m, *arg_i);
+ break;
+#endif /* !OSSV4_EXPERIMENT */
+ default:
+ ret = ENXIO;
}
-#endif /* !OSSV4_EXPERIMENT */
+
snd_mtxunlock(m->lock);
- return ENXIO;
+ return ret;
}
#ifdef USING_DEVFS
==== //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/mixer.h#4 (text+ko) ====
@@ -49,6 +49,11 @@
* this is a kludge to allow hiding of the struct snd_mixer definition
* 512 should be enough for all architectures
*/
-#define MIXER_SIZE (512 + sizeof(struct kobj))
+#ifdef OSSV4_EXPERIMENT
+# define MIXER_SIZE (512 + sizeof(struct kobj) + \
+ sizeof(oss_mixer_enuminfo))
+#else
+# define MIXER_SIZE (512 + sizeof(struct kobj))
+#endif
#define MIXER_DECLARE(name) DEFINE_CLASS(name, name ## _methods, MIXER_SIZE)
==== //depot/projects/soc2006/rbeasley_sound/sys/sys/soundcard.h#6 (text+ko) ====
@@ -1471,6 +1471,38 @@
typedef char oss_label_t[OSS_LABEL_SIZE];
typedef char oss_devnode_t[OSS_DEVNODE_SIZE];
+typedef struct audio_errinfo
+{
+ int play_underruns;
+ int rec_overruns;
+ unsigned int play_ptradjust;
+ unsigned int rec_ptradjust;
+ int play_errorcount;
+ int rec_errorcount;
+ int play_lasterror;
+ int rec_lasterror;
+ long play_errorparm;
+ long rec_errorparm;
+ int filler[16];
+} audio_errinfo;
+
+#define SNDCTL_DSP_GETPLAYVOL _IOR ('P', 24, int)
+#define SNDCTL_DSP_SETPLAYVOL _IOWR('P', 24, int)
+#define SNDCTL_DSP_GETERROR _IOR ('P', 25, audio_errinfo)
+/*
+ ****************************************************************************
+ * Interface for selecting recording sources and playback output routings.
+ */
+#define SNDCTL_DSP_GET_RECSRC_NAMES _IOR ('P', 37, oss_mixer_enuminfo)
+#define SNDCTL_DSP_GET_RECSRC _IOR ('P', 38, int)
+#define SNDCTL_DSP_SET_RECSRC _IOWR('P', 38, int)
+
+#define SNDCTL_DSP_GET_PLAYTGT_NAMES _IOR ('P', 39, oss_mixer_enuminfo)
+#define SNDCTL_DSP_GET_PLAYTGT _IOR ('P', 40, int)
+#define SNDCTL_DSP_SET_PLAYTGT _IOWR('P', 40, int)
+#define SNDCTL_DSP_GETRECVOL _IOR ('P', 41, int)
+#define SNDCTL_DSP_SETRECVOL _IOWR('P', 41, int)
+
/**
* @brief Argument for SNDCTL_SYSINFO ioctl.
*
@@ -1503,6 +1535,26 @@
#define SNDCTL_SYSINFO _IOR ('X', 1, oss_sysinfo)
#define OSS_SYSINFO SNDCTL_SYSINFO /* Old name */
+/*
+ * Few more "globally" available ioctl calls.
+ */
+#define SNDCTL_SETSONG _IOW ('Y', 2, oss_longname_t)
+#define SNDCTL_GETSONG _IOR ('Y', 2, oss_longname_t)
+#define SNDCTL_SETNAME _IOW ('Y', 3, oss_longname_t)
+#define SNDCTL_SETLABEL _IOW ('Y', 4, oss_label_t)
+#define SNDCTL_GETLABEL _IOR ('Y', 4, oss_label_t)
+
+#define OSS_ENUM_MAXVALUE 255
+typedef struct oss_mixer_enuminfo
+{
+ int dev;
+ int ctrl;
+ int nvalues;
+ int version; /* Read the manual */
+ short strindex[OSS_ENUM_MAXVALUE];
+ char strings[3000];
+} oss_mixer_enuminfo;
+
#define OPEN_READ PCM_ENABLE_INPUT
#define OPEN_WRITE PCM_ENABLE_OUTPUT
#define OPEN_READWRITE (OPEN_READ|OPEN_WRITE)
More information about the p4-projects
mailing list