📄 vicam.c
字号:
if (cam->shutter_speed > 60) { // Short exposure realShutter = ((-15631900 / cam->shutter_speed) + 260533) / 1000; request[4] = realShutter & 0xFF; request[5] = (realShutter >> 8) & 0xFF; request[6] = 0x03; request[7] = 0x01; } else { // Long exposure realShutter = 15600 / cam->shutter_speed - 1; request[4] = 0; request[5] = 0; request[6] = realShutter & 0xFF; request[7] = realShutter >> 8; } // Per John Markus Bj鴕ndalen, byte at index 8 causes problems if it isn't 0 request[8] = 0; // bytes 9-15 do not seem to affect exposure or image quality down(&cam->cam_lock); if (!cam->udev) { goto done; } n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16); if (n < 0) { printk(KERN_ERR " Problem sending frame capture control message"); goto done; } n = usb_bulk_msg(cam->udev, usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint), cam->raw_image, 512 * 242 + 128, &actual_length, 10000); if (n < 0) { printk(KERN_ERR "Problem during bulk read of frame data: %d\n", n); } done: up(&cam->cam_lock);}static ssize_tvicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ){ struct vicam_camera *cam = file->private_data; DBG("read %d bytes.\n", (int) count); if (*ppos >= VICAM_MAX_FRAME_SIZE) { *ppos = 0; return 0; } if (*ppos == 0) { read_frame(cam, 0); vicam_decode_color(cam->raw_image, cam->framebuf + 0 * VICAM_MAX_FRAME_SIZE); } count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos); if (copy_to_user(buf, &cam->framebuf[*ppos], count)) { count = -EFAULT; } else { *ppos += count; } if (count == VICAM_MAX_FRAME_SIZE) { *ppos = 0; } return count;}static intvicam_mmap(struct file *file, struct vm_area_struct *vma){ // TODO: allocate the raw frame buffer if necessary unsigned long page, pos; unsigned long start = vma->vm_start; unsigned long size = vma->vm_end-vma->vm_start; struct vicam_camera *cam = file->private_data; if (!cam) return -ENODEV; DBG("vicam_mmap: %ld\n", size); /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes * to the size the application requested for mmap and it was screwing apps up. if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE) return -EINVAL; */ pos = (unsigned long)cam->framebuf; while (size > 0) { page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } return 0;}#if defined(CONFIG_VIDEO_PROC_FS)static struct proc_dir_entry *vicam_proc_root = NULL;static int vicam_read_helper(char *page, char **start, off_t off, int count, int *eof, int value){ char *out = page; int len; out += sprintf(out, "%d",value); len = out - page; len -= off; if (len < count) { *eof = 1; if (len <= 0) return 0; } else len = count; *start = page + off; return len;}static int vicam_read_proc_shutter(char *page, char **start, off_t off, int count, int *eof, void *data){ return vicam_read_helper(page,start,off,count,eof, ((struct vicam_camera *)data)->shutter_speed);}static int vicam_read_proc_gain(char *page, char **start, off_t off, int count, int *eof, void *data){ return vicam_read_helper(page,start,off,count,eof, ((struct vicam_camera *)data)->gain);}static intvicam_write_proc_shutter(struct file *file, const char *buffer, unsigned long count, void *data){ u16 stmp; char kbuf[8]; struct vicam_camera *cam = (struct vicam_camera *) data; if (count > 6) return -EINVAL; if (copy_from_user(kbuf, buffer, count)) return -EFAULT; stmp = (u16) simple_strtoul(kbuf, NULL, 10); if (stmp < 4 || stmp > 32000) return -EINVAL; cam->shutter_speed = stmp; return count;}static intvicam_write_proc_gain(struct file *file, const char *buffer, unsigned long count, void *data){ u16 gtmp; char kbuf[8]; struct vicam_camera *cam = (struct vicam_camera *) data; if (count > 4) return -EINVAL; if (copy_from_user(kbuf, buffer, count)) return -EFAULT; gtmp = (u16) simple_strtoul(kbuf, NULL, 10); if (gtmp > 255) return -EINVAL; cam->gain = gtmp; return count;}static voidvicam_create_proc_root(void){ vicam_proc_root = proc_mkdir("video/vicam", NULL); if (vicam_proc_root) vicam_proc_root->owner = THIS_MODULE; else printk(KERN_ERR "could not create /proc entry for vicam!");}static voidvicam_destroy_proc_root(void){ if (vicam_proc_root) remove_proc_entry("video/vicam", 0);}static voidvicam_create_proc_entry(struct vicam_camera *cam){ char name[64]; struct proc_dir_entry *ent; DBG(KERN_INFO "vicam: creating proc entry\n"); if (!vicam_proc_root || !cam) { printk(KERN_INFO "vicam: could not create proc entry, %s pointer is null.\n", (!cam ? "camera" : "root")); return; } sprintf(name, "video%d", cam->vdev.minor); cam->proc_dir = proc_mkdir(name, vicam_proc_root); if ( !cam->proc_dir ) return; // FIXME: We should probably return an error here ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, cam->proc_dir); if (ent) { ent->data = cam; ent->read_proc = vicam_read_proc_shutter; ent->write_proc = vicam_write_proc_shutter; ent->size = 64; } ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, cam->proc_dir); if (ent) { ent->data = cam; ent->read_proc = vicam_read_proc_gain; ent->write_proc = vicam_write_proc_gain; ent->size = 64; }}static voidvicam_destroy_proc_entry(void *ptr){ struct vicam_camera *cam = (struct vicam_camera *) ptr; char name[16]; if ( !cam->proc_dir ) return; sprintf(name, "video%d", cam->vdev.minor); remove_proc_entry("shutter", cam->proc_dir); remove_proc_entry("gain", cam->proc_dir); remove_proc_entry(name,vicam_proc_root); cam->proc_dir = NULL;}#elsestatic inline void vicam_create_proc_root(void) { }static inline void vicam_destroy_proc_root(void) { }static inline void vicam_create_proc_entry(struct vicam_camera *cam) { }static inline void vicam_destroy_proc_entry(void *ptr) { }#endifstatic struct file_operations vicam_fops = { .owner = THIS_MODULE, .open = vicam_open, .release = vicam_close, .read = vicam_read, .mmap = vicam_mmap, .ioctl = vicam_ioctl, .llseek = no_llseek,};static struct video_device vicam_template = { .owner = THIS_MODULE, .name = "ViCam-based USB Camera", .type = VID_TYPE_CAPTURE, .hardware = VID_HARDWARE_VICAM, .fops = &vicam_fops, .minor = -1,};/* table of devices that work with this driver */static struct usb_device_id vicam_table[] = { {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)}, {} /* Terminating entry */};MODULE_DEVICE_TABLE(usb, vicam_table);static struct usb_driver vicam_driver = { .owner = THIS_MODULE, .name = "vicam", .probe = vicam_probe, .disconnect = vicam_disconnect, .id_table = vicam_table};/** * vicam_probe * @intf: the interface * @id: the device id * * Called by the usb core when a new device is connected that it thinks * this driver might be interested in. */static intvicam_probe( struct usb_interface *intf, const struct usb_device_id *id){ struct usb_device *dev = interface_to_usbdev(intf); int bulkEndpoint = 0; const struct usb_host_interface *interface; const struct usb_endpoint_descriptor *endpoint; struct vicam_camera *cam; printk(KERN_INFO "ViCam based webcam connected\n"); interface = intf->cur_altsetting; DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n", interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints)); endpoint = &interface->endpoint[0].desc; if ((endpoint->bEndpointAddress & 0x80) && ((endpoint->bmAttributes & 3) == 0x02)) { /* we found a bulk in endpoint */ bulkEndpoint = endpoint->bEndpointAddress; } else { printk(KERN_ERR "No bulk in endpoint was found ?! (this is bad)\n"); } if ((cam = kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) { printk(KERN_WARNING "could not allocate kernel memory for vicam_camera struct\n"); return -ENOMEM; } memset(cam, 0, sizeof (struct vicam_camera)); cam->shutter_speed = 15; init_MUTEX(&cam->cam_lock); memcpy(&cam->vdev, &vicam_template, sizeof (vicam_template)); cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only cam->udev = dev; cam->bulkEndpoint = bulkEndpoint; if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) { kfree(cam); printk(KERN_WARNING "video_register_device failed\n"); return -EIO; } vicam_create_proc_entry(cam); printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor); usb_set_intfdata (intf, cam); return 0;}static voidvicam_disconnect(struct usb_interface *intf){ int open_count; struct vicam_camera *cam = usb_get_intfdata (intf); usb_set_intfdata (intf, NULL); /* we must unregister the device before taking its * cam_lock. This is because the video open call * holds the same lock as video unregister. if we * unregister inside of the cam_lock and open also * uses the cam_lock, we get deadlock. */ video_unregister_device(&cam->vdev); /* stop the camera from being used */ down(&cam->cam_lock); /* mark the camera as gone */ cam->udev = NULL; vicam_destroy_proc_entry(cam); /* the only thing left to do is synchronize with * our close/release function on who should release * the camera memory. if there are any users using the * camera, it's their job. if there are no users, * it's ours. */ open_count = cam->open_count; up(&cam->cam_lock); if (!open_count) { kfree(cam); } printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");}/* */static int __initusb_vicam_init(void){ int retval; DBG(KERN_INFO "ViCam-based WebCam driver startup\n"); vicam_create_proc_root(); retval = usb_register(&vicam_driver); if (retval) printk(KERN_WARNING "usb_register failed!\n"); return retval;}static void __exitusb_vicam_exit(void){ DBG(KERN_INFO "ViCam-based WebCam driver shutdown\n"); usb_deregister(&vicam_driver); vicam_destroy_proc_root();}module_init(usb_vicam_init);module_exit(usb_vicam_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -