📄 stv680.c
字号:
return -EFAULT; } if (v != 0) return -EINVAL; return 0; } case VIDIOCGPICT:{ struct video_picture p; stv680_get_pict (stv680, &p); if (copy_to_user (arg, &p, sizeof (p))) { PDEBUG (2, "STV(e): VIDIOCGPICT failed"); return -EFAULT; } return 0; } case VIDIOCSPICT:{ struct video_picture p; if (copy_from_user (&p, arg, sizeof (p))) { PDEBUG (2, "STV(e): VIDIOCSPICT failed"); return -EFAULT; } copy_from_user (&p, arg, sizeof (p)); PDEBUG (2, "STV(i): palette set to %i in VIDIOSPICT", p.palette); if (stv680_set_pict (stv680, &p)) return -EINVAL; return 0; } case VIDIOCSWIN:{ struct video_window vw; if (copy_from_user (&vw, arg, sizeof (vw))) return -EFAULT; if (vw.flags) return -EINVAL; if (vw.clipcount) return -EINVAL; if (vw.width != stv680->vwidth) { if (stv680_set_size (stv680, vw.width, vw.height)) { PDEBUG (2, "STV(e): failed (from user) set size in VIDIOCSWIN"); return -EINVAL; } } return 0; } case VIDIOCGWIN:{ struct video_window vw; vw.x = 0; /* FIXME */ vw.y = 0; vw.chromakey = 0; vw.flags = 0; vw.clipcount = 0; vw.width = stv680->vwidth; vw.height = stv680->vheight; if (copy_to_user (arg, &vw, sizeof (vw))) { PDEBUG (2, "STV(e): VIDIOCGWIN failed"); return -EFAULT; } return 0; } case VIDIOCGMBUF:{ struct video_mbuf vm; int i; memset (&vm, 0, sizeof (vm)); vm.size = STV680_NUMFRAMES * stv680->maxframesize; vm.frames = STV680_NUMFRAMES; for (i = 0; i < STV680_NUMFRAMES; i++) vm.offsets[i] = stv680->maxframesize * i; if (copy_to_user ((void *) arg, (void *) &vm, sizeof (vm))) { PDEBUG (2, "STV(e): VIDIOCGMBUF failed"); return -EFAULT; } return 0; } case VIDIOCMCAPTURE:{ struct video_mmap vm; if (copy_from_user (&vm, arg, sizeof (vm))) { PDEBUG (2, "STV(e): VIDIOCMCAPTURE failed"); return -EFAULT; } if (vm.format != STV_VIDEO_PALETTE) { PDEBUG (2, "STV(i): VIDIOCMCAPTURE vm.format (%i) != VIDEO_PALETTE (%i)", vm.format, STV_VIDEO_PALETTE); if ((vm.format == 3) && (swapRGB_on == 0)) { PDEBUG (2, "STV(i): VIDIOCMCAPTURE swapRGB is (auto) ON"); /* this may fix those apps (e.g., xawtv) that want BGR */ swapRGB = 1; } return -EINVAL; } if (vm.frame >= STV680_NUMFRAMES) { PDEBUG (2, "STV(e): VIDIOCMCAPTURE vm.frame > NUMFRAMES"); return -EINVAL; } if ((stv680->frame[vm.frame].grabstate == FRAME_ERROR) || (stv680->frame[vm.frame].grabstate == FRAME_GRABBING)) { PDEBUG (2, "STV(e): VIDIOCMCAPTURE grabstate (%i) error", stv680->frame[vm.frame].grabstate); return -EBUSY; } /* Is this according to the v4l spec??? */ if (stv680->vwidth != vm.width) { if (stv680_set_size (stv680, vm.width, vm.height)) { PDEBUG (2, "STV(e): VIDIOCMCAPTURE set_size failed"); return -EINVAL; } } stv680->frame[vm.frame].grabstate = FRAME_READY; if (!stv680->streaming) stv680_start_stream (stv680); return 0; } case VIDIOCSYNC:{ int frame, ret = 0; if (copy_from_user ((void *) &frame, arg, sizeof (int))) { PDEBUG (2, "STV(e): VIDIOCSYNC failed"); return -EFAULT; } if (frame < 0 || frame >= STV680_NUMFRAMES) { PDEBUG (2, "STV(e): Bad frame # in VIDIOCSYNC"); return -EINVAL; } ret = stv680_newframe (stv680, frame); stv680->frame[frame].grabstate = FRAME_UNUSED; return ret; } case VIDIOCGFBUF:{ struct video_buffer vb; memset (&vb, 0, sizeof (vb)); vb.base = NULL; /* frame buffer not supported, not used */ if (copy_to_user ((void *) arg, (void *) &vb, sizeof (vb))) { PDEBUG (2, "STV(e): VIDIOCSYNC failed"); return -EFAULT; } return 0; } case VIDIOCKEY: return 0; case VIDIOCCAPTURE: { PDEBUG (2, "STV(e): VIDIOCCAPTURE failed"); return -EINVAL; } case VIDIOCSFBUF: return -EINVAL; case VIDIOCGTUNER: case VIDIOCSTUNER: return -EINVAL; case VIDIOCGFREQ: case VIDIOCSFREQ: return -EINVAL; case VIDIOCGAUDIO: case VIDIOCSAUDIO: return -EINVAL; default: return -ENOIOCTLCMD; } /* end switch */ return 0;}static int stv680_mmap (struct video_device *dev, const char *adr, unsigned long size){ struct usb_stv *stv680 = (struct usb_stv *) dev; unsigned long start = (unsigned long) adr; unsigned long page, pos; down (&stv680->lock); if (stv680->udev == NULL) { up (&stv680->lock); return -EIO; } if (size > (((STV680_NUMFRAMES * stv680->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { up (&stv680->lock); return -EINVAL; } pos = (unsigned long) stv680->fbuf; while (size > 0) { page = kvirt_to_pa (pos); if (remap_page_range (start, page, PAGE_SIZE, PAGE_SHARED)) { up (&stv680->lock); return -EAGAIN; } start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } up (&stv680->lock); return 0;}static long stv680_read (struct video_device *dev, char *buf, unsigned long count, int noblock){ unsigned long int realcount = count; int ret = 0; struct usb_stv *stv680 = (struct usb_stv *) dev; unsigned long int i; if (STV680_NUMFRAMES != 2) { PDEBUG (0, "STV(e): STV680_NUMFRAMES needs to be 2!"); return -1; } if (stv680->udev == NULL) return -EIO; if (realcount > (stv680->vwidth * stv680->vheight * 3)) realcount = stv680->vwidth * stv680->vheight * 3; /* Shouldn't happen: */ if (stv680->frame[0].grabstate == FRAME_GRABBING) { PDEBUG (2, "STV(e): FRAME_GRABBING in stv680_read"); return -EBUSY; } stv680->frame[0].grabstate = FRAME_READY; stv680->frame[1].grabstate = FRAME_UNUSED; stv680->curframe = 0; if (!stv680->streaming) stv680_start_stream (stv680); if (!stv680->streaming) { ret = stv680_newframe (stv680, 0); /* ret should = 0 */ } ret = stv680_newframe (stv680, 0); if (!ret) { if ((i = copy_to_user (buf, stv680->frame[0].data, realcount)) != 0) { PDEBUG (2, "STV(e): copy_to_user frame 0 failed, ret count = %li", i); return -EFAULT; } } else { realcount = ret; } stv680->frame[0].grabstate = FRAME_UNUSED; return realcount;} /* stv680_read */static int stv_init_done (struct video_device *dev){#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) if (create_proc_stv680_cam ((struct usb_stv *) dev) < 0) return -1;#endif return 0;}static struct video_device stv680_template = { owner: THIS_MODULE, name: "STV0680 USB camera", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_SE401, open: stv_open, close: stv_close, read: stv680_read, write: stv680_write, ioctl: stv680_ioctl, mmap: stv680_mmap, initialize: stv_init_done,};static void *__devinit stv680_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_interface_descriptor *interface; struct usb_stv *stv680; char *camera_name = NULL; /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) { PDEBUG (0, "STV(e): Number of Configurations != 1"); return NULL; } interface = &dev->actconfig->interface[ifnum].altsetting[0]; /* Is it a STV680? */ if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) { camera_name = "STV0680"; PDEBUG (0, "STV(i): STV0680 camera found."); } else { PDEBUG (0, "STV(e): Vendor/Product ID do not match STV0680 values."); PDEBUG (0, "STV(e): Check that the STV0680 camera is connected to the computer."); return NULL; } /* We found one */ if ((stv680 = kmalloc (sizeof (*stv680), GFP_KERNEL)) == NULL) { PDEBUG (0, "STV(e): couldn't kmalloc stv680 struct."); return NULL; } memset (stv680, 0, sizeof (*stv680)); stv680->udev = dev; stv680->camera_name = camera_name; memcpy (&stv680->vdev, &stv680_template, sizeof (stv680_template)); memcpy (stv680->vdev.name, stv680->camera_name, strlen (stv680->camera_name)); init_waitqueue_head (&stv680->wq); init_MUTEX (&stv680->lock); wmb (); if (video_register_device (&stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { kfree (stv680); PDEBUG (0, "STV(e): video_register_device failed"); return NULL; } PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor); return stv680;}static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680){ int i; stv680->udev = NULL; stv680->frame[0].grabstate = FRAME_ERROR; stv680->frame[1].grabstate = FRAME_ERROR; stv680->streaming = 0; wake_up_interruptible (&stv680->wq); for (i = 0; i < STV680_NUMSBUF; i++) if (stv680->urb[i]) { stv680->urb[i]->next = NULL; usb_unlink_urb (stv680->urb[i]); usb_free_urb (stv680->urb[i]); stv680->urb[i] = NULL; kfree (stv680->sbuf[i].data); } for (i = 0; i < STV680_NUMSCRATCH; i++) if (stv680->scratch[i].data) { kfree (stv680->scratch[i].data); } PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name);#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) destroy_proc_stv680_cam (stv680);#endif /* Free the memory */ kfree (stv680);}static void stv680_disconnect (struct usb_device *dev, void *ptr){ struct usb_stv *stv680 = (struct usb_stv *) ptr; lock_kernel (); /* We don't want people trying to open up the device */ if (!stv680->user) { video_unregister_device (&stv680->vdev); usb_stv680_remove_disconnected (stv680); } else { stv680->removed = 1; } unlock_kernel ();}static struct usb_driver stv680_driver = { name: "stv680", probe: stv680_probe, disconnect: stv680_disconnect, id_table: device_table};/******************************************************************** * Module routines ********************************************************************/static int __init usb_stv680_init (void){#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) if (proc_stv680_create () < 0) return -1;#endif if (usb_register (&stv680_driver) < 0) { PDEBUG (0, "STV(e): Could not setup STV0680 driver"); return -1; } PDEBUG (0, "STV(i): usb camera driver version %s registering", DRIVER_VERSION); info(DRIVER_DESC " " DRIVER_VERSION); return 0;}static void __exit usb_stv680_exit (void){ usb_deregister (&stv680_driver); PDEBUG (0, "STV(i): driver deregistered");#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) proc_stv680_destroy ();#endif}module_init (usb_stv680_init);module_exit (usb_stv680_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -