V4L/DVB (8773): cx18: Fix cx18_find_handle() and add error checking
cx18: Fix cx18_find_handle() and add error checking. cx18_find_handle() did not find a good task handle and would use the invalid task handle under common conditions. Added a define for the invalid task handle and added error checking as well. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
b04bce476c
commit
d3c5e70755
@@ -236,6 +236,8 @@ struct cx18_dvb {
|
|||||||
struct cx18; /* forward reference */
|
struct cx18; /* forward reference */
|
||||||
struct cx18_scb; /* forward reference */
|
struct cx18_scb; /* forward reference */
|
||||||
|
|
||||||
|
#define CX18_INVALID_TASK_HANDLE 0xffffffff
|
||||||
|
|
||||||
struct cx18_stream {
|
struct cx18_stream {
|
||||||
/* These first four fields are always set, even if the stream
|
/* These first four fields are always set, even if the stream
|
||||||
is not actually created. */
|
is not actually created. */
|
||||||
|
@@ -132,6 +132,7 @@ static void cx18_dualwatch(struct cx18 *cx)
|
|||||||
u16 new_stereo_mode;
|
u16 new_stereo_mode;
|
||||||
const u16 stereo_mask = 0x0300;
|
const u16 stereo_mask = 0x0300;
|
||||||
const u16 dual = 0x0200;
|
const u16 dual = 0x0200;
|
||||||
|
u32 h;
|
||||||
|
|
||||||
new_stereo_mode = cx->params.audio_properties & stereo_mask;
|
new_stereo_mode = cx->params.audio_properties & stereo_mask;
|
||||||
memset(&vt, 0, sizeof(vt));
|
memset(&vt, 0, sizeof(vt));
|
||||||
@@ -143,13 +144,21 @@ static void cx18_dualwatch(struct cx18 *cx)
|
|||||||
if (new_stereo_mode == cx->dualwatch_stereo_mode)
|
if (new_stereo_mode == cx->dualwatch_stereo_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
new_bitmap = new_stereo_mode | (cx->params.audio_properties & ~stereo_mask);
|
new_bitmap = new_stereo_mode
|
||||||
|
| (cx->params.audio_properties & ~stereo_mask);
|
||||||
|
|
||||||
CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. new audio_bitmask=0x%ux\n",
|
CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
|
||||||
cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
|
"new audio_bitmask=0x%ux\n",
|
||||||
|
cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
|
||||||
|
|
||||||
if (cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
|
h = cx18_find_handle(cx);
|
||||||
cx18_find_handle(cx), new_bitmap) == 0) {
|
if (h == CX18_INVALID_TASK_HANDLE) {
|
||||||
|
CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cx18_vapi(cx,
|
||||||
|
CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
|
||||||
cx->dualwatch_stereo_mode = new_stereo_mode;
|
cx->dualwatch_stereo_mode = new_stereo_mode;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -695,20 +704,28 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp)
|
|||||||
|
|
||||||
void cx18_mute(struct cx18 *cx)
|
void cx18_mute(struct cx18 *cx)
|
||||||
{
|
{
|
||||||
if (atomic_read(&cx->ana_capturing))
|
u32 h;
|
||||||
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
|
if (atomic_read(&cx->ana_capturing)) {
|
||||||
cx18_find_handle(cx), 1);
|
h = cx18_find_handle(cx);
|
||||||
|
if (h != CX18_INVALID_TASK_HANDLE)
|
||||||
|
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
|
||||||
|
else
|
||||||
|
CX18_ERR("Can't find valid task handle for mute\n");
|
||||||
|
}
|
||||||
CX18_DEBUG_INFO("Mute\n");
|
CX18_DEBUG_INFO("Mute\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cx18_unmute(struct cx18 *cx)
|
void cx18_unmute(struct cx18 *cx)
|
||||||
{
|
{
|
||||||
|
u32 h;
|
||||||
if (atomic_read(&cx->ana_capturing)) {
|
if (atomic_read(&cx->ana_capturing)) {
|
||||||
cx18_msleep_timeout(100, 0);
|
h = cx18_find_handle(cx);
|
||||||
cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
|
if (h != CX18_INVALID_TASK_HANDLE) {
|
||||||
cx18_find_handle(cx), 12);
|
cx18_msleep_timeout(100, 0);
|
||||||
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
|
cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
|
||||||
cx18_find_handle(cx), 0);
|
cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
|
||||||
|
} else
|
||||||
|
CX18_ERR("Can't find valid task handle for unmute\n");
|
||||||
}
|
}
|
||||||
CX18_DEBUG_INFO("Unmute\n");
|
CX18_DEBUG_INFO("Unmute\n");
|
||||||
}
|
}
|
||||||
|
@@ -622,6 +622,7 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
|
|||||||
{
|
{
|
||||||
struct cx18_open_id *id = fh;
|
struct cx18_open_id *id = fh;
|
||||||
struct cx18 *cx = id->cx;
|
struct cx18 *cx = id->cx;
|
||||||
|
u32 h;
|
||||||
|
|
||||||
switch (enc->cmd) {
|
switch (enc->cmd) {
|
||||||
case V4L2_ENC_CMD_START:
|
case V4L2_ENC_CMD_START:
|
||||||
@@ -643,8 +644,14 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
|
if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
h = cx18_find_handle(cx);
|
||||||
|
if (h == CX18_INVALID_TASK_HANDLE) {
|
||||||
|
CX18_ERR("Can't find valid task handle for "
|
||||||
|
"V4L2_ENC_CMD_PAUSE\n");
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
cx18_mute(cx);
|
cx18_mute(cx);
|
||||||
cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, cx18_find_handle(cx));
|
cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V4L2_ENC_CMD_RESUME:
|
case V4L2_ENC_CMD_RESUME:
|
||||||
@@ -654,7 +661,13 @@ static int cx18_encoder_cmd(struct file *file, void *fh,
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
|
if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
|
||||||
return 0;
|
return 0;
|
||||||
cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, cx18_find_handle(cx));
|
h = cx18_find_handle(cx);
|
||||||
|
if (h == CX18_INVALID_TASK_HANDLE) {
|
||||||
|
CX18_ERR("Can't find valid task handle for "
|
||||||
|
"V4L2_ENC_CMD_RESUME\n");
|
||||||
|
return -EBADFD;
|
||||||
|
}
|
||||||
|
cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
|
||||||
cx18_unmute(cx);
|
cx18_unmute(cx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
|
|||||||
s->cx = cx;
|
s->cx = cx;
|
||||||
s->type = type;
|
s->type = type;
|
||||||
s->name = cx18_stream_info[type].name;
|
s->name = cx18_stream_info[type].name;
|
||||||
s->handle = 0xffffffff;
|
s->handle = CX18_INVALID_TASK_HANDLE;
|
||||||
|
|
||||||
s->dma = cx18_stream_info[type].dma;
|
s->dma = cx18_stream_info[type].dma;
|
||||||
s->buf_size = cx->stream_buf_size[type];
|
s->buf_size = cx->stream_buf_size[type];
|
||||||
@@ -548,7 +548,7 @@ int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
|
|||||||
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
|
clear_bit(CX18_F_S_STREAMING, &s->s_flags);
|
||||||
|
|
||||||
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
|
cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
|
||||||
s->handle = 0xffffffff;
|
s->handle = CX18_INVALID_TASK_HANDLE;
|
||||||
|
|
||||||
if (atomic_read(&cx->tot_capturing) > 0)
|
if (atomic_read(&cx->tot_capturing) > 0)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -567,8 +567,8 @@ u32 cx18_find_handle(struct cx18 *cx)
|
|||||||
for (i = 0; i < CX18_MAX_STREAMS; i++) {
|
for (i = 0; i < CX18_MAX_STREAMS; i++) {
|
||||||
struct cx18_stream *s = &cx->streams[i];
|
struct cx18_stream *s = &cx->streams[i];
|
||||||
|
|
||||||
if (s->v4l2dev && s->handle)
|
if (s->v4l2dev && (s->handle != CX18_INVALID_TASK_HANDLE))
|
||||||
return s->handle;
|
return s->handle;
|
||||||
}
|
}
|
||||||
return 0;
|
return CX18_INVALID_TASK_HANDLE;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user