📄 stv680.c
字号:
else *(output + x) -= (unsigned char) p; } /* for */ } /* else */ } /* if */ frame->curpix = 0; frame->curlinepix = 0; frame->grabstate = FRAME_DONE; stv680->framecount++; stv680->readcount++; if (stv680->frame[(stv680->curframe + 1) & (STV680_NUMFRAMES - 1)].grabstate == FRAME_READY) { stv680->curframe = (stv680->curframe + 1) & (STV680_NUMFRAMES - 1); }} /* bayer_unshuffle *//******* end routines from the pencam program *********/static int stv680_newframe (struct usb_stv *stv680, int framenr){ int errors = 0; while (stv680->streaming && (stv680->frame[framenr].grabstate == FRAME_READY || stv680->frame[framenr].grabstate == FRAME_GRABBING)) { if (!stv680->frame[framenr].curpix) { errors++; } wait_event_interruptible (stv680->wq, (stv680->scratch[stv680->scratch_use].state == BUFFER_READY)); if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { stv680->nullpackets = 0; PDEBUG (2, "STV(i): too many null length packets, restarting capture"); stv680_stop_stream (stv680); stv680_start_stream (stv680); } else { if (stv680->scratch[stv680->scratch_use].state != BUFFER_READY) { stv680->frame[framenr].grabstate = FRAME_ERROR; PDEBUG (2, "STV(e): FRAME_ERROR in _newframe"); return -EIO; } stv680->scratch[stv680->scratch_use].state = BUFFER_BUSY; bayer_unshuffle (stv680, &stv680->scratch[stv680->scratch_use]); stv680->scratch[stv680->scratch_use].state = BUFFER_UNUSED; stv680->scratch_use++; if (stv680->scratch_use >= STV680_NUMSCRATCH) stv680->scratch_use = 0; if (errors > STV680_MAX_ERRORS) { errors = 0; PDEBUG (2, "STV(i): too many errors, restarting capture"); stv680_stop_stream (stv680); stv680_start_stream (stv680); } } /* else */ } /* while */ return 0;}/********************************************************************* * Video4Linux *********************************************************************/static int stv_open (struct inode *inode, struct file *file){ struct video_device *dev = video_devdata(file); struct usb_stv *stv680 = (struct usb_stv *) dev; int err = 0; /* we are called with the BKL held */ stv680->user = 1; err = stv_init (stv680); /* main initialization routine for camera */ if (err >= 0) { stv680->fbuf = rvmalloc (stv680->maxframesize * STV680_NUMFRAMES); if (!stv680->fbuf) { PDEBUG (0, "STV(e): Could not rvmalloc frame bufer"); err = -ENOMEM; } file->private_data = dev; } if (err) stv680->user = 0; return err;}static int stv_close (struct inode *inode, struct file *file){ struct video_device *dev = file->private_data; struct usb_stv *stv680 = (struct usb_stv *) dev; int i; for (i = 0; i < STV680_NUMFRAMES; i++) stv680->frame[i].grabstate = FRAME_UNUSED; if (stv680->streaming) stv680_stop_stream (stv680); if ((i = stv_stop_video (stv680)) < 0) PDEBUG (1, "STV(e): stop_video failed in stv_close"); rvfree (stv680->fbuf, stv680->maxframesize * STV680_NUMFRAMES); stv680->user = 0; if (stv680->removed) { kfree (stv680); stv680 = NULL; PDEBUG (0, "STV(i): device unregistered"); } file->private_data = NULL; return 0;}static int stv680_do_ioctl (struct inode *inode, struct file *file, unsigned int cmd, void *arg){ struct video_device *vdev = file->private_data; struct usb_stv *stv680 = (struct usb_stv *) vdev; if (!stv680->udev) return -EIO; switch (cmd) { case VIDIOCGCAP:{ struct video_capability *b = arg; strcpy (b->name, stv680->camera_name); b->type = VID_TYPE_CAPTURE; b->channels = 1; b->audios = 0; b->maxwidth = stv680->maxwidth; b->maxheight = stv680->maxheight; b->minwidth = stv680->maxwidth / 2; b->minheight = stv680->maxheight / 2; return 0; } case VIDIOCGCHAN:{ struct video_channel *v = arg; if (v->channel != 0) return -EINVAL; v->flags = 0; v->tuners = 0; v->type = VIDEO_TYPE_CAMERA; strcpy (v->name, "STV Camera"); return 0; } case VIDIOCSCHAN:{ struct video_channel *v = arg; if (v->channel != 0) return -EINVAL; return 0; } case VIDIOCGPICT:{ struct video_picture *p = arg; stv680_get_pict (stv680, p); return 0; } case VIDIOCSPICT:{ struct video_picture *p = arg; if (stv680_set_pict (stv680, p)) return -EINVAL; return 0; } case VIDIOCSWIN:{ struct video_window *vw = arg; 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 = arg; vw->x = 0; /* FIXME */ vw->y = 0; vw->chromakey = 0; vw->flags = 0; vw->clipcount = 0; vw->width = stv680->vwidth; vw->height = stv680->vheight; return 0; } case VIDIOCGMBUF:{ struct video_mbuf *vm = arg; 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; return 0; } case VIDIOCMCAPTURE:{ struct video_mmap *vm = arg; 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 = arg; int ret = 0; 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 = arg; memset (vb, 0, sizeof (*vb)); 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_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ return video_usercopy(inode, file, cmd, arg, stv680_do_ioctl);}static int stv680_mmap (struct file *file, struct vm_area_struct *vma){ struct video_device *dev = file->private_data; struct usb_stv *stv680 = (struct usb_stv *) dev; unsigned long start = vma->vm_start; unsigned long size = vma->vm_end-vma->vm_start; 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 (vma, 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 int stv680_read (struct file *file, char *buf, size_t count, loff_t *ppos){ struct video_device *dev = file->private_data; 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 struct file_operations stv680_fops = { owner: THIS_MODULE, open: stv_open, release: stv_close, read: stv680_read, mmap: stv680_mmap, ioctl: stv680_ioctl, llseek: no_llseek,};static struct video_device stv680_template = { owner: THIS_MODULE, name: "STV0680 USB camera", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_SE401, fops: &stv680_fops,};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; }#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) create_proc_stv680_cam (stv680);#endif 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; /* We don't want people trying to open up the device */ video_unregister_device (&stv680->vdev); if (!stv680->user) { usb_stv680_remove_disconnected (stv680); } else { stv680->removed = 1; }}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 + -