diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -260,6 +260,7 @@ int chn_flush(struct pcm_channel *c); int chn_poll(struct pcm_channel *c, int ev, struct thread *td); +char *chn_mkname(char *buf, size_t len, struct pcm_channel *c); struct pcm_channel *chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo); void chn_kill(struct pcm_channel *c); diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -1161,13 +1161,13 @@ chn_getunr(struct snddev_info *d, int type) { switch (type) { - case SND_DEV_DSPHW_PLAY: + case PCMDIR_PLAY: return (d->p_unr); - case SND_DEV_DSPHW_VPLAY: + case PCMDIR_PLAY_VIRTUAL: return (d->vp_unr); - case SND_DEV_DSPHW_REC: + case PCMDIR_REC: return (d->r_unr); - case SND_DEV_DSPHW_VREC: + case PCMDIR_REC_VIRTUAL: return (d->vr_unr); default: __assert_unreachable(); @@ -1175,6 +1175,36 @@ } +char * +chn_mkname(char *buf, size_t len, struct pcm_channel *c) +{ + const char *str; + + KASSERT(buf != NULL && len != 0, + ("%s(): bogus buf=%p len=%lu", __func__, buf, len)); + + switch (c->type) { + case PCMDIR_PLAY: + str = ".play."; + break; + case PCMDIR_PLAY_VIRTUAL: + str = ".virtual_play."; + break; + case PCMDIR_REC: + str = ".record."; + break; + case PCMDIR_REC_VIRTUAL: + str = ".virtual_record."; + break; + default: + __assert_unreachable(); + } + + snprintf(buf, len, "dsp%d%s%d", device_get_unit(c->dev), str, c->unit); + + return (buf); +} + struct pcm_channel * chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo) @@ -1183,27 +1213,19 @@ struct feeder_class *fc; struct snd_dbuf *b, *bs; char buf[CHN_NAMELEN]; - int i, direction, type; + int i, direction; PCM_BUSYASSERT(d); PCM_LOCKASSERT(d); switch (dir) { - case PCMDIR_PLAY: - direction = PCMDIR_PLAY; - type = SND_DEV_DSPHW_PLAY; - break; + case PCMDIR_PLAY: /* FALLTHROUGH */ case PCMDIR_PLAY_VIRTUAL: direction = PCMDIR_PLAY; - type = SND_DEV_DSPHW_VPLAY; - break; - case PCMDIR_REC: - direction = PCMDIR_REC; - type = SND_DEV_DSPHW_REC; break; + case PCMDIR_REC: /* FALLTHROUGH */ case PCMDIR_REC_VIRTUAL: direction = PCMDIR_REC; - type = SND_DEV_DSPHW_VREC; break; default: device_printf(d->dev, @@ -1222,7 +1244,7 @@ CHN_INIT(c, children); CHN_INIT(c, children.busy); c->direction = direction; - c->type = type; + c->type = dir; c->unit = alloc_unr(chn_getunr(d, c->type)); c->format = SND_FORMAT(AFMT_U8, 1, 0); c->speed = DSP_DEFAULT_SPEED; @@ -1234,8 +1256,7 @@ c->parentchannel = parent; c->dev = d->dev; c->trigger = PCMTRIG_STOP; - - strlcpy(c->name, dsp_unit2name(buf, sizeof(buf), c), sizeof(c->name)); + strlcpy(c->name, chn_mkname(buf, sizeof(buf), c), sizeof(c->name)); c->matrix = *feeder_matrix_id_map(SND_CHN_MATRIX_1_0); c->matrix.id = SND_CHN_MATRIX_PCMCHANNEL; @@ -1303,16 +1324,16 @@ CHN_INSERT_SORT_ASCEND(d, c, channels.pcm); switch (c->type) { - case SND_DEV_DSPHW_PLAY: + case PCMDIR_PLAY: d->playcount++; break; - case SND_DEV_DSPHW_VPLAY: + case PCMDIR_PLAY_VIRTUAL: d->pvchancount++; break; - case SND_DEV_DSPHW_REC: + case PCMDIR_REC: d->reccount++; break; - case SND_DEV_DSPHW_VREC: + case PCMDIR_REC_VIRTUAL: d->rvchancount++; break; default: @@ -1354,16 +1375,16 @@ CHN_REMOVE(d, c, channels.pcm); switch (c->type) { - case SND_DEV_DSPHW_PLAY: + case PCMDIR_PLAY: d->playcount--; break; - case SND_DEV_DSPHW_VPLAY: + case PCMDIR_PLAY_VIRTUAL: d->pvchancount--; break; - case SND_DEV_DSPHW_REC: + case PCMDIR_REC: d->reccount--; break; - case SND_DEV_DSPHW_VREC: + case PCMDIR_REC_VIRTUAL: d->rvchancount--; break; default: diff --git a/sys/dev/sound/pcm/dsp.h b/sys/dev/sound/pcm/dsp.h --- a/sys/dev/sound/pcm/dsp.h +++ b/sys/dev/sound/pcm/dsp.h @@ -35,7 +35,6 @@ int dsp_make_dev(device_t); void dsp_destroy_dev(device_t); -char *dsp_unit2name(char *, size_t, struct pcm_channel *); int dsp_oss_audioinfo(struct cdev *, oss_audioinfo *, bool); int dsp_oss_engineinfo(struct cdev *, oss_audioinfo *); diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -164,25 +164,6 @@ #define DSP_F_READ(x) ((x) & FREAD) #define DSP_F_WRITE(x) ((x) & FWRITE) -static const struct { - int type; - char *name; - char *sep; - char *alias; -} dsp_cdevs[] = { - { SND_DEV_DSP, "dsp", ".", NULL }, - { SND_DEV_DSPHW_PLAY, "dsp", ".play.", NULL }, - { SND_DEV_DSPHW_VPLAY, "dsp", ".virtual_play.", NULL }, - { SND_DEV_DSPHW_REC, "dsp", ".record.", NULL }, - { SND_DEV_DSPHW_VREC, "dsp", ".virtual_record.", NULL }, - /* Low priority, OSSv4 aliases. */ - { SND_DEV_DSP, "dsp_ac3", ".", "dsp" }, - { SND_DEV_DSP, "dsp_mmap", ".", "dsp" }, - { SND_DEV_DSP, "dsp_multich", ".", "dsp" }, - { SND_DEV_DSP, "dsp_spdifout", ".", "dsp" }, - { SND_DEV_DSP, "dsp_spdifin", ".", "dsp" }, -}; - static void dsp_close(void *data) { @@ -1941,20 +1922,26 @@ return (0); } +static const char *dsp_aliases[] = { + "dsp_ac3", + "dsp_mmap", + "dsp_multich", + "dsp_spdifout", + "dsp_spdifin", +}; + static void dsp_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev) { struct snddev_info *d; size_t i; - if (*dev != NULL) return; if (strcmp(name, "dsp") == 0 && dsp_basename_clone) goto found; - for (i = 0; i < nitems(dsp_cdevs); i++) { - if (dsp_cdevs[i].alias != NULL && - strcmp(name, dsp_cdevs[i].name) == 0) + for (i = 0; i < nitems(dsp_aliases); i++) { + if (strcmp(name, dsp_aliases[i]) == 0) goto found; } return; @@ -1994,26 +1981,6 @@ SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL); SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL); -char * -dsp_unit2name(char *buf, size_t len, struct pcm_channel *ch) -{ - size_t i; - - KASSERT(buf != NULL && len != 0, - ("bogus buf=%p len=%ju", buf, (uintmax_t)len)); - - for (i = 0; i < nitems(dsp_cdevs); i++) { - if (ch->type != dsp_cdevs[i].type || dsp_cdevs[i].alias != NULL) - continue; - snprintf(buf, len, "%s%d%s%d", - dsp_cdevs[i].name, device_get_unit(ch->dev), - dsp_cdevs[i].sep, ch->unit); - return (buf); - } - - return (NULL); -} - static void dsp_oss_audioinfo_unavail(oss_audioinfo *ai, int unit) { @@ -2233,7 +2200,6 @@ struct snddev_info *d; uint32_t fmts; int i, nchan, *rates, minch, maxch, unit; - char *devname, buf[CHN_NAMELEN]; /* * If probing the device that received the ioctl, make sure it's a @@ -2244,9 +2210,7 @@ return (EINVAL); ch = NULL; - devname = NULL; nchan = 0; - bzero(buf, sizeof(buf)); /* * Search for the requested audio device (channel). Start by @@ -2267,147 +2231,142 @@ CHN_FOREACH(ch, d, channels.pcm) { CHN_UNLOCKASSERT(ch); CHN_LOCK(ch); - if (ai->dev == -1) { - if (devfs_foreach_cdevpriv(i_dev, - dsp_oss_engineinfo_cb, ch) != 0) { - devname = dsp_unit2name(buf, - sizeof(buf), ch); - } - } else if (ai->dev == nchan) - devname = dsp_unit2name(buf, sizeof(buf), ch); - if (devname != NULL) + if ((ai->dev == -1 && devfs_foreach_cdevpriv( + i_dev, dsp_oss_engineinfo_cb, ch) != 0) || + ai->dev == nchan) break; CHN_UNLOCK(ch); ++nchan; } - if (devname != NULL) { - /* - * At this point, the following synchronization stuff - * has happened: - * - a specific PCM device is locked. - * - a specific audio channel has been locked, so be - * sure to unlock when exiting; - */ + if (ch == NULL) { + PCM_UNLOCK(d); + continue; + } - caps = chn_getcaps(ch); + /* + * At this point, the following synchronization stuff + * has happened: + * - a specific PCM device is locked. + * - a specific audio channel has been locked, so be + * sure to unlock when exiting; + */ - /* - * With all handles collected, zero out the user's - * container and begin filling in its fields. - */ - bzero((void *)ai, sizeof(oss_audioinfo)); + caps = chn_getcaps(ch); - ai->dev = nchan; - strlcpy(ai->name, ch->name, sizeof(ai->name)); + /* + * With all handles collected, zero out the user's + * container and begin filling in its fields. + */ + bzero((void *)ai, sizeof(oss_audioinfo)); - if ((ch->flags & CHN_F_BUSY) == 0) - ai->busy = 0; - else - ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ; + ai->dev = nchan; + strlcpy(ai->name, ch->name, sizeof(ai->name)); - ai->pid = ch->pid; - strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd)); + if ((ch->flags & CHN_F_BUSY) == 0) + ai->busy = 0; + else + ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ; - /* - * These flags stolen from SNDCTL_DSP_GETCAPS handler. - * Note, however, that a single channel operates in - * only one direction, so PCM_CAP_DUPLEX is out. - */ - /** - * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep - * these in pcmchan::caps? - */ - ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER | - ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | - ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT); + ai->pid = ch->pid; + strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd)); - /* - * Collect formats supported @b natively by the - * device. Also determine min/max channels. - */ - minch = INT_MAX; - maxch = 0; - fmts = 0; - for (i = 0; caps->fmtlist[i]; i++) { - fmts |= AFMT_ENCODING(caps->fmtlist[i]); - minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); - maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); - } + /* + * These flags stolen from SNDCTL_DSP_GETCAPS handler. + * Note, however, that a single channel operates in + * only one direction, so PCM_CAP_DUPLEX is out. + */ + /** + * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep + * these in pcmchan::caps? + */ + ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER | + ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | + ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT); - if (ch->direction == PCMDIR_PLAY) - ai->oformats = fmts; - else - ai->iformats = fmts; - - /** - * @note - * @c magic - OSSv4 docs: "Reserved for internal use - * by OSS." - * - * @par - * @c card_number - OSSv4 docs: "Number of the sound - * card where this device belongs or -1 if this - * information is not available. Applications - * should normally not use this field for any - * purpose." - */ - ai->card_number = unit; - /** - * @todo @c song_name - depends first on - * SNDCTL_[GS]ETSONG @todo @c label - depends - * on SNDCTL_[GS]ETLABEL - * @todo @c port_number - routing information? - */ - ai->port_number = unit; - ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; - /** - * @note - * @c legacy_device - OSSv4 docs: "Obsolete." - */ - ai->legacy_device = unit; - snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); - ai->enabled = device_is_attached(d->dev) ? 1 : 0; - /** - * @note - * @c flags - OSSv4 docs: "Reserved for future use." - * - * @note - * @c binding - OSSv4 docs: "Reserved for future use." - * - * @todo @c handle - haven't decided how to generate - * this yet; bus, vendor, device IDs? - */ + /* + * Collect formats supported @b natively by the + * device. Also determine min/max channels. + */ + minch = INT_MAX; + maxch = 0; + fmts = 0; + for (i = 0; caps->fmtlist[i]; i++) { + fmts |= AFMT_ENCODING(caps->fmtlist[i]); + minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); + maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); + } - if ((ch->flags & CHN_F_EXCLUSIVE) || - (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { - ai->min_rate = caps->minspeed; - ai->max_rate = caps->maxspeed; - } else { - ai->min_rate = feeder_rate_min; - ai->max_rate = feeder_rate_max; - } + if (ch->direction == PCMDIR_PLAY) + ai->oformats = fmts; + else + ai->iformats = fmts; + + /** + * @note + * @c magic - OSSv4 docs: "Reserved for internal use + * by OSS." + * + * @par + * @c card_number - OSSv4 docs: "Number of the sound + * card where this device belongs or -1 if this + * information is not available. Applications + * should normally not use this field for any + * purpose." + */ + ai->card_number = unit; + /** + * @todo @c song_name - depends first on + * SNDCTL_[GS]ETSONG @todo @c label - depends + * on SNDCTL_[GS]ETLABEL + * @todo @c port_number - routing information? + */ + ai->port_number = unit; + ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; + /** + * @note + * @c legacy_device - OSSv4 docs: "Obsolete." + */ + ai->legacy_device = unit; + snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); + ai->enabled = device_is_attached(d->dev) ? 1 : 0; + /** + * @note + * @c flags - OSSv4 docs: "Reserved for future use." + * + * @note + * @c binding - OSSv4 docs: "Reserved for future use." + * + * @todo @c handle - haven't decided how to generate + * this yet; bus, vendor, device IDs? + */ - ai->min_channels = minch; - ai->max_channels = maxch; + if ((ch->flags & CHN_F_EXCLUSIVE) || + (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { + ai->min_rate = caps->minspeed; + ai->max_rate = caps->maxspeed; + } else { + ai->min_rate = feeder_rate_min; + ai->max_rate = feeder_rate_max; + } - ai->nrates = chn_getrates(ch, &rates); - if (ai->nrates > OSS_MAX_SAMPLE_RATES) - ai->nrates = OSS_MAX_SAMPLE_RATES; + ai->min_channels = minch; + ai->max_channels = maxch; - for (i = 0; i < ai->nrates; i++) - ai->rates[i] = rates[i]; - - ai->next_play_engine = 0; - ai->next_rec_engine = 0; + ai->nrates = chn_getrates(ch, &rates); + if (ai->nrates > OSS_MAX_SAMPLE_RATES) + ai->nrates = OSS_MAX_SAMPLE_RATES; - CHN_UNLOCK(ch); - } + for (i = 0; i < ai->nrates; i++) + ai->rates[i] = rates[i]; + + ai->next_play_engine = 0; + ai->next_rec_engine = 0; + CHN_UNLOCK(ch); PCM_UNLOCK(d); - if (devname != NULL) - return (0); + return (0); } /* Exhausted the search -- nothing is locked, so return. */ diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -225,10 +225,6 @@ SND_DEV_MIDIN, /* Raw midi access */ SND_DEV_DSP, /* Digitized voice /dev/dsp */ SND_DEV_STATUS, /* /dev/sndstat */ - SND_DEV_DSPHW_PLAY, /* specific playback channel */ - SND_DEV_DSPHW_VPLAY, /* specific virtual playback channel */ - SND_DEV_DSPHW_REC, /* specific record channel */ - SND_DEV_DSPHW_VREC, /* specific virtual record channel */ }; #define DSP_DEFAULT_SPEED 8000 diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c --- a/sys/dev/sound/pcm/vchan.c +++ b/sys/dev/sound/pcm/vchan.c @@ -886,14 +886,9 @@ c->flags |= CHN_F_DIRTY; #ifdef SND_DEBUG - if (snd_passthrough_verbose != 0) { - char *devname, buf[CHN_NAMELEN]; - - devname = dsp_unit2name(buf, sizeof(buf), c); - device_printf(c->dev, - "%s(%s/%s) %s() -> re-sync err=%d\n", - __func__, (devname != NULL) ? devname : "dspX", c->comm, - caller, ret); + if (snd_passthrough_verbose) { + device_printf(c->dev, "%s(%s/%s) %s() -> re-sync err=%d\n", + __func__, c->name, c->comm, caller, ret); } #endif