提交 5f454d82 编写于 作者: H Hans Verkuil 提交者: Mauro Carvalho Chehab

[media] hdpvr: improve error handling

get_video_info() should never return EFAULT, instead it should return
the low-level usb_control_msg() error. Add a valid field to the hdpvr_video_info
struct so the driver can easily check if a valid format was detected.
Whenever get_video_info is called and it returns an error (e.g. usb_control_msg
failed), then return that error to userspace as well.
Signed-off-by: NHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 79f10b62
...@@ -49,6 +49,7 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) ...@@ -49,6 +49,7 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf)
{ {
int ret; int ret;
vidinf->valid = false;
mutex_lock(&dev->usbc_mutex); mutex_lock(&dev->usbc_mutex);
ret = usb_control_msg(dev->udev, ret = usb_control_msg(dev->udev,
usb_rcvctrlpipe(dev->udev, 0), usb_rcvctrlpipe(dev->udev, 0),
...@@ -56,11 +57,6 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) ...@@ -56,11 +57,6 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf)
0x1400, 0x0003, 0x1400, 0x0003,
dev->usbc_buf, 5, dev->usbc_buf, 5,
1000); 1000);
if (ret == 5) {
vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
vidinf->fps = dev->usbc_buf[4];
}
#ifdef HDPVR_DEBUG #ifdef HDPVR_DEBUG
if (hdpvr_debug & MSG_INFO) { if (hdpvr_debug & MSG_INFO) {
...@@ -73,14 +69,15 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf) ...@@ -73,14 +69,15 @@ int get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vidinf)
#endif #endif
mutex_unlock(&dev->usbc_mutex); mutex_unlock(&dev->usbc_mutex);
if ((ret > 0 && ret != 5) ||/* fail if unexpected byte count returned */ if (ret < 0)
!vidinf->width || /* preserve original behavior - */ return ret;
!vidinf->height || /* fail if no signal is detected */
!vidinf->fps) {
ret = -EFAULT;
}
return ret < 0 ? ret : 0; vidinf->width = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
vidinf->height = dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
vidinf->fps = dev->usbc_buf[4];
vidinf->valid = vidinf->width && vidinf->height && vidinf->fps;
return 0;
} }
int get_input_lines_info(struct hdpvr_device *dev) int get_input_lines_info(struct hdpvr_device *dev)
......
...@@ -285,7 +285,10 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) ...@@ -285,7 +285,10 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev)
return -EAGAIN; return -EAGAIN;
ret = get_video_info(dev, &vidinf); ret = get_video_info(dev, &vidinf);
if (ret) { if (ret < 0)
return ret;
if (!vidinf.valid) {
msleep(250); msleep(250);
v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
"no video signal at input %d\n", dev->options.video_input); "no video signal at input %d\n", dev->options.video_input);
...@@ -617,15 +620,12 @@ static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a) ...@@ -617,15 +620,12 @@ static int vidioc_querystd(struct file *file, void *_fh, v4l2_std_id *a)
if (dev->options.video_input == HDPVR_COMPONENT) if (dev->options.video_input == HDPVR_COMPONENT)
return fh->legacy_mode ? 0 : -ENODATA; return fh->legacy_mode ? 0 : -ENODATA;
ret = get_video_info(dev, &vid_info); ret = get_video_info(dev, &vid_info);
if (ret) if (vid_info.valid && vid_info.width == 720 &&
return 0;
if (vid_info.width == 720 &&
(vid_info.height == 480 || vid_info.height == 576)) { (vid_info.height == 480 || vid_info.height == 576)) {
*a = (vid_info.height == 480) ? *a = (vid_info.height == 480) ?
V4L2_STD_525_60 : V4L2_STD_625_50; V4L2_STD_525_60 : V4L2_STD_625_50;
} }
return ret;
return 0;
} }
static int vidioc_s_dv_timings(struct file *file, void *_fh, static int vidioc_s_dv_timings(struct file *file, void *_fh,
...@@ -679,6 +679,8 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh, ...@@ -679,6 +679,8 @@ static int vidioc_query_dv_timings(struct file *file, void *_fh,
return -ENODATA; return -ENODATA;
ret = get_video_info(dev, &vid_info); ret = get_video_info(dev, &vid_info);
if (ret) if (ret)
return ret;
if (!vid_info.valid)
return -ENOLCK; return -ENOLCK;
interlaced = vid_info.fps <= 30; interlaced = vid_info.fps <= 30;
for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) { for (i = 0; i < ARRAY_SIZE(hdpvr_dv_timings); i++) {
...@@ -1008,7 +1010,9 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh, ...@@ -1008,7 +1010,9 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
struct hdpvr_video_info vid_info; struct hdpvr_video_info vid_info;
ret = get_video_info(dev, &vid_info); ret = get_video_info(dev, &vid_info);
if (ret) if (ret < 0)
return ret;
if (!vid_info.valid)
return -EFAULT; return -EFAULT;
f->fmt.pix.width = vid_info.width; f->fmt.pix.width = vid_info.width;
f->fmt.pix.height = vid_info.height; f->fmt.pix.height = vid_info.height;
......
...@@ -154,6 +154,7 @@ struct hdpvr_video_info { ...@@ -154,6 +154,7 @@ struct hdpvr_video_info {
u16 width; u16 width;
u16 height; u16 height;
u8 fps; u8 fps;
bool valid;
}; };
enum { enum {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册