Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Jun 2006 07:41:19 GMT
From:      Ryan Beasley <ryanb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 99801 for review
Message-ID:  <200606220741.k5M7fJWs023014@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99801

Change 99801 by ryanb@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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606220741.k5M7fJWs023014>