📄 vicam.c
字号:
}static void vicam_v4l_close(struct video_device *vdev){ struct usb_vicam *vicam = (struct usb_vicam *)vdev; dbg("vicam_v4l_close"); down(&vicam->sem);#ifdef BLINKING info ("led off"); vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);// vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on#endif rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES); vicam->fbuf = 0; vicam->open_count=0; up(&vicam->sem); /* Why does se401.c have a usbdevice check here? */ /* If device is unplugged while open, I guess we only may unregister now */ MOD_DEC_USE_COUNT;}static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock){ //struct usb_vicam *vicam = (struct usb_vicam *)vdev; dbg("vicam_v4l_read(%ld)", buflen); if (!vdev || !buf) return -EFAULT; if (copy_to_user(user_buf, buf2, buflen)) return -EFAULT; return buflen;}static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock){ info("vicam_v4l_write"); return -EINVAL;}static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg){ struct usb_vicam *vicam = (struct usb_vicam *)vdev; int ret = -EL3RST; if (!vicam->udev) return -EIO; down(&vicam->sem); switch (cmd) { case VIDIOCGCAP: { struct video_capability b; ret = vicam_get_capability(vicam,&b); dbg("name %s",b.name); if (copy_to_user(arg, &b, sizeof(b))) ret = -EFAULT; } case VIDIOCGFBUF: { struct video_buffer vb; info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param"); /* frame buffer not supported, not used */ memset(&vb, 0, sizeof(vb)); vb.base = NULL; /* FIXME - VIDIOCGFBUF - why the void */ if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) ret = -EFAULT; ret = 0; } case VIDIOCGWIN: { struct video_window vw; ret = vicam_get_window(vicam, &vw); if (copy_to_user(arg, &vw, sizeof(vw))) ret = -EFAULT; } case VIDIOCSWIN: { struct video_window vw; if (copy_from_user(&vw, arg, sizeof(vw))) ret = -EFAULT; else ret = vicam_set_window(vicam, &vw); return ret; } case VIDIOCGCHAN: { struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) ret = -EFAULT; else { ret = vicam_get_channel(vicam,&v); if (copy_to_user(arg, &v, sizeof(v))) ret = -EFAULT; } } case VIDIOCSCHAN: { struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) ret = -EFAULT; else ret = vicam_set_channel(vicam,&v); } case VIDIOCGPICT: { struct video_picture p; ret = vicam_get_picture(vicam, &p); if (copy_to_user(arg, &p, sizeof(p))) ret = -EFAULT; } case VIDIOCSPICT: { struct video_picture p; if (copy_from_user(&p, arg, sizeof(p))) ret = -EFAULT; else ret = vicam_set_picture(vicam, &p); } case VIDIOCGMBUF: { struct video_mbuf vm; ret = vicam_get_mmapbuffer(vicam,&vm); /* FIXME - VIDIOCGMBUF - why the void */ if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) ret = -EFAULT; } case VIDIOCMCAPTURE: { struct video_mmap vm; ret = vicam_mmap_capture(vicam, &vm); /* FIXME: This is probably not right */ } case VIDIOCSYNC: { int frame; /* FIXME - VIDIOCSYNC - why the void */ if (copy_from_user((void *)&frame, arg, sizeof(int))) ret = -EFAULT; else ret = vicam_sync_frame(vicam,frame); } case VIDIOCKEY: ret = 0; case VIDIOCCAPTURE: case VIDIOCSFBUF: case VIDIOCGTUNER: case VIDIOCSTUNER: case VIDIOCGFREQ: case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: case VIDIOCGUNIT: ret = -EINVAL; default: { info("vicam_v4l_ioctl - %ui",cmd); ret = -ENOIOCTLCMD; } } /* end switch */ up(&vicam->sem); return ret;}static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size){ struct usb_vicam *vicam = (struct usb_vicam *)dev; unsigned long start = (unsigned long)adr; unsigned long page, pos; down(&vicam->sem); if (vicam->udev == NULL) { up(&vicam->sem); return -EIO; }#if 0 if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { up(&vicam->sem); return -EINVAL; }#endif pos = (unsigned long)vicam->fbuf; while (size > 0) { page = kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) { up(&vicam->sem); return -EAGAIN; } start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } up(&vicam->sem); return 0;}/* FIXME - vicam_v4l_init */static int vicam_v4l_init(struct video_device *dev){ /* stick proc fs stuff in here if wanted */ dbg("vicam_v4l_init"); return 0;}/* FIXME - vicam_template - important */static struct video_device vicam_template = { name: "vicam USB camera", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_SE401, /* need to ask for own id */ open: vicam_v4l_open, close: vicam_v4l_close, read: vicam_v4l_read, write: vicam_v4l_write, ioctl: vicam_v4l_ioctl, mmap: vicam_v4l_mmap, initialize: vicam_v4l_init,};/****************************************************************************** * * Some Routines * ******************************************************************************//*Flash the ledvicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);info ("led on");vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);info ("led off");vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);*/static void vicam_bulk(struct urb *urb){ struct usb_vicam *vicam = urb->context; /* if (!vicam || !vicam->dev || !vicam->used) return; */ if (urb->status) printk("vicam%d: nonzero read/write bulk status received: %d", 0, urb->status); urb->actual_length = 0; urb->dev = vicam->udev; memcpy(buf2, buf+64, 0x1e480); if (vicam->fbuf) memcpy(vicam->fbuf, buf+64, 0x1e480); if (!change_pending) { if (usb_submit_urb(urb)) dbg("failed resubmitting read urb"); } else { change_pending = 0; wake_up_interruptible(&vicam->wait); }}static int vicam_parameters(struct usb_vicam *vicam){ unsigned char req[0x10]; unsigned int shutter; shutter = 10; switch (vicam->win.width) { case 512: default: memcpy(req, s512x242bw, 0x10); break; case 256: memcpy(req, s256x242bw, 0x10); break; case 128: memcpy(req, s128x122bw, 0x10); break; } mdelay(10); vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); info ("led on"); vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); mdelay(10); shutter = vicam->win.contrast / 256; if (shutter == 0) shutter = 1; printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter ); req[0] = vicam->win.brightness /256; shutter = 15600/shutter - 1; req[6] = shutter & 0xff; req[7] = (shutter >> 8) & 0xff; vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10); mdelay(10); vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10); mdelay(10); return 0;}static int vicam_init(struct usb_vicam *vicam){ int width[] = {128, 256, 512}; int height[] = {122, 242, 242}; dbg("vicam_init"); buf = kmalloc(0x1e480, GFP_KERNEL); buf2 = kmalloc(0x1e480, GFP_KERNEL); if ((!buf) || (!buf2)) { printk("Not enough memory for vicam!\n"); goto error; } /* do we do aspect correction in kernel or not? */ vicam->sizes = 3; vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL); vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL); memcpy(vicam->width, &width, sizeof(width)); memcpy(vicam->height, &height, sizeof(height)); vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1]; /* Download firmware to camera */ vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1)); vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1)); vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup)); vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2)); vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2)); vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup)); vicam_parameters(vicam); FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81), buf, 0x1e480, vicam_bulk, vicam); printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb)); return 0;error: if (buf) kfree(buf); if (buf2) kfree(buf2); return 1;}static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_vicam *vicam; char *camera_name=NULL; dbg("vicam_probe"); /* See if the device offered us matches what we can accept */ if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) || (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) { return NULL; } camera_name="3Com HomeConnect USB"; info("ViCAM camera found: %s", camera_name); vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL); if (vicam == NULL) { err ("couldn't kmalloc vicam struct"); return NULL; } memset(vicam, 0, sizeof(*vicam)); vicam->udev = udev; vicam->camera_name = camera_name; vicam->win.brightness = 128; vicam->win.contrast = 10; /* FIXME */ if (vicam_init(vicam)) return NULL; memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template)); memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name)); if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { err("video_register_device"); return NULL; } info("registered new video device: video%d", vicam->vdev.minor); init_MUTEX (&vicam->sem); init_waitqueue_head(&vicam->wait); return vicam;}/* FIXME - vicam_disconnect - important */static void vicam_disconnect(struct usb_device *udev, void *ptr){ struct usb_vicam *vicam; vicam = (struct usb_vicam *) ptr; if (!vicam->open_count) video_unregister_device(&vicam->vdev); vicam->udev = NULL;/* vicam->frame[0].grabstate = FRAME_ERROR; vicam->frame[1].grabstate = FRAME_ERROR;*/ /* Free buffers and shit */ info("%s disconnected", vicam->camera_name); synchronize(vicam); if (!vicam->open_count) { /* Other random junk */ kfree(vicam); vicam = NULL; }}/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver vicam_driver = { name: "vicam", probe: vicam_probe, disconnect: vicam_disconnect, id_table: vicam_table,};/****************************************************************************** * * Module Routines * ******************************************************************************/MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");/* Module paramaters */MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");static int __init usb_vicam_init(void){ int result; printk("VICAM: initializing\n"); /* register this driver with the USB subsystem */ result = usb_register(&vicam_driver); if (result < 0) { err("usb_register failed for the "__FILE__" driver. Error number %d", result); return -1; } info(DRIVER_VERSION " " DRIVER_AUTHOR); info(DRIVER_DESC); return 0;}static void __exit usb_vicam_exit(void){ /* deregister this driver with the USB subsystem */ usb_deregister(&vicam_driver);}module_init(usb_vicam_init);module_exit(usb_vicam_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -