Enscript Output

extractedLnx/linux-2.4.37/drivers/media/video/planb.c_planb_ioctl.c

static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
	struct planb *pb=(struct planb *)dev->priv;
  	
	switch (cmd)
	{	
		case VIDIOCGCAP:
		{
			struct video_capability b;

			DBG("PlanB: IOCTL VIDIOCGCAP\n");

			strcpy (b.name, pb->video_dev.name);
			b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
				 VID_TYPE_FRAMERAM | VID_TYPE_SCALES |
				 VID_TYPE_CAPTURE;
			b.channels = 2;	/* composite & svhs */
			b.audios = 0;
			b.maxwidth = PLANB_MAXPIXELS;
                        b.maxheight = PLANB_MAXLINES;
                        b.minwidth = 32; /* wild guess */
                        b.minheight = 32;
                        if (copy_to_user(arg,&b,sizeof(b)))
                                return -EFAULT;
			return 0;
		}
		case VIDIOCSFBUF:
		{
                        struct video_buffer v;
			unsigned int fmt;

			DBG("PlanB: IOCTL VIDIOCSFBUF\n");

                        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
                                return -EPERM;
                        if (copy_from_user(&v, arg, sizeof(v)))
                                return -EFAULT;
			planb_lock(pb);
			switch(v.depth) {
			    /* xawtv only asks for 8 bit in static grey, but
			     * there is no way to know what it really means.. */
			    case 8:
				fmt = VIDEO_PALETTE_GREY;
				break;
			    case 15:
				fmt = VIDEO_PALETTE_RGB555;
				break;
			    case 32:
				fmt = VIDEO_PALETTE_RGB32;
				break;
			    /* We don't deliver these two... */
			    case 16:
			    case 24:
			    default:
				planb_unlock(pb);
                                return -EINVAL;
			}
			if (palette2fmt[fmt].bpp * v.width > v.bytesperline) {
				planb_unlock(pb);
				return -EINVAL;
			}
			pb->win.bpp = palette2fmt[fmt].bpp;
			pb->win.color_fmt = fmt;
			pb->fb.phys = (unsigned long) v.base;
			pb->win.sheight = v.height;
			pb->win.swidth = v.width;
			pb->picture.depth = pb->win.depth = v.depth;
			pb->win.bpl = pb->win.bpp * pb->win.swidth;
			pb->win.pad = v.bytesperline - pb->win.bpl;

                        DBG("PlanB: Display at %p is %d by %d, bytedepth %d,"
				" bpl %d (+ %d)\n", v.base, v.width,v.height,
				pb->win.bpp, pb->win.bpl, pb->win.pad);

			pb->cmd_buff_inited = 0;
			if(pb->overlay) {
				suspend_overlay(pb);
				fill_cmd_buff(pb);
				resume_overlay(pb);
			}
			planb_unlock(pb);
			return 0;		
		}
		case VIDIOCGFBUF:
		{
                        struct video_buffer v;

			DBG("PlanB: IOCTL VIDIOCGFBUF\n");

			v.base = (void *)pb->fb.phys;
			v.height = pb->win.sheight;
			v.width = pb->win.swidth;
			v.depth = pb->win.depth;
			v.bytesperline = pb->win.bpl + pb->win.pad;
			if (copy_to_user(arg, &v, sizeof(v)))
                                return -EFAULT;
			return 0;
		}
		case VIDIOCCAPTURE:
		{
			int i;

                        if(copy_from_user(&i, arg, sizeof(i)))
                                return -EFAULT;
			if(i==0) {
				DBG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");

				if (!(pb->overlay))
					return 0;
				planb_lock(pb);
				pb->overlay = 0;
				overlay_stop(pb);
				planb_unlock(pb);
			} else {
				DBG("PlanB: IOCTL VIDIOCCAPTURE Start\n");

				if (pb->fb.phys == 0 ||
					  pb->win.width == 0 ||
					  pb->win.height == 0)
					return -EINVAL;
				if (pb->overlay)
					return 0;
				planb_lock(pb);
				pb->overlay = 1;
				if(!(pb->cmd_buff_inited))
					fill_cmd_buff(pb);
				overlay_start(pb);
				planb_unlock(pb);
			}
			return 0;
		}
		case VIDIOCGCHAN:
		{
			struct video_channel v;

			DBG("PlanB: IOCTL VIDIOCGCHAN\n");

			if(copy_from_user(&v, arg,sizeof(v)))
				return -EFAULT;
			v.flags = 0;
			v.tuners = 0;
			v.type = VIDEO_TYPE_CAMERA;
			v.norm = pb->win.norm;
			switch(v.channel)
			{
			case 0:
				strcpy(v.name,"Composite");
				break;
			case 1:
				strcpy(v.name,"SVHS");
				break;
			default:
				return -EINVAL;
				break;
			}
			if(copy_to_user(arg,&v,sizeof(v)))
				return -EFAULT;

			return 0;
		}
		case VIDIOCSCHAN:
		{
			struct video_channel v;

			DBG("PlanB: IOCTL VIDIOCSCHAN\n");

			if(copy_from_user(&v, arg, sizeof(v)))
				return -EFAULT;

			if (v.norm != pb->win.norm) {
				int i, maxlines;

				switch (v.norm)
				{
				case VIDEO_MODE_PAL:
				case VIDEO_MODE_SECAM:
					maxlines = PLANB_MAXLINES;
					break;
				case VIDEO_MODE_NTSC:
					maxlines = PLANB_NTSC_MAXLINES;
					break;
				default:
					DBG("       invalid norm %d.\n", v.norm);
					return -EINVAL;
					break;
				}
				planb_lock(pb);
				/* empty the grabbing queue */
				while(pb->grabbing)
					interruptible_sleep_on(&pb->capq);
				pb->maxlines = maxlines;
				pb->win.norm = v.norm;
				/* Stop overlay if running */
				suspend_overlay(pb);
				for(i = 0; i < MAX_GBUFFERS; i++)
					pb->gbuf[i].norm_switch = 1;
				/* I know it's an overkill, but.... */
				fill_cmd_buff(pb);
				/* ok, now init it accordingly */
				saa_init_regs (pb);
				/* restart overlay if it was running */
				resume_overlay(pb);
				planb_unlock(pb);
			}

			switch(v.channel)
			{
			case 0:	/* Composite	*/
				saa_set (SAA7196_IOCC,
					((saa_regs[pb->win.norm][SAA7196_IOCC] &
					  ~7) | 3), pb);
				break;
			case 1:	/* SVHS		*/
				saa_set (SAA7196_IOCC,
					((saa_regs[pb->win.norm][SAA7196_IOCC] &
					  ~7) | 4), pb);
				break;
			default:
				DBG("       invalid channel %d.\n", v.channel);
				return -EINVAL;
				break;
			}

			return 0;
		}
		case VIDIOCGPICT:
		{
			struct video_picture vp = pb->picture;

			DBG("PlanB: IOCTL VIDIOCGPICT\n");

			vp.palette = pb->win.color_fmt;
			if(copy_to_user(arg,&vp,sizeof(vp)))
				return -EFAULT;
			return 0;
		}
		case VIDIOCSPICT:
		{
			struct video_picture vp;

			DBG("PlanB: IOCTL VIDIOCSPICT\n");

			if(copy_from_user(&vp,arg,sizeof(vp)))
				return -EFAULT;
			pb->picture = vp;
			/* Should we do sanity checks here? */
			planb_lock(pb);
			saa_set (SAA7196_BRIG, (unsigned char)
			    ((pb->picture.brightness) >> 8), pb);
			saa_set (SAA7196_HUEC, (unsigned char)
			    ((pb->picture.hue) >> 8) ^ 0x80, pb);
			saa_set (SAA7196_CSAT, (unsigned char)
			    ((pb->picture.colour) >> 9), pb);
			saa_set (SAA7196_CONT, (unsigned char)
			    ((pb->picture.contrast) >> 9), pb);
			planb_unlock(pb);

			return 0;
		}
		case VIDIOCSWIN:
		{
			struct video_window	vw;
			struct video_clip	clip;
			int 			i;
			
			DBG("PlanB: IOCTL VIDIOCSWIN\n");

			if(copy_from_user(&vw,arg,sizeof(vw)))
				return -EFAULT;

			planb_lock(pb);
			/* Stop overlay if running */
			suspend_overlay(pb);
			pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0;
			if (pb->win.x != vw.x ||
			    pb->win.y != vw.y ||
			    pb->win.width != vw.width ||
			    pb->win.height != vw.height ||
			    !pb->cmd_buff_inited) {
				pb->win.x = vw.x;
				pb->win.y = vw.y;
				pb->win.width = vw.width;
				pb->win.height = vw.height;
				fill_cmd_buff(pb);
			}
                        DBG("PlanB: Window at (%d,%d) size %dx%d\n", vw.x, vw.y, vw.width,
				vw.height);

			/* Reset clip mask */
			memset ((void *) pb->mask, 0xff, (pb->maxlines
					* ((PLANB_MAXPIXELS + 7) & ~7)) / 8);
			/* Add any clip rects */
			for (i = 0; i < vw.clipcount; i++) {
				if (copy_from_user(&clip, vw.clips + i,
						sizeof(struct video_clip)))
					return -EFAULT;
				add_clip(pb, &clip);
			}
			/* restart overlay if it was running */
			resume_overlay(pb);
			planb_unlock(pb);
			return 0;
		}
		case VIDIOCGWIN:
		{
			struct video_window vw;

			DBG("PlanB: IOCTL VIDIOCGWIN\n");

			vw.x=pb->win.x;
			vw.y=pb->win.y;
			vw.width=pb->win.width;
			vw.height=pb->win.height;
			vw.chromakey=0;
			vw.flags=0;
			if(pb->win.interlace)
				vw.flags|=VIDEO_WINDOW_INTERLACE;
			if(copy_to_user(arg,&vw,sizeof(vw)))
				return -EFAULT;
			return 0;
		}
	        case VIDIOCSYNC: {
			int		i;
			gbuf_ptr	gbuf;

			DBG("PlanB: IOCTL VIDIOCSYNC\n");

			if(copy_from_user((void *)&i,arg,sizeof(int)))
				return -EFAULT;

			DBG("PlanB: sync to frame %d\n", i);

                        if(i > (MAX_GBUFFERS - 1) || i < 0)
                                return -EINVAL;
			gbuf = &pb->gbuf[i];
chk_grab:
                        switch (*gbuf->status) {
                        case GBUFFER_UNUSED:
                                return -EINVAL;
			case GBUFFER_GRABBING:
				DBG("PlanB: waiting for grab"
							" done (%d)\n", i);
 			        interruptible_sleep_on(&pb->capq);
				if(signal_pending(current))
					return -EINTR;
				goto chk_grab;
                        case GBUFFER_DONE:
                                *gbuf->status = GBUFFER_UNUSED;
                                break;
                        }
                        return 0;
		}

	        case VIDIOCMCAPTURE:
		{
                        struct video_mmap vm;
			int		  fr;

			DBG("PlanB: IOCTL VIDIOCMCAPTURE\n");

			if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
				return -EFAULT;
			fr = vm.frame;
                        if(fr > (MAX_GBUFFERS - 1) || fr < 0)
                                return -EINVAL;
			if (*pb->gbuf[fr].status != GBUFFER_UNUSED)
				return -EBUSY;

			return vgrab(pb, &vm);
		}
		
		case VIDIOCGMBUF:
		{
			int i;
			struct video_mbuf vm;

			DBG("PlanB: IOCTL VIDIOCGMBUF\n");

			memset(&vm, 0 , sizeof(vm));
			vm.size = PLANB_MAX_FBUF * MAX_GBUFFERS;
			vm.frames = MAX_GBUFFERS;
			for(i = 0; i<MAX_GBUFFERS; i++)
				vm.offsets[i] = PLANB_MAX_FBUF * i;
			if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
				return -EFAULT;
			return 0;
		}
		
		case VIDIOCGUNIT:
		{
			struct video_unit vu;

			DBG("PlanB: IOCTL VIDIOCGUNIT\n");

			vu.video=pb->video_dev.minor;
			vu.vbi=pb->vbi_dev.minor;
			vu.radio=VIDEO_NO_UNIT;
			vu.audio=VIDEO_NO_UNIT;
			vu.teletext=VIDEO_NO_UNIT;
			if(copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
				return -EFAULT;
			return 0;
		}

		case PLANBIOCGSAAREGS:
		{
			struct planb_saa_regs preg;

			DBG("PlanB: IOCTL PLANBIOCGSAAREGS\n");

			if(copy_from_user(&preg, arg, sizeof(preg)))
				return -EFAULT;
			if(preg.addr >= SAA7196_NUMREGS)
				return -EINVAL;
			preg.val = saa_regs[pb->win.norm][preg.addr];
			if(copy_to_user((void *)arg, (void *)&preg,
								sizeof(preg)))
				return -EFAULT;
			return 0;
		}
		
		case PLANBIOCSSAAREGS:
		{
			struct planb_saa_regs preg;

			DBG("PlanB: IOCTL PLANBIOCSSAAREGS\n");

			if(copy_from_user(&preg, arg, sizeof(preg)))
				return -EFAULT;
			if(preg.addr >= SAA7196_NUMREGS)
				return -EINVAL;
			saa_set (preg.addr, preg.val, pb);
			return 0;
		}
		
		case PLANBIOCGSTAT:
		{
			struct planb_stat_regs pstat;

			DBG("PlanB: IOCTL PLANBIOCGSTAT\n");

			pstat.ch1_stat = readl(&pb->planb_base->ch1.status);
			pstat.ch2_stat = readl(&pb->planb_base->ch2.status);
			pstat.ch1_cmdbase = (unsigned long)pb->vid_cbo.start;
			pstat.ch2_cmdbase = (unsigned long)pb->clip_cbo.start;
			pstat.ch1_cmdptr = readl(&pb->planb_base->ch1.cmdptr);
			pstat.ch2_cmdptr = readl(&pb->planb_base->ch2.cmdptr);
			pstat.saa_stat0 = saa_status(0, pb);
			pstat.saa_stat1 = saa_status(1, pb);

			if(copy_to_user((void *)arg, (void *)&pstat,
							sizeof(pstat)))
				return -EFAULT;
			return 0;
		}

		case PLANBIOCSMODE: {
			int v;

			DBG("PlanB: IOCTL PLANBIOCSMODE\n");

			if(copy_from_user(&v, arg, sizeof(v)))
				return -EFAULT;

			switch(v)
			{
			case PLANB_TV_MODE:
				saa_set (SAA7196_STDC,
					(saa_regs[pb->win.norm][SAA7196_STDC] &
					  0x7f), pb);
				break;
			case PLANB_VTR_MODE:
				saa_set (SAA7196_STDC,
					(saa_regs[pb->win.norm][SAA7196_STDC] |
					  0x80), pb);
				break;
			default:
				return -EINVAL;
				break;
			}
			pb->win.mode = v;
			return 0;
		}
		case PLANBIOCGMODE: {
			int v=pb->win.mode;

			DBG("PlanB: IOCTL PLANBIOCGMODE\n");

			if(copy_to_user(arg,&v,sizeof(v)))
				return -EFAULT;
			return 0;
		}
#ifdef PLANB_GSCANLINE
		case PLANBG_GRAB_BPL: {
			int v=pb->gbytes_per_line;

			DBG("PlanB: IOCTL PLANBG_GRAB_BPL\n");

			if(copy_to_user(arg,&v,sizeof(v)))
				return -EFAULT;
			return 0;
		}
#endif /* PLANB_GSCANLINE */

/* These serve only for debugging... */
#ifdef DEBUG
		case PLANB_INTR_DEBUG: {
			int i;

			DBG("PlanB: IOCTL PLANB_INTR_DEBUG\n");

			if(copy_from_user(&i, arg, sizeof(i)))
				return -EFAULT;

			/* avoid hang ups all together */
			for (i = 0; i < MAX_GBUFFERS; i++) {
				if(*pb->gbuf[i].status == GBUFFER_GRABBING) {
					*pb->gbuf[i].status = GBUFFER_DONE;
				}
			}
			if(pb->grabbing)
				pb->grabbing--;
			wake_up_interruptible(&pb->capq);
			return 0;
		}
		case PLANB_INV_REGS: {
			int i;
			struct planb_any_regs any;

			DBG("PlanB: IOCTL PLANB_INV_REGS\n");

			if(copy_from_user(&any, arg, sizeof(any)))
				return -EFAULT;
			if(any.offset < 0 || any.offset + any.bytes > 0x400)
				return -EINVAL;
			if(any.bytes > 128)
				return -EINVAL;
			for (i = 0; i < any.bytes; i++) {
				any.data[i] =
					readb((unsigned char *)pb->planb_base
							+ any.offset + i);
			}
			if(copy_to_user(arg,&any,sizeof(any)))
				return -EFAULT;
			return 0;
		}
		case PLANBIOCGDBDMABUF:
		{
			struct planb_buf_regs buf;
			dbdma_cmd_ptr dc;
			int i;

			DBG("PlanB: IOCTL PLANBIOCGDBDMABUF\n");

			if(copy_from_user(&buf, arg, sizeof(buf)))
				return -EFAULT;
			buf.end &= ~0xf;
			if( (buf.start < 0) || (buf.end < 0x10) ||
			    (buf.end < buf.start+0x10) ||
			    (buf.end > 2*pb->tab_size) )
				return -EINVAL;

			printk ("PlanB DBDMA command buffer:\n");
			for (i=(buf.start>>4); i<=(buf.end>>4); i++) {
				printk(" 0x%04x:", i<<4);
				dc = pb->vid_cbo.start + i;
				printk (" %04x %04x %08x %08x %04x %04x\n",
				  dc->req_count, dc->command, dc->phy_addr,
				  dc->cmd_dep, dc->res_count, dc->xfer_status);
			}
			return 0;
		}
#endif /* DEBUG */

		default:
		{
			DBG("PlanB: Unimplemented IOCTL: %d (0x%x)\n", cmd, cmd);
			return -ENOIOCTLCMD;
		}
	/* Some IOCTLs are currently unsupported on PlanB */
		case VIDIOCGTUNER: {
		DBG("PlanB: IOCTL VIDIOCGTUNER\n");
			goto unimplemented; }
		case VIDIOCSTUNER: {
		DBG("PlanB: IOCTL VIDIOCSTUNER\n");
			goto unimplemented; }
		case VIDIOCSFREQ: {
		DBG("PlanB: IOCTL VIDIOCSFREQ\n");
			goto unimplemented; }
		case VIDIOCGFREQ: {
		DBG("PlanB: IOCTL VIDIOCGFREQ\n");
			goto unimplemented; }
		case VIDIOCKEY: {
		DBG("PlanB: IOCTL VIDIOCKEY\n");
			goto unimplemented; }
		case VIDIOCSAUDIO: {
		DBG("PlanB: IOCTL VIDIOCSAUDIO\n");
			goto unimplemented; }
		case VIDIOCGAUDIO: {
		DBG("PlanB: IOCTL VIDIOCGAUDIO\n");
			goto unimplemented; }
unimplemented:
		DBG("       Unimplemented\n");
			return -ENOIOCTLCMD;
	}
	return 0;
}

Generated by GNU enscript 1.6.4.