📄 vicam.c
字号:
{ struct vicam_camera *cam = dev->priv; int retval = 0; if (!cam) return -ENODEV; /* make this _really_ smp-safe */ if (down_interruptible(&cam->busy_lock)) return -EINTR; switch (ioctlnr) { /* query capabilites */ case VIDIOCGCAP: { struct video_capability b; DBG("VIDIOCGCAP\n"); strcpy(b.name, "ViCam-based Camera"); b.type = VID_TYPE_CAPTURE; b.channels = 1; b.audios = 0; b.maxwidth = 320; /* VIDEOSIZE_CIF */ b.maxheight = 240; b.minwidth = 320; /* VIDEOSIZE_48_48 */ b.minheight = 240; if (copy_to_user(arg, &b, sizeof (b))) retval = -EFAULT; break; } /* get/set video source - we are a camera and nothing else */ case VIDIOCGCHAN: { struct video_channel v; DBG("VIDIOCGCHAN\n"); if (copy_from_user(&v, arg, sizeof (v))) { retval = -EFAULT; break; } if (v.channel != 0) { retval = -EINVAL; break; } v.channel = 0; strcpy(v.name, "Camera"); v.tuners = 0; v.flags = 0; v.type = VIDEO_TYPE_CAMERA; v.norm = 0; if (copy_to_user(arg, &v, sizeof (v))) retval = -EFAULT; break; } case VIDIOCSCHAN: { int v; if (copy_from_user(&v, arg, sizeof (v))) retval = -EFAULT; DBG("VIDIOCSCHAN %d\n", v); if (retval == 0 && v != 0) retval = -EINVAL; break; } /* image properties */ case VIDIOCGPICT: { struct video_picture vp; DBG("VIDIOCGPICT\n"); memset(&vp, 0, sizeof (struct video_picture)); vp.brightness = cam->gain << 8; vp.depth = 24; vp.palette = VIDEO_PALETTE_RGB24; if (copy_to_user (arg, &vp, sizeof (struct video_picture))) retval = -EFAULT; break; } case VIDIOCSPICT: { struct video_picture vp; if(copy_from_user(&vp, (struct video_picture *) arg, sizeof(struct video_picture))) retval = -EFAULT; else { DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth, vp.palette); cam->gain = vp.brightness >> 8; if (vp.depth != 24 || vp.palette != VIDEO_PALETTE_RGB24) retval = -EINVAL; } break; } /* get/set capture window */ case VIDIOCGWIN: { struct video_window vw; vw.x = 0; vw.y = 0; vw.width = 320; vw.height = 240; vw.chromakey = 0; vw.flags = 0; vw.clips = NULL; vw.clipcount = 0; DBG("VIDIOCGWIN\n"); if (copy_to_user ((void *) arg, (void *) &vw, sizeof (vw))) retval = -EFAULT; // I'm not sure what the deal with a capture window is, it is very poorly described // in the doc. So I won't support it now. break; } case VIDIOCSWIN: { struct video_window *vw = (struct video_window *) arg; DBG("VIDIOCSWIN %d x %d\n", vw->width, vw->height); if ( vw->width != 320 || vw->height != 240 ) retval = -EFAULT; break; } /* mmap interface */ case VIDIOCGMBUF: { struct video_mbuf vm; int i; DBG("VIDIOCGMBUF\n"); memset(&vm, 0, sizeof (vm)); vm.size = VICAM_MAX_FRAME_SIZE * VICAM_FRAMES; vm.frames = VICAM_FRAMES; for (i = 0; i < VICAM_FRAMES; i++) vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i; if (copy_to_user ((void *) arg, (void *) &vm, sizeof (vm))) retval = -EFAULT; break; } case VIDIOCMCAPTURE: { struct video_mmap vm; // int video_size; if (copy_from_user ((void *) &vm, (void *) arg, sizeof (vm))) { retval = -EFAULT; break; } DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format); if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 ) retval = -EINVAL; // in theory right here we'd start the image capturing // (fill in a bulk urb and submit it asynchronously) // // Instead we're going to do a total hack job for now and // retrieve the frame in VIDIOCSYNC break; } case VIDIOCSYNC: { int frame; if (copy_from_user((void *) &frame, arg, sizeof (int))) { retval = -EFAULT; break; } DBG("VIDIOCSYNC: %d\n", frame); read_frame(cam, frame); break; } /* pointless to implement overlay with this camera */ case VIDIOCCAPTURE: case VIDIOCGFBUF: case VIDIOCSFBUF: case VIDIOCKEY: retval = -EINVAL; break; /* tuner interface - we have none */ case VIDIOCGTUNER: case VIDIOCSTUNER: case VIDIOCGFREQ: case VIDIOCSFREQ: retval = -EINVAL; break; /* audio interface - we have none */ case VIDIOCGAUDIO: case VIDIOCSAUDIO: retval = -EINVAL; break; default: retval = -ENOIOCTLCMD; break; } up(&cam->busy_lock); return retval;}static intvicam_open(struct video_device *dev, int flags){ struct vicam_camera *cam = (struct vicam_camera *) dev->priv; DBG("open\n"); if (!cam) { printk(KERN_ERR "vicam video_device improperly initialized"); } down_interruptible(&cam->busy_lock); if (cam->open_count > 0) { printk(KERN_INFO "vicam_open called on already opened camera"); up(&cam->busy_lock); return -EBUSY; } if (!cam->raw_image) { cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL); if (!cam->raw_image) { up(&cam->busy_lock); return -ENOMEM; } } if (!cam->framebuf) { cam->framebuf = usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES); if (!cam->framebuf) { kfree(cam->raw_image); up(&cam->busy_lock); return -ENOMEM; } } // First upload firmware, then turn the camera on if (!cam->is_initialized) { initialize_camera(cam); cam->is_initialized = 1; } set_camera_power(cam, 1); cam->needsDummyRead = 1; cam->open_count++; up(&cam->busy_lock); return 0;}static voidvicam_close(struct video_device *dev){ DBG("close\n"); set_camera_power((struct vicam_camera *) dev->priv, 0); ((struct vicam_camera *) dev->priv)->open_count--;}inline int pin(int x){ return((x > 255) ? 255 : ((x < 0) ? 0 : x));}inline void writepixel(char *rgb, int Y, int Cr, int Cb){ Y = 1160 * (Y - 16); rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 ); rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 ); rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );}#define DATA_HEADER_SIZE 64// --------------------------------------------------------------------------------// vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB//// Copyright (C) 2002 Monroe Williams (monroe@pobox.com)// --------------------------------------------------------------------------------void vicam_decode_color( char *data, char *rgb){ int x,y; int Cr, Cb; int sign; int prevX, nextX, prevY, nextY; int skip; unsigned char *src; unsigned char *dst; prevY = 512; nextY = 512; src = data + DATA_HEADER_SIZE; dst = rgb; for(y = 1; y < 241; y += 2) { // even line sign = 1; prevX = 1; nextX = 1; skip = 0; dst = rgb + (y-1)*320*3; for(x = 0; x < 512; x++) { if(x == 512-1) nextX = -1; Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1; Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2; writepixel( dst + ((x*5)>>3)*3, src[0] + (sign * (Cr >> 1)), Cr, Cb); src++; sign *= -1; prevX = -1; } prevY = -512; if(y == (242 - 2)) nextY = -512; // odd line sign = 1; prevX = 1; nextX = 1; skip = 0; dst = rgb + (y)*320*3; for(x = 0; x < 512; x++) { if(x == 512-1) nextX = -1; Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2; Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1; writepixel( dst + ((x * 5)>>3)*3, src[0] - (sign * (Cb >> 1)), Cr, Cb); src++; sign *= -1; prevX = -1; } }}static voidread_frame(struct vicam_camera *cam, int framenum){ unsigned char request[16]; int realShutter; int n; int actual_length; memset(request, 0, 16); request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain request[1] = 0; // 512x242 capture request[2] = 0x90; // the function of these two bytes request[3] = 0x07; // is not yet understood 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 n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16); if (n < 0) { printk(KERN_ERR " Problem sending frame capture control message"); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -