#include <linux/videodev2.h>
#include <linux/i2c.h>
-#include <media/saa7115.h>
+#include <media/i2c/saa7115.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h>
static inline struct usb_usbvision *cd_to_usbvision(struct device *cd)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
return video_get_drvdata(vdev);
}
static ssize_t show_model(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
return sprintf(buf, "%s\n",
usbvision_device_data[usbvision->dev_model].model_string);
static ssize_t show_hue(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_HUE;
static ssize_t show_contrast(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_CONTRAST;
static ssize_t show_brightness(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_BRIGHTNESS;
static ssize_t show_saturation(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
struct v4l2_control ctrl;
ctrl.id = V4L2_CID_SATURATION;
static ssize_t show_streaming(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
return sprintf(buf, "%s\n",
YES_NO(usbvision->streaming == stream_on ? 1 : 0));
static ssize_t show_compression(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
return sprintf(buf, "%s\n",
YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS));
static ssize_t show_device_bridge(struct device *cd,
struct device_attribute *attr, char *buf)
{
- struct video_device *vdev =
- container_of(cd, struct video_device, dev);
+ struct video_device *vdev = to_video_device(cd);
struct usb_usbvision *usbvision = video_get_drvdata(vdev);
return sprintf(buf, "%d\n", usbvision->bridge_type);
}
usbvision_audio_off(usbvision);
usbvision->radio = 0;
usbvision->user--;
+ mutex_unlock(&usbvision->v4l2_lock);
if (usbvision->remove_pending) {
printk(KERN_INFO "%s: Final disconnect\n", __func__);
return 0;
}
- mutex_unlock(&usbvision->v4l2_lock);
PDEBUG(DBG_IO, "success");
return v4l2_fh_release(file);
}
printk(KERN_INFO "%s: %s found\n", __func__,
usbvision_device_data[model].model_string);
+ /*
+ * this is a security check.
+ * an exploit using an incorrect bInterfaceNumber is known
+ */
+ if (ifnum >= USB_MAXINTERFACES || !dev->actconfig->interface[ifnum])
+ return -ENODEV;
+
if (usbvision_device_data[model].interface >= 0)
interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
- else
+ else if (ifnum < dev->actconfig->desc.bNumInterfaces)
interface = &dev->actconfig->interface[ifnum]->altsetting[0];
+ else {
+ dev_err(&intf->dev, "interface %d is invalid, max is %d\n",
+ ifnum, dev->actconfig->desc.bNumInterfaces - 1);
+ ret = -ENODEV;
+ goto err_usb;
+ }
+
+ if (interface->desc.bNumEndpoints < 2) {
+ dev_err(&intf->dev, "interface %d has %d endpoints, but must"
+ " have minimum 2\n", ifnum, interface->desc.bNumEndpoints);
+ ret = -ENODEV;
+ goto err_usb;
+ }
endpoint = &interface->endpoint[1].desc;
+
if (!usb_endpoint_xfer_isoc(endpoint)) {
dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
__func__, ifnum);