📄 ultracam.c
字号:
/* * USB NB Camera driver */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/wrapper.h>#include <linux/module.h>#include <linux/init.h>#include "usbvideo.h"#define ULTRACAM_VENDOR_ID 0x0461#define ULTRACAM_PRODUCT_ID 0x0813#define MAX_CAMERAS 4 /* How many devices we allow to connect *//* * This structure lives in uvd_t->user field. */typedef struct { int initialized; /* Had we already sent init sequence? */ int camera_model; /* What type of IBM camera we got? */ int has_hdr;} ultracam_t;#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data))static usbvideo_t *cams = NULL;static int debug = 0;static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */static const int min_canvasWidth = 8;static const int min_canvasHeight = 4;//static int lighting = 1; /* Medium */#define SHARPNESS_MIN 0#define SHARPNESS_MAX 6//static int sharpness = 4; /* Low noise, good details */#define FRAMERATE_MIN 0#define FRAMERATE_MAX 6static int framerate = -1;/* * Here we define several initialization variables. They may * be used to automatically set color, hue, brightness and * contrast to desired values. This is particularly useful in * case of webcams (which have no controls and no on-screen * output) and also when a client V4L software is used that * does not have some of those controls. In any case it's * good to have startup values as options. * * These values are all in [0..255] range. This simplifies * operation. Note that actual values of V4L variables may * be scaled up (as much as << 8). User can see that only * on overlay output, however, or through a V4L client. */static int init_brightness = 128;static int init_contrast = 192;static int init_color = 128;static int init_hue = 128;static int hue_correction = 128;MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");MODULE_PARM(flags, "i");MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, " "1=B/W, " "2=show hints, " "3=show stats, " "4=test pattern, " "5=separate frames, " "6=clean frames");MODULE_PARM(framerate, "i");MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");MODULE_PARM(lighting, "i");MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");MODULE_PARM(sharpness, "i");MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");MODULE_PARM(init_brightness, "i");MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");MODULE_PARM(init_contrast, "i");MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");MODULE_PARM(init_color, "i");MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");MODULE_PARM(init_hue, "i");MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");MODULE_PARM(hue_correction, "i");MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");/* * ultracam_ProcessIsocData() * * Generic routine to parse the ring queue data. It employs either * ultracam_find_header() or ultracam_parse_lines() to do most * of work. * * 02-Nov-2000 First (mostly dummy) version. * 06-Nov-2000 Rewrote to dump all data into frame. */void ultracam_ProcessIsocData(uvd_t *uvd, usbvideo_frame_t *frame){ int n; assert(uvd != NULL); assert(frame != NULL); /* Try to move data from queue into frame buffer */ n = RingQueue_GetLength(&uvd->dp); if (n > 0) { int m; /* See how much spare we have left */ m = uvd->max_frame_size - frame->seqRead_Length; if (n > m) n = m; /* Now move that much data into frame buffer */ RingQueue_Dequeue( &uvd->dp, frame->data + frame->seqRead_Length, m); frame->seqRead_Length += m; } /* See if we filled the frame */ if (frame->seqRead_Length >= uvd->max_frame_size) { frame->frameState = FrameState_Done; uvd->curframe = -1; uvd->stats.frame_num++; }}/* * ultracam_veio() * * History: * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged. */static int ultracam_veio( uvd_t *uvd, unsigned char req, unsigned short value, unsigned short index, int is_out){ static const char proc[] = "ultracam_veio"; unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */; int i; if (!CAMERA_IS_OPERATIONAL(uvd)) return 0; if (!is_out) { i = usb_control_msg( uvd->dev, usb_rcvctrlpipe(uvd->dev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, cp, sizeof(cp), HZ);#if 1 info("USB => %02x%02x%02x%02x%02x%02x%02x%02x " "(req=$%02x val=$%04x ind=$%04x)", cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7], req, value, index);#endif } else { i = usb_control_msg( uvd->dev, usb_sndctrlpipe(uvd->dev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, index, NULL, 0, HZ); } if (i < 0) { err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.", proc, i); uvd->last_error = i; } return i;}/* * ultracam_calculate_fps() */static int ultracam_calculate_fps(uvd_t *uvd){ return 3 + framerate*4 + framerate/2;}/* * ultracam_adjust_contrast() */static void ultracam_adjust_contrast(uvd_t *uvd){}/* * ultracam_change_lighting_conditions() */static void ultracam_change_lighting_conditions(uvd_t *uvd){}/* * ultracam_set_sharpness() * * Cameras model 1 have internal smoothing feature. It is controlled by value in * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess). * Recommended value is 4. Cameras model 2 do not have this feature at all. */static void ultracam_set_sharpness(uvd_t *uvd){}/* * ultracam_set_brightness() * * This procedure changes brightness of the picture. */static void ultracam_set_brightness(uvd_t *uvd){}static void ultracam_set_hue(uvd_t *uvd){}/* * ultracam_adjust_picture() * * This procedure gets called from V4L interface to update picture settings. * Here we change brightness and contrast. */static void ultracam_adjust_picture(uvd_t *uvd){ ultracam_adjust_contrast(uvd); ultracam_set_brightness(uvd); ultracam_set_hue(uvd);}/* * ultracam_video_stop() * * This code tells camera to stop streaming. The interface remains * configured and bandwidth - claimed. */static void ultracam_video_stop(uvd_t *uvd){}/* * ultracam_reinit_iso() * * This procedure sends couple of commands to the camera and then * resets the video pipe. This sequence was observed to reinit the * camera or, at least, to initiate ISO data stream. */static void ultracam_reinit_iso(uvd_t *uvd, int do_stop){}static void ultracam_video_start(uvd_t *uvd){ ultracam_change_lighting_conditions(uvd); ultracam_set_sharpness(uvd); ultracam_reinit_iso(uvd, 0);}static int ultracam_resetPipe(uvd_t *uvd){ usb_clear_halt(uvd->dev, uvd->video_endp); return 0;}static int ultracam_alternateSetting(uvd_t *uvd, int setting){ static const char proc[] = "ultracam_alternateSetting"; int i; i = usb_set_interface(uvd->dev, uvd->iface, setting); if (i < 0) { err("%s: usb_set_interface error", proc); uvd->last_error = i; return -EBUSY; } return 0;}/* * Return negative code on failure, 0 on success. */static int ultracam_setup_on_open(uvd_t *uvd){ int setup_ok = 0; /* Success by default */ /* Send init sequence only once, it's large! */ if (!ULTRACAM_T(uvd)->initialized) { ultracam_alternateSetting(uvd, 0x04); ultracam_alternateSetting(uvd, 0x00); ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1); ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1); ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1); ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1); ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1); ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1); ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1); ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1); ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1); ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1); ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1); ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1); ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1); ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1); ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1); ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1); ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1); ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1); ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1); ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1); ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1); ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1); ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1); ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1); ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1); ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1); ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1); ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1); ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1); ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1); ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1); ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1); ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1); ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1); ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1); ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1); ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1); ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1); ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1); ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1); ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1); ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1); ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1); ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1); ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1); ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -