mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
add more error checking in chn_init() and chn_reset()
This commit is contained in:
parent
79e6a82b48
commit
1e59d53c22
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=89687
@ -632,30 +632,33 @@ fmtvalid(u_int32_t fmt, u_int32_t *fmtlist)
|
|||||||
int
|
int
|
||||||
chn_reset(struct pcm_channel *c, u_int32_t fmt)
|
chn_reset(struct pcm_channel *c, u_int32_t fmt)
|
||||||
{
|
{
|
||||||
int hwspd, r = 0;
|
int hwspd, r;
|
||||||
|
|
||||||
CHN_LOCKASSERT(c);
|
CHN_LOCKASSERT(c);
|
||||||
c->flags &= CHN_F_RESET;
|
c->flags &= CHN_F_RESET;
|
||||||
c->interrupts = 0;
|
c->interrupts = 0;
|
||||||
c->xruns = 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;
|
hwspd = DSP_DEFAULT_SPEED;
|
||||||
/* only do this on a record channel until feederbuilder works */
|
/* only do this on a record channel until feederbuilder works */
|
||||||
if (c->direction == PCMDIR_REC)
|
if (c->direction == PCMDIR_REC)
|
||||||
RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
|
RANGE(hwspd, chn_getcaps(c)->minspeed, chn_getcaps(c)->maxspeed);
|
||||||
c->speed = hwspd;
|
c->speed = hwspd;
|
||||||
|
|
||||||
r = chn_setformat(c, fmt);
|
if (r == 0)
|
||||||
|
r = chn_setformat(c, fmt);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = chn_setspeed(c, hwspd);
|
r = chn_setspeed(c, hwspd);
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = chn_setvolume(c, 100, 100);
|
r = chn_setvolume(c, 100, 100);
|
||||||
}
|
}
|
||||||
r = chn_setblocksize(c, 0, 0);
|
if (r == 0)
|
||||||
|
r = chn_setblocksize(c, 0, 0);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
chn_resetbuf(c);
|
chn_resetbuf(c);
|
||||||
CHANNEL_RESETDONE(c->methods, c->devinfo);
|
r = CHANNEL_RESETDONE(c->methods, c->devinfo);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -665,46 +668,74 @@ chn_init(struct pcm_channel *c, void *devinfo, int dir)
|
|||||||
{
|
{
|
||||||
struct feeder_class *fc;
|
struct feeder_class *fc;
|
||||||
struct snd_dbuf *b, *bs;
|
struct snd_dbuf *b, *bs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
chn_lockinit(c);
|
chn_lockinit(c);
|
||||||
CHN_LOCK(c);
|
CHN_LOCK(c);
|
||||||
|
|
||||||
|
b = NULL;
|
||||||
|
bs = NULL;
|
||||||
|
c->devinfo = NULL;
|
||||||
c->feeder = NULL;
|
c->feeder = NULL;
|
||||||
|
|
||||||
|
ret = EINVAL;
|
||||||
fc = feeder_getclass(NULL);
|
fc = feeder_getclass(NULL);
|
||||||
if (fc == NULL)
|
if (fc == NULL)
|
||||||
return EINVAL;
|
goto out;
|
||||||
if (chn_addfeeder(c, fc, NULL))
|
if (chn_addfeeder(c, fc, NULL))
|
||||||
return EINVAL;
|
goto out;
|
||||||
|
|
||||||
|
ret = ENOMEM;
|
||||||
b = sndbuf_create(c->name, "primary");
|
b = sndbuf_create(c->name, "primary");
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
return ENOMEM;
|
goto out;
|
||||||
bs = sndbuf_create(c->name, "secondary");
|
bs = sndbuf_create(c->name, "secondary");
|
||||||
if (bs == NULL) {
|
if (bs == NULL)
|
||||||
sndbuf_destroy(b);
|
goto out;
|
||||||
return ENOMEM;
|
|
||||||
}
|
|
||||||
sndbuf_setup(bs, NULL, 0);
|
sndbuf_setup(bs, NULL, 0);
|
||||||
c->bufhard = b;
|
c->bufhard = b;
|
||||||
c->bufsoft = bs;
|
c->bufsoft = bs;
|
||||||
c->flags = 0;
|
c->flags = 0;
|
||||||
c->feederflags = 0;
|
c->feederflags = 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
chn_setdir(c, dir);
|
|
||||||
|
|
||||||
/* And the secondary buffer. */
|
ret = ENODEV;
|
||||||
sndbuf_setfmt(b, AFMT_U8);
|
c->devinfo = CHANNEL_INIT(c->methods, devinfo, b, c, dir);
|
||||||
sndbuf_setfmt(bs, AFMT_U8);
|
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_UNLOCK(c);
|
CHN_UNLOCK(c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -841,11 +872,11 @@ chn_tryformat(struct pcm_channel *c, u_int32_t fmt)
|
|||||||
c->format = fmt;
|
c->format = fmt;
|
||||||
r = chn_buildfeeder(c);
|
r = chn_buildfeeder(c);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
sndbuf_setfmt(b, c->feeder->desc->out);
|
sndbuf_setfmt(bs, c->format);
|
||||||
sndbuf_setfmt(bs, fmt);
|
|
||||||
chn_resetbuf(c);
|
chn_resetbuf(c);
|
||||||
CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
|
r = CHANNEL_SETFORMAT(c->methods, c->devinfo, sndbuf_getfmt(b));
|
||||||
r = chn_tryspeed(c, c->speed);
|
if (r == 0)
|
||||||
|
r = chn_tryspeed(c, c->speed);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
} else
|
} else
|
||||||
|
Loading…
Reference in New Issue
Block a user