summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2002-01-23 05:21:27 +0000
committercg <cg@FreeBSD.org>2002-01-23 05:21:27 +0000
commit505a32c5daf85f50f560ecce7803988370e53eb8 (patch)
treef6bbf24aa823995444c7bacc7009c1f2eeabdbf3
parent3b2958fa78f7a813524c7610f56e82b698c8b2a1 (diff)
downloadFreeBSD-src-505a32c5daf85f50f560ecce7803988370e53eb8.zip
FreeBSD-src-505a32c5daf85f50f560ecce7803988370e53eb8.tar.gz
add more error checking in chn_init() and chn_reset()
-rw-r--r--sys/dev/sound/pcm/channel.c91
1 files changed, 61 insertions, 30 deletions
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 0c73dd0..5a8fb1c 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -632,30 +632,33 @@ fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
int
chn_reset(struct pcm_channel *c, u_int32_t fmt)
{
- int hwspd, r = 0;
+ int hwspd, r;
CHN_LOCKASSERT(c);
c->flags &= CHN_F_RESET;
c->interrupts = 0;
c->xruns = 0;
- CHANNEL_RESET(c->methods, c->devinfo);
- if (fmt) {
+
+ r = CHANNEL_RESET(c->methods, c->devinfo);
+ if (fmt != 0) {
hwspd = DSP_DEFAULT_SPEED;
/* only do this on a record channel until feederbuilder works */
if (c->direction == PCMDIR_REC)
RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
c->speed = hwspd;
- r = chn_setformat(c, fmt);
+ if (r == 0)
+ r = chn_setformat(c, fmt);
if (r == 0)
r = chn_setspeed(c, hwspd);
if (r == 0)
r = chn_setvolume(c, 100, 100);
}
- r = chn_setblocksize(c, 0, 0);
+ if (r == 0)
+ r = chn_setblocksize(c, 0, 0);
if (r == 0) {
chn_resetbuf(c);
- CHANNEL_RESETDONE(c->methods, c->devinfo);
+ r = CHANNEL_RESETDONE(c->methods, c->devinfo);
}
return r;
}
@@ -665,46 +668,74 @@ chn_init(struct pcm_channel *c, void *devinfo, int dir)
{
struct feeder_class *fc;
struct snd_dbuf *b, *bs;
+ int ret;
chn_lockinit(c);
CHN_LOCK(c);
+ b = NULL;
+ bs = NULL;
+ c->devinfo = NULL;
c->feeder = NULL;
+
+ ret = EINVAL;
fc = feeder_getclass(NULL);
if (fc == NULL)
- return EINVAL;
+ goto out;
if (chn_addfeeder(c, fc, NULL))
- return EINVAL;
+ goto out;
+ ret = ENOMEM;
b = sndbuf_create(c->name, "primary");
if (b == NULL)
- return ENOMEM;
+ goto out;
bs = sndbuf_create(c->name, "secondary");
- if (bs == NULL) {
- sndbuf_destroy(b);
- return ENOMEM;
- }
+ if (bs == NULL)
+ goto out;
sndbuf_setup(bs, NULL, 0);
c->bufhard = b;
c->bufsoft = bs;
c->flags = 0;
c->feederflags = 0;
+
+ ret = ENODEV;
c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, dir);
- if (c->devinfo == NULL) {
- sndbuf_destroy(bs);
- sndbuf_destroy(b);
- return ENODEV;
- }
- if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0)) {
- sndbuf_destroy(bs);
- sndbuf_destroy(b);
- return ENOMEM;
+ if (c->devinfo == NULL)
+ goto out;
+
+ ret = ENOMEM;
+ if ((sndbuf_getsize(b) == 0) && ((c->flags & CHN_F_VIRTUAL) == 0))
+ goto out;
+
+ ret = chn_setdir(c, dir);
+ if (ret)
+ goto out;
+
+ ret = sndbuf_setfmt(b, AFMT_U8);
+ if (ret)
+ goto out;
+
+ ret = sndbuf_setfmt(bs, AFMT_U8);
+ if (ret)
+ goto out;
+
+
+out:
+ if (ret) {
+ if (c->devinfo) {
+ if (CHANNEL_FREE(c->methods, c->devinfo))
+ sndbuf_free(b);
+ }
+ if (bs)
+ sndbuf_destroy(bs);
+ if (b)
+ sndbuf_destroy(b);
+ c->flags |= CHN_F_DEAD;
+ chn_lockdestroy(c);
+
+ return ret;
}
- chn_setdir(c, dir);
- /* And the secondary buffer. */
- sndbuf_setfmt(b, AFMT_U8);
- sndbuf_setfmt(bs, AFMT_U8);
CHN_UNLOCK(c);
return 0;
}
@@ -841,11 +872,11 @@ chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
c->format = fmt;
r = chn_buildfeeder(c);
if (r == 0) {
- sndbuf_setfmt(b, c->feeder->desc->out);
- sndbuf_setfmt(bs, fmt);
+ sndbuf_setfmt(bs, c->format);
chn_resetbuf(c);
- CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
- r = chn_tryspeed(c, c->speed);
+ r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
+ if (r == 0)
+ r = chn_tryspeed(c, c->speed);
}
return r;
} else
OpenPOWER on IntegriCloud