📄 planb.c
字号:
DEBUG("PlanB: device opened\n"); return 0; }static void planb_close(struct video_device *dev){ struct planb *pb = (struct planb *)dev; if(pb->user < 1) /* ??? */ return; planb_lock(pb); if (pb->user == 1) { if (pb->overlay) { planb_dbdma_stop(&pb->planb_base->ch2); planb_dbdma_stop(&pb->planb_base->ch1); pb->overlay = 0; } planb_prepare_close(pb); } pb->user--; planb_unlock(pb); DEBUG("PlanB: device closed\n");}static long planb_read(struct video_device *v, char *buf, unsigned long count, int nonblock){ DEBUG("planb: read request\n"); return -EINVAL;}static long planb_write(struct video_device *v, const char *buf, unsigned long count, int nonblock){ DEBUG("planb: write request\n"); return -EINVAL;}static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg){ struct planb *pb=(struct planb *)dev; switch (cmd) { case VIDIOCGCAP: { struct video_capability b; DEBUG("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 short bpp; unsigned int fmt; DEBUG("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) { case 8: bpp = 1; fmt = PLANB_GRAY; break; case 15: case 16: bpp = 2; fmt = PLANB_COLOUR15; break; case 24: case 32: bpp = 4; fmt = PLANB_COLOUR32; break; default: planb_unlock(pb); return -EINVAL; } if (bpp * v.width > v.bytesperline) { planb_unlock(pb); return -EINVAL; } pb->win.bpp = bpp; pb->win.color_fmt = fmt; pb->frame_buffer_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; DEBUG("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; DEBUG("PlanB: IOCTL VIDIOCGFBUF\n"); v.base = (void *)pb->frame_buffer_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) { DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n"); if (!(pb->overlay)) return 0; planb_lock(pb); pb->overlay = 0; overlay_stop(pb); planb_unlock(pb); } else { DEBUG("PlanB: IOCTL VIDIOCCAPTURE Start\n"); if (pb->frame_buffer_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; DEBUG("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; DEBUG("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: return -EINVAL; break; } planb_lock(pb); /* empty the grabbing queue */ wait_event(pb->capq, !pb->grabbing); pb->maxlines = maxlines; pb->win.norm = v.norm; /* Stop overlay if running */ suspend_overlay(pb); for(i = 0; i < MAX_GBUFFERS; i++) pb->gnorm_switch[i] = 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: return -EINVAL; break; } return 0; } case VIDIOCGPICT: { struct video_picture vp = pb->picture; DEBUG("PlanB: IOCTL VIDIOCGPICT\n"); switch(pb->win.color_fmt) { case PLANB_GRAY: vp.palette = VIDEO_PALETTE_GREY; case PLANB_COLOUR15: vp.palette = VIDEO_PALETTE_RGB555; break; case PLANB_COLOUR32: vp.palette = VIDEO_PALETTE_RGB32; break; default: vp.palette = 0; break; } if(copy_to_user(arg,&vp,sizeof(vp))) return -EFAULT; return 0; } case VIDIOCSPICT: { struct video_picture vp; DEBUG("PlanB: IOCTL VIDIOCSPICT\n"); if(copy_from_user(&vp,arg,sizeof(vp))) return -EFAULT; pb->picture = vp; /* Should we do sanity checks here? */ 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); return 0; } case VIDIOCSWIN: { struct video_window vw; struct video_clip clip; int i; DEBUG("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); } /* 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; DEBUG("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; IDEBUG("PlanB: IOCTL VIDIOCSYNC\n"); if(copy_from_user((void *)&i,arg,sizeof(int))) return -EFAULT; IDEBUG("PlanB: sync to frame %d\n", i); if(i > (MAX_GBUFFERS - 1) || i < 0) return -EINVAL;chk_grab: switch (pb->frame_stat[i]) { case GBUFFER_UNUSED: return -EINVAL; case GBUFFER_GRABBING: IDEBUG("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: pb->frame_stat[i] = GBUFFER_UNUSED; break; } return 0; } case VIDIOCMCAPTURE: { struct video_mmap vm; volatile unsigned int status; IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n"); if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm))) return -EFAULT; status = pb->frame_stat[vm.frame]; if (status != GBUFFER_UNUSED) return -EBUSY; return vgrab(pb, &vm); } case VIDIOCGMBUF: { int i; struct video_mbuf vm; DEBUG("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 PLANBIOCGSAAREGS: { struct planb_saa_regs preg; DEBUG("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; DEBUG("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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -