* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * Author: Bill Dirks <bdirks@pacbell.net>
+ * Author: Bill Dirks <bill@thedirks.org>
* et al.
*
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
-#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/videodev.h>
+#include <media/v4l2-common.h>
#include <asm/uaccess.h>
#include <asm/system.h>
/* ----------------------------------------------------------------- */
-static int palette2pixelformat[] = {
+const static unsigned int palette2pixelformat[] = {
[VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY,
[VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555,
[VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565,
[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
};
-static unsigned int
+static unsigned int __pure
palette_to_pixelformat(unsigned int palette)
{
if (palette < ARRAY_SIZE(palette2pixelformat))
return 0;
}
-static unsigned int
-pixelformat_to_palette(int pixelformat)
+static unsigned int __attribute_const__
+pixelformat_to_palette(unsigned int pixelformat)
{
int palette = 0;
switch (pixelformat)
{
struct video_capability *cap = arg;
- cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
+ cap2 = kzalloc(sizeof(*cap2), GFP_KERNEL);
+ if (!cap2) {
+ err = -ENOMEM;
+ break;
+ }
memset(cap, 0, sizeof(*cap));
- memset(cap2, 0, sizeof(*cap2));
memset(&fbuf2, 0, sizeof(fbuf2));
err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
{
struct video_buffer *buffer = arg;
+ memset(buffer, 0, sizeof(*buffer));
+ memset(&fbuf2, 0, sizeof(fbuf2));
+
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
if (err < 0) {
dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
switch (fbuf2.fmt.pixelformat) {
case V4L2_PIX_FMT_RGB332:
buffer->depth = 8;
- break;
+ break;
case V4L2_PIX_FMT_RGB555:
buffer->depth = 15;
break;
default:
buffer->depth = 0;
}
- if (0 != fbuf2.fmt.bytesperline)
+ if (fbuf2.fmt.bytesperline) {
buffer->bytesperline = fbuf2.fmt.bytesperline;
- else {
+ if (!buffer->depth && buffer->width)
+ buffer->depth = ((fbuf2.fmt.bytesperline<<3)
+ + (buffer->width-1) )
+ /buffer->width;
+ } else {
buffer->bytesperline =
(buffer->width * buffer->depth + 7) & 7;
buffer->bytesperline >>= 3;
{
struct video_window *win = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
memset(win,0,sizeof(*win));
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
struct video_window *win = arg;
int err1,err2;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
{
struct video_picture *pict = arg;
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
+
pict->brightness = get_v4l_control(inode, file,
V4L2_CID_BRIGHTNESS,drv);
pict->hue = get_v4l_control(inode, file,
pict->whiteness = get_v4l_control(inode, file,
V4L2_CID_WHITENESS, drv);
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
if (err < 0) {
dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
break;
}
+
+ pict->depth = ((fmt2->fmt.pix.bytesperline<<3)
+ + (fmt2->fmt.pix.width-1) )
+ /fmt2->fmt.pix.width;
pict->palette = pixelformat_to_palette(
fmt2->fmt.pix.pixelformat);
break;
case VIDIOCSPICT: /* set tone controls & partial capture format */
{
struct video_picture *pict = arg;
+ int mem_err = 0, ovl_err = 0;
+
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
+ memset(&fbuf2, 0, sizeof(fbuf2));
set_v4l_control(inode, file,
V4L2_CID_BRIGHTNESS, pict->brightness, drv);
V4L2_CID_SATURATION, pict->colour, drv);
set_v4l_control(inode, file,
V4L2_CID_WHITENESS, pict->whiteness, drv);
+ /*
+ * V4L1 uses this ioctl to set both memory capture and overlay
+ * pixel format, while V4L2 has two different ioctls for this.
+ * Some cards may not support one or the other, and may support
+ * different pixel formats for memory vs overlay.
+ */
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0)
+ /* If VIDIOC_G_FMT failed, then the driver likely doesn't
+ support memory capture. Trying to set the memory capture
+ parameters would be pointless. */
+ if (err < 0) {
dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
- if (fmt2->fmt.pix.pixelformat !=
- palette_to_pixelformat(pict->palette)) {
+ mem_err = -1000; /* didn't even try */
+ } else if (fmt2->fmt.pix.pixelformat !=
+ palette_to_pixelformat(pict->palette)) {
fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
pict->palette);
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
- if (err < 0)
- dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
+ mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
+ if (mem_err < 0)
+ dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
+ mem_err);
}
err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
- if (err < 0)
+ /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
+ support overlay. Trying to set the overlay parameters
+ would be quite pointless. */
+ if (err < 0) {
dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
- if (fbuf2.fmt.pixelformat !=
- palette_to_pixelformat(pict->palette)) {
+ ovl_err = -1000; /* didn't even try */
+ } else if (fbuf2.fmt.pixelformat !=
+ palette_to_pixelformat(pict->palette)) {
fbuf2.fmt.pixelformat = palette_to_pixelformat(
pict->palette);
- err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
- if (err < 0)
- dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
- err = 0; /* likely fails for non-root */
+ ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
+ if (ovl_err < 0)
+ dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
+ ovl_err);
}
+ if (ovl_err < 0 && mem_err < 0)
+ /* ioctl failed, couldn't set either parameter */
+ if (mem_err != -1000) {
+ err = mem_err;
+ } else if (ovl_err == -EPERM) {
+ err = 0;
+ } else {
+ err = ovl_err;
+ }
+ else
+ err = 0;
break;
}
case VIDIOCGTUNER: /* get tuner information */
}
case VIDIOCSTUNER: /* select a tuner input */
{
- err = 0;
+ struct video_tuner *tun = arg;
+ struct v4l2_tuner t;
+ memset(&t,0,sizeof(t));
+
+ t.index=tun->tuner;
+
+ err = drv(inode, file, VIDIOC_S_INPUT, &t);
+ if (err < 0)
+ dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
+
break;
}
case VIDIOCGFREQ: /* get frequency */
{
unsigned long *freq = arg;
+ memset(&freq2,0,sizeof(freq2));
freq2.tuner = 0;
err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
case VIDIOCSFREQ: /* set frequency */
{
unsigned long *freq = arg;
+ memset(&freq2,0,sizeof(freq2));
- freq2.tuner = 0;
drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
freq2.frequency = *freq;
err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
case VIDIOCGAUDIO: /* get audio properties/controls */
{
struct video_audio *aud = arg;
+ memset(&aud2,0,sizeof(aud2));
err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
if (err < 0) {
{
struct video_mmap *mm = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
memset(&buf2,0,sizeof(buf2));
- memset(fmt2,0,sizeof(*fmt2));
fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
{
int *i = arg;
+ memset(&buf2,0,sizeof(buf2));
buf2.index = *i;
buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
{
struct vbi_format *fmt = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2, 0, sizeof(*fmt2));
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
err = drv(inode, file, VIDIOC_G_FMT, fmt2);
dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
break;
}
+ if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
+ err = -EINVAL;
+ break;
+ }
memset(fmt, 0, sizeof(*fmt));
fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
fmt->start[1] = fmt2->fmt.vbi.start[1];
fmt->count[1] = fmt2->fmt.vbi.count[1];
fmt->flags = fmt2->fmt.vbi.flags & 0x03;
- break;
+ break;
}
case VIDIOCSVBIFMT:
{
struct vbi_format *fmt = arg;
- fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(fmt2, 0, sizeof(*fmt2));
+ if (VIDEO_PALETTE_RAW != fmt->sample_format) {
+ err = -EINVAL;
+ break;
+ }
+ fmt2 = kzalloc(sizeof(*fmt2), GFP_KERNEL);
+ if (!fmt2) {
+ err = -ENOMEM;
+ break;
+ }
fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate;
if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
- VIDEO_PALETTE_RAW != fmt->sample_format ||
+ fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
fmt2->fmt.vbi.start[0] != fmt->start[0] ||
fmt2->fmt.vbi.count[0] != fmt->count[0] ||
fmt2->fmt.vbi.start[1] != fmt->start[1] ||