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>