struct video_capability *cap = arg; 
struct video_capability *cap = arg; 
static int bttv_do_ioctl(struct inode *inode, struct file *file,			 unsigned int cmd, void *arg){	struct bttv_fh *fh  = file->private_data;	struct bttv    *btv = fh->btv;	unsigned long flags;	int retval = 0;	if (bttv_debug > 1) {		switch (_IOC_TYPE(cmd)) {		case 'v':			printk("bttv%d: ioctl 0x%x (v4l1, VIDIOC%s)\n",			       btv->c.nr, cmd, (_IOC_NR(cmd) < V4L1_IOCTLS) ?			       v4l1_ioctls[_IOC_NR(cmd)] : "???");			break;		case 'V':			printk("bttv%d: ioctl 0x%x (v4l2, %s)\n",			       btv->c.nr, cmd,  v4l2_ioctl_names[_IOC_NR(cmd)]);			break;		default:			printk("bttv%d: ioctl 0x%x (???)\n",			       btv->c.nr, cmd);		}	}	if (btv->errors)		bttv_reinit_bt848(btv);	switch (cmd) {        case VIDIOCSFREQ:        case VIDIOCSTUNER:        case VIDIOCSCHAN:	case VIDIOC_S_CTRL:	case VIDIOC_S_STD:	case VIDIOC_S_INPUT:	case VIDIOC_S_TUNER:	case VIDIOC_S_FREQUENCY:		retval = v4l2_prio_check(&btv->prio,&fh->prio);		if (0 != retval)			return retval;	};	switch (cmd) {	/* ***  v4l1  *** ************************************************ */	case VIDIOCGCAP:	{                struct video_capability *cap = arg;		memset(cap,0,sizeof(*cap));                strcpy(cap->name,btv->video_dev->name);		if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {			/* vbi */			cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT;		} else {			/* others */			cap->type = VID_TYPE_CAPTURE|				VID_TYPE_TUNER|				VID_TYPE_CLIPPING|				VID_TYPE_SCALES;			if (no_overlay <= 0)				cap->type |= VID_TYPE_OVERLAY;			cap->maxwidth  = bttv_tvnorms[btv->tvnorm].swidth;			cap->maxheight = bttv_tvnorms[btv->tvnorm].sheight;			cap->minwidth  = 48;			cap->minheight = 32;		}		cap->channels  = bttv_tvcards[btv->c.type].video_inputs;		cap->audios    = bttv_tvcards[btv->c.type].audio_inputs;                return 0;	}	case VIDIOCGPICT:	{		struct video_picture *pic = arg;		memset(pic,0,sizeof(*pic));		pic->brightness = btv->bright;		pic->contrast   = btv->contrast;		pic->hue        = btv->hue;		pic->colour     = btv->saturation;		if (fh->fmt) {			pic->depth   = fh->fmt->depth;			pic->palette = fh->fmt->palette;		}		return 0;	}	case VIDIOCSPICT:	{		struct video_picture *pic = arg;		const struct bttv_format *fmt;		fmt = format_by_palette(pic->palette);		if (NULL == fmt)			return -EINVAL;		down(&fh->cap.lock);		if (fmt->depth != pic->depth) {			retval = -EINVAL;			goto fh_unlock_and_return;		}		fh->ovfmt   = fmt;		fh->fmt     = fmt;		btv->init.ovfmt   = fmt;		btv->init.fmt     = fmt;		if (bigendian) {			/* dirty hack time:  swap bytes for overlay if the			   display adaptor is big endian (insmod option) */			if (fmt->palette == VIDEO_PALETTE_RGB555 ||			    fmt->palette == VIDEO_PALETTE_RGB565 ||			    fmt->palette == VIDEO_PALETTE_RGB32) {				fh->ovfmt = fmt+1;			}		}		bt848_bright(btv,pic->brightness);		bt848_contrast(btv,pic->contrast);		bt848_hue(btv,pic->hue);		bt848_sat(btv,pic->colour);		up(&fh->cap.lock);                return 0;	}	case VIDIOCGWIN:	{		struct video_window *win = arg;		memset(win,0,sizeof(*win));		win->x      = fh->ov.w.left;		win->y      = fh->ov.w.top;		win->width  = fh->ov.w.width;		win->height = fh->ov.w.height;		return 0;	}	case VIDIOCSWIN:	{		struct video_window *win = arg;		struct v4l2_window w2;		if (no_overlay > 0) {			printk ("VIDIOCSWIN: no_overlay\n");			return -EINVAL;		}		w2.field = V4L2_FIELD_ANY;		w2.w.left    = win->x;		w2.w.top     = win->y;		w2.w.width   = win->width;		w2.w.height  = win->height;		w2.clipcount = win->clipcount;		w2.clips     = (struct v4l2_clip __user *)win->clips;		retval = setup_window(fh, btv, &w2, 0);		if (0 == retval) {			/* on v4l1 this ioctl affects the read() size too */			fh->width  = fh->ov.w.width;			fh->height = fh->ov.w.height;			btv->init.width  = fh->ov.w.width;			btv->init.height = fh->ov.w.height;		}		return retval;	}	case VIDIOCGFBUF:	{		struct video_buffer *fbuf = arg;		fbuf->base          = btv->fbuf.base;		fbuf->width         = btv->fbuf.fmt.width;		fbuf->height        = btv->fbuf.fmt.height;		fbuf->bytesperline  = btv->fbuf.fmt.bytesperline;		if (fh->ovfmt)			fbuf->depth = fh->ovfmt->depth;		return 0;	}	case VIDIOCSFBUF:	{		struct video_buffer *fbuf = arg;		const struct bttv_format *fmt;		unsigned long end;		if(!capable(CAP_SYS_ADMIN) &&                   !capable(CAP_SYS_RAWIO))                        return -EPERM;		end = (unsigned long)fbuf->base +			fbuf->height * fbuf->bytesperline;		down(&fh->cap.lock);		retval = -EINVAL;		switch (fbuf->depth) {		case 8:			fmt = format_by_palette(VIDEO_PALETTE_HI240);			break;		case 16:			fmt = format_by_palette(VIDEO_PALETTE_RGB565);			break;		case 24:			fmt = format_by_palette(VIDEO_PALETTE_RGB24);			break;		case 32:			fmt = format_by_palette(VIDEO_PALETTE_RGB32);			break;		case 15:			fbuf->depth = 16;			fmt = format_by_palette(VIDEO_PALETTE_RGB555);			break;		default:			fmt = NULL;			break;		}		if (NULL == fmt)			goto fh_unlock_and_return;		fh->ovfmt = fmt;		fh->fmt   = fmt;		btv->init.ovfmt = fmt;		btv->init.fmt   = fmt;		btv->fbuf.base             = fbuf->base;		btv->fbuf.fmt.width        = fbuf->width;		btv->fbuf.fmt.height       = fbuf->height;		if (fbuf->bytesperline)			btv->fbuf.fmt.bytesperline = fbuf->bytesperline;		else			btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fbuf->depth/8;		up(&fh->cap.lock);		return 0;	}	case VIDIOCCAPTURE:	case VIDIOC_OVERLAY:	{		struct bttv_buffer *new;		int *on = arg;		if (*on) {			/* verify args */			if (NULL == btv->fbuf.base)				return -EINVAL;			if (!fh->ov.setup_ok) {				dprintk("bttv%d: overlay: !setup_ok\n",btv->c.nr);				return -EINVAL;			}		}		if (!check_alloc_btres(btv,fh,RESOURCE_OVERLAY))			return -EBUSY;		down(&fh->cap.lock);		if (*on) {			fh->ov.tvnorm = btv->tvnorm;			new = videobuf_alloc(sizeof(*new));			bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);		} else {			new = NULL;		}		/* switch over */	        retval = bttv_switch_overlay(btv,fh,new);		up(&fh->cap.lock);		return retval;	}	case VIDIOCGMBUF:	{		struct video_mbuf *mbuf = arg;		unsigned int i;		down(&fh->cap.lock);		retval = videobuf_mmap_setup(&fh->cap,gbuffers,gbufsize,					     V4L2_MEMORY_MMAP);		if (retval < 0)			goto fh_unlock_and_return;		memset(mbuf,0,sizeof(*mbuf));		mbuf->frames = gbuffers;		mbuf->size   = gbuffers * gbufsize;		for (i = 0; i < gbuffers; i++)			mbuf->offsets[i] = i * gbufsize;		up(&fh->cap.lock);		return 0;	}	case VIDIOCMCAPTURE:	{		struct video_mmap *vm = arg;		struct bttv_buffer *buf;		enum v4l2_field field;		if (vm->frame >= VIDEO_MAX_FRAME)			return -EINVAL;		down(&fh->cap.lock);		retval = -EINVAL;		buf = (struct bttv_buffer *)fh->cap.bufs[vm->frame];		if (NULL == buf)			goto fh_unlock_and_return;		if (0 == buf->vb.baddr)			goto fh_unlock_and_return;		if (buf->vb.state == STATE_QUEUED ||		    buf->vb.state == STATE_ACTIVE)			goto fh_unlock_and_return;		field = (vm->height > bttv_tvnorms[btv->tvnorm].sheight/2)			? V4L2_FIELD_INTERLACED			: V4L2_FIELD_BOTTOM;		retval = bttv_prepare_buffer(btv,buf,					     format_by_palette(vm->format),					     vm->width,vm->height,field);		if (0 != retval)			goto fh_unlock_and_return;		spin_lock_irqsave(&btv->s_lock,flags);		buffer_queue(&fh->cap,&buf->vb);		spin_unlock_irqrestore(&btv->s_lock,flags);		up(&fh->cap.lock);		return 0;	}	case VIDIOCSYNC:	{		int *frame = arg;		struct bttv_buffer *buf;		if (*frame >= VIDEO_MAX_FRAME)			return -EINVAL;		down(&fh->cap.lock);		retval = -EINVAL;		buf = (struct bttv_buffer *)fh->cap.bufs[*frame];		if (NULL == buf)			goto fh_unlock_and_return;		retval = videobuf_waiton(&buf->vb,0,1);		if (0 != retval)			goto fh_unlock_and_return;		switch (buf->vb.state) {		case STATE_ERROR:			retval = -EIO;			/* fall through */		case STATE_DONE:			videobuf_dma_pci_sync(btv->c.pci,&buf->vb.dma);			bttv_dma_free(btv,buf);			break;		default:			retval = -EINVAL;			break;		}		up(&fh->cap.lock);		return retval;	}	case VIDIOCGVBIFMT:	{		struct vbi_format *fmt = (void *) arg;		struct v4l2_format fmt2;		if (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE) {			retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);			if (0 != retval)				return retval;		}		bttv_vbi_get_fmt(fh, &fmt2);		memset(fmt,0,sizeof(*fmt));		fmt->sampling_rate    = fmt2.fmt.vbi.sampling_rate;		fmt->samples_per_line = fmt2.fmt.vbi.samples_per_line;		fmt->sample_format    = VIDEO_PALETTE_RAW;		fmt->start[0]         = fmt2.fmt.vbi.start[0];		fmt->count[0]         = fmt2.fmt.vbi.count[0];		fmt->start[1]         = fmt2.fmt.vbi.start[1];		fmt->count[1]         = fmt2.fmt.vbi.count[1];		if (fmt2.fmt.vbi.flags & VBI_UNSYNC)			fmt->flags   |= V4L2_VBI_UNSYNC;		if (fmt2.fmt.vbi.flags & VBI_INTERLACED)			fmt->flags   |= V4L2_VBI_INTERLACED;		return 0;	}	case VIDIOCSVBIFMT:	{		struct vbi_format *fmt = (void *) arg;		struct v4l2_format fmt2;		retval = bttv_switch_type(fh,V4L2_BUF_TYPE_VBI_CAPTURE);		if (0 != retval)			return retval;		bttv_vbi_get_fmt(fh, &fmt2);		if (fmt->sampling_rate    != fmt2.fmt.vbi.sampling_rate     ||		    fmt->samples_per_line != fmt2.fmt.vbi.samples_per_line  ||		    fmt->sample_format    != VIDEO_PALETTE_RAW              ||		    fmt->start[0]         != fmt2.fmt.vbi.start[0]          ||		    fmt->start[1]         != fmt2.fmt.vbi.start[1]          ||		    fmt->count[0]         != fmt->count[1]                  ||		    fmt->count[0]         <  1                              ||		    fmt->count[0]         >  32 /* VBI_MAXLINES */)			return -EINVAL;		bttv_vbi_setlines(fh,btv,fmt->count[0]);		return 0;	}        case BTTV_VERSION:        case VIDIOCGFREQ:        case VIDIOCSFREQ:        case VIDIOCGTUNER:        case VIDIOCSTUNER:        case VIDIOCGCHAN:        case VIDIOCSCHAN:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		return bttv_common_ioctls(btv,cmd,arg);	/* ***  v4l2  *** ************************************************ */	case VIDIOC_QUERYCAP:	{		struct v4l2_capability *cap = arg;		if (0 == v4l2)			return -EINVAL;                strcpy(cap->driver,"bttv");                strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card));		sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci));		cap->version = BTTV_VERSION_CODE;		cap->capabilities =			V4L2_CAP_VIDEO_CAPTURE |			V4L2_CAP_VBI_CAPTURE |			V4L2_CAP_READWRITE |			V4L2_CAP_STREAMING;		if (no_overlay <= 0)			cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;		if (bttv_tvcards[btv->c.type].tuner != UNSET &&		    bttv_tvcards[btv->c.type].tuner != TUNER_ABSENT)			cap->capabilities |= V4L2_CAP_TUNER;		return 0;	}	case VIDIOC_ENUM_FMT:	{		struct v4l2_fmtdesc *f = arg;		enum v4l2_buf_type type;		unsigned int i;		int index;		type  = f->type;		if (V4L2_BUF_TYPE_VBI_CAPTURE == type) {			/* vbi */			index = f->index;			if (0 != index)				return -EINVAL;			memset(f,0,sizeof(*f));			f->index       = index;			f->type        = type;			f->pixelformat = V4L2_PIX_FMT_GREY;			strcpy(f->description,"vbi data");			return 0;		}		/* video capture + overlay */		index = -1;		for (i = 0; i < BTTV_FORMATS; i++) {			if (bttv_formats[i].fourcc != -1)				index++;			if ((unsigned int)index == f->index)				break;		}		if (BTTV_FORMATS == i)			return -EINVAL;		switch (f->type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			break;		case V4L2_BUF_TYPE_VIDEO_OVERLAY:			if (!(bttv_formats[i].flags & FORMAT_FLAGS_PACKED))				return -EINVAL;			break;		default:			return -EINVAL;		}		memset(f,0,sizeof(*f));		f->index       = index;		f->type        = type;		f->pixelformat = bttv_formats[i].fourcc;		strlcpy(f->description,bttv_formats[i].name,sizeof(f->description));		return 0;	}	case VIDIOC_TRY_FMT:	{		struct v4l2_format *f = arg;		return bttv_try_fmt(fh,btv,f);	}	case VIDIOC_G_FMT:	{		struct v4l2_format *f = arg;		return bttv_g_fmt(fh,f);	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = arg;		return bttv_s_fmt(fh,btv,f);	}	case VIDIOC_G_FBUF:	{		struct v4l2_framebuffer *fb = arg;		*fb = btv->fbuf;		fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;		if (fh->ovfmt)			fb->fmt.pixelformat  = fh->ovfmt->fourcc;		return 0;	}	case VIDIOC_S_FBUF:	{		struct v4l2_framebuffer *fb = arg;		const struct bttv_format *fmt;		if(!capable(CAP_SYS_ADMIN) &&		   !capable(CAP_SYS_RAWIO))			return -EPERM;		/* check args */		fmt = format_by_fourcc(fb->fmt.pixelformat);		if (NULL == fmt)			return -EINVAL;		if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))			return -EINVAL;		down(&fh->cap.lock);		retval = -EINVAL;		if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {			if (fb->fmt.width > bttv_tvnorms[btv->tvnorm].swidth)				goto fh_unlock_and_return;			if (fb->fmt.height > bttv_tvnorms[btv->tvnorm].sheight)				goto fh_unlock_and_return;		}		/* ok, accept it */		btv->fbuf.base       = fb->base;		btv->fbuf.fmt.width  = fb->fmt.width;		btv->fbuf.fmt.height = fb->fmt.height;		if (0 != fb->fmt.bytesperline)			btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;		else			btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;		retval = 0;		fh->ovfmt = fmt;		btv->init.ovfmt = fmt;		if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {			fh->ov.w.left   = 0;			fh->ov.w.top    = 0;			fh->ov.w.width  = fb->fmt.width;			fh->ov.w.height = fb->fmt.height;			btv->init.ov.w.width  = fb->fmt.width;			btv->init.ov.w.height = fb->fmt.height;			kfree(fh->ov.clips);			fh->ov.clips = NULL;			fh->ov.nclips = 0;			if (check_btres(fh, RESOURCE_OVERLAY)) {				struct bttv_buffer *new;				new = videobuf_alloc(sizeof(*new));				bttv_overlay_risc(btv,&fh->ov,fh->ovfmt,new);				retval = bttv_switch_overlay(btv,fh,new);			}		}		up(&fh->cap.lock);		return retval;	}	case VIDIOC_REQBUFS:		return videobuf_reqbufs(bttv_queue(fh),arg);	case VIDIOC_QUERYBUF:		return videobuf_querybuf(bttv_queue(fh),arg);	case VIDIOC_QBUF:		return videobuf_qbuf(bttv_queue(fh),arg);	case VIDIOC_DQBUF:		return videobuf_dqbuf(bttv_queue(fh),arg,				      file->f_flags & O_NONBLOCK);	case VIDIOC_STREAMON:	{		int res = bttv_resource(fh);		if (!check_alloc_btres(btv,fh,res))			return -EBUSY;		return videobuf_streamon(bttv_queue(fh));	}	case VIDIOC_STREAMOFF:	{		int res = bttv_resource(fh);		retval = videobuf_streamoff(bttv_queue(fh));		if (retval < 0)			return retval;		free_btres(btv,fh,res);		return 0;	}	case VIDIOC_QUERYCTRL:	{		struct v4l2_queryctrl *c = arg;		int i;		if ((c->id <  V4L2_CID_BASE ||		     c->id >= V4L2_CID_LASTP1) &&		    (c->id <  V4L2_CID_PRIVATE_BASE ||		     c->id >= V4L2_CID_PRIVATE_LASTP1))			return -EINVAL;		for (i = 0; i < BTTV_CTLS; i++)			if (bttv_ctls[i].id == c->id)				break;		if (i == BTTV_CTLS) {			*c = no_ctl;			return 0;		}		*c = bttv_ctls[i];		if (i >= 4 && i <= 8) {			struct video_audio va;			memset(&va,0,sizeof(va));			bttv_call_i2c_clients(btv, VIDIOCGAUDIO, &va);			if (btv->audio_hook)				btv->audio_hook(btv,&va,0);			switch (bttv_ctls[i].id) {			case V4L2_CID_AUDIO_VOLUME:				if (!(va.flags & VIDEO_AUDIO_VOLUME))					*c = no_ctl;				break;			case V4L2_CID_AUDIO_BALANCE:				if (!(va.flags & VIDEO_AUDIO_BALANCE))					*c = no_ctl;				break;			case V4L2_CID_AUDIO_BASS:				if (!(va.flags & VIDEO_AUDIO_BASS))					*c = no_ctl;				break;			case V4L2_CID_AUDIO_TREBLE:				if (!(va.flags & VIDEO_AUDIO_TREBLE))					*c = no_ctl;				break;			}		}		return 0;	}	case VIDIOC_G_CTRL:		return get_control(btv,arg);	case VIDIOC_S_CTRL:		return set_control(btv,arg);	case VIDIOC_G_PARM:	{		struct v4l2_streamparm *parm = arg;		struct v4l2_standard s;		if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		memset(parm,0,sizeof(*parm));		v4l2_video_std_construct(&s, bttv_tvnorms[btv->tvnorm].v4l2_id,					 bttv_tvnorms[btv->tvnorm].name);		parm->parm.capture.timeperframe = s.frameperiod;		return 0;	}	case VIDIOC_G_PRIORITY:	{		enum v4l2_priority *p = arg;		*p = v4l2_prio_max(&btv->prio);		return 0;	}	case VIDIOC_S_PRIORITY:	{		enum v4l2_priority *prio = arg;		return v4l2_prio_change(&btv->prio, &fh->prio, *prio);	}	case VIDIOC_ENUMSTD:	case VIDIOC_G_STD:	case VIDIOC_S_STD:	case VIDIOC_ENUMINPUT:	case VIDIOC_G_INPUT:	case VIDIOC_S_INPUT:	case VIDIOC_G_TUNER:	case VIDIOC_S_TUNER:	case VIDIOC_G_FREQUENCY:	case VIDIOC_S_FREQUENCY:	case VIDIOC_LOG_STATUS:		return bttv_common_ioctls(btv,cmd,arg);	default:		return -ENOIOCTLCMD;	}	return 0; fh_unlock_and_return:	up(&fh->cap.lock);	return retval;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/4ac97914c6c35f6bf132071c718e034d0846b9f5/bttv-driver.c/buggy/drivers/media/video/bttv-driver.c