📄 stv680.c
字号:
if (stv680->SupportedModes == 0) { PDEBUG (0, "STV(e): There are NO supported STV680 modes!!"); i = -1; goto error; } else { if (stv680->CIF) PDEBUG (0, "STV(i): CIF is supported"); if (stv680->QVGA) PDEBUG (0, "STV(i): QVGA is supported"); } /* FW rev, ASIC rev, sensor ID */ PDEBUG (1, "STV(i): Firmware rev is %i.%i", buffer[0], buffer[1]); PDEBUG (1, "STV(i): ASIC rev is %i.%i", buffer[2], buffer[3]); PDEBUG (1, "STV(i): Sensor ID is %i", (buffer[4]*16) + (buffer[5]>>4)); /* set alternate interface 1 */ if ((i = stv_set_config (stv680, 1, 0, 1)) < 0) goto error; if ((i = stv_sndctrl (0, stv680, 0x85, 0, buffer, 0x10)) != 0x10) goto error; if ((i = stv_sndctrl (0, stv680, 0x8d, 0, buffer, 0x08)) != 0x08) goto error; i = buffer[3]; PDEBUG (0, "STV(i): Camera has %i pictures.", i); /* get current mode */ if ((i = stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08)) != 0x08) goto error; stv680->origMode = buffer[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */ /* This will attemp CIF mode, if supported. If not, set to QVGA */ memset (buffer, 0, 8); if (stv680->CIF) buffer[0] = 0x00; else if (stv680->QVGA) buffer[0] = 0x03; if ((i = stv_sndctrl (3, stv680, 0x07, 0x0100, buffer, 0x08)) != 0x08) { PDEBUG (0, "STV(i): Set_Camera_Mode failed"); i = -1; goto error; } buffer[0] = 0xf0; stv_sndctrl (0, stv680, 0x87, 0, buffer, 0x08); if (((stv680->CIF == 1) && (buffer[0] != 0x00)) || ((stv680->QVGA == 1) && (buffer[0] != 0x03))) { PDEBUG (0, "STV(e): Error setting camera video mode!"); i = -1; goto error; } else { if (buffer[0] == 0) { stv680->VideoMode = 0x0000; PDEBUG (0, "STV(i): Video Mode set to CIF"); } if (buffer[0] == 0x03) { stv680->VideoMode = 0x0300; PDEBUG (0, "STV(i): Video Mode set to QVGA"); } } if ((i = stv_sndctrl (0, stv680, 0x8f, 0, buffer, 0x10)) != 0x10) goto error; bufsize = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3]); stv680->cwidth = (buffer[4] << 8) | (buffer[5]); /* ->camera = 322, 356, 644 */ stv680->cheight = (buffer[6] << 8) | (buffer[7]); /* ->camera = 242, 292, 484 */ stv680->origGain = buffer[12]; goto exit;error: i = stv_sndctrl (0, stv680, 0x80, 0, buffer, 0x02); /* Get Last Error */ PDEBUG (1, "STV(i): last error: %i, command = 0x%x", buffer[0], buffer[1]); kfree (buffer); return -1;exit: kfree (buffer); /* video = 320x240, 352x288 */ if (stv680->CIF == 1) { stv680->maxwidth = 352; stv680->maxheight = 288; stv680->vwidth = 352; stv680->vheight = 288; } if (stv680->QVGA == 1) { stv680->maxwidth = 320; stv680->maxheight = 240; stv680->vwidth = 320; stv680->vheight = 240; } stv680->rawbufsize = bufsize; /* must be ./. by 8 */ stv680->maxframesize = bufsize * 3; /* RGB size */ PDEBUG (2, "STV(i): cwidth = %i, cheight = %i", stv680->cwidth, stv680->cheight); PDEBUG (1, "STV(i): width = %i, height = %i, rawbufsize = %li", stv680->vwidth, stv680->vheight, stv680->rawbufsize); /* some default values */ stv680->bulk_in_endpointAddr = 0x82; stv680->dropped = 0; stv680->error = 0; stv680->framecount = 0; stv680->readcount = 0; stv680->streaming = 0; /* bright, white, colour, hue, contrast are set by software, not in stv0680 */ stv680->brightness = 32767; stv680->chgbright = 0; stv680->whiteness = 0; /* only for greyscale */ stv680->colour = 32767; stv680->contrast = 32767; stv680->hue = 32767; stv680->palette = STV_VIDEO_PALETTE; stv680->depth = 24; /* rgb24 bits */ swapRGB = 0; if ((swapRGB_on == 0) && (swapRGB == 0)) PDEBUG (1, "STV(i): swapRGB is (auto) OFF"); else if ((swapRGB_on == 1) && (swapRGB == 1)) PDEBUG (1, "STV(i): swapRGB is (auto) ON"); else if (swapRGB_on == 1) PDEBUG (1, "STV(i): swapRGB is (forced) ON"); else if (swapRGB_on == -1) PDEBUG (1, "STV(i): swapRGB is (forced) OFF"); if (stv_set_video_mode (stv680) < 0) { PDEBUG (0, "STV(e): Could not set video mode in stv_init"); return -1; } return 0;}/***************** last of pencam routines *******************//******************************************************************** * /proc interface *******************************************************************/#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)static struct proc_dir_entry *stv680_proc_entry = NULL;extern struct proc_dir_entry *video_proc_entry;#define YES_NO(x) ((x) ? "yes" : "no")#define ON_OFF(x) ((x) ? "(auto) on" : "(auto) off")static int stv680_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data){ char *out = page; int len; struct usb_stv *stv680 = data; /* Stay under PAGE_SIZE or else bla bla bla.... */ out += sprintf (out, "driver_version : %s\n", DRIVER_VERSION); out += sprintf (out, "model : %s\n", stv680->camera_name); out += sprintf (out, "in use : %s\n", YES_NO (stv680->user)); out += sprintf (out, "streaming : %s\n", YES_NO (stv680->streaming)); out += sprintf (out, "num_frames : %d\n", STV680_NUMFRAMES); out += sprintf (out, "Current size : %ix%i\n", stv680->vwidth, stv680->vheight); if (swapRGB_on == 0) out += sprintf (out, "swapRGB : %s\n", ON_OFF (swapRGB)); else if (swapRGB_on == 1) out += sprintf (out, "swapRGB : (forced) on\n"); else if (swapRGB_on == -1) out += sprintf (out, "swapRGB : (forced) off\n"); out += sprintf (out, "Palette : %i", stv680->palette); out += sprintf (out, "\n"); out += sprintf (out, "Frames total : %d\n", stv680->readcount); out += sprintf (out, "Frames read : %d\n", stv680->framecount); out += sprintf (out, "Packets dropped : %d\n", stv680->dropped); out += sprintf (out, "Decoding Errors : %d\n", stv680->error); 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 create_proc_stv680_cam (struct usb_stv *stv680){ char name[9]; struct proc_dir_entry *ent; if (!stv680_proc_entry || !stv680) return -1; sprintf (name, "video%d", stv680->vdev.minor); ent = create_proc_entry (name, S_IFREG | S_IRUGO | S_IWUSR, stv680_proc_entry); if (!ent) return -1; ent->data = stv680; ent->read_proc = stv680_read_proc; stv680->proc_entry = ent; return 0;}static void destroy_proc_stv680_cam (struct usb_stv *stv680){ /* One to much, just to be sure :) */ char name[9]; if (!stv680 || !stv680->proc_entry) return; sprintf (name, "video%d", stv680->vdev.minor); remove_proc_entry (name, stv680_proc_entry); stv680->proc_entry = NULL;}static int proc_stv680_create (void){ if (video_proc_entry == NULL) { PDEBUG (0, "STV(e): /proc/video/ doesn't exist!"); return -1; } stv680_proc_entry = create_proc_entry ("stv680", S_IFDIR, video_proc_entry); if (stv680_proc_entry) { stv680_proc_entry->owner = THIS_MODULE; } else { PDEBUG (0, "STV(e): Unable to initialize /proc/video/stv680"); return -1; } return 0;}static void proc_stv680_destroy (void){ if (stv680_proc_entry == NULL) return; remove_proc_entry ("stv", video_proc_entry);}#endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS *//******************************************************************** * Camera control *******************************************************************/static int stv680_get_pict (struct usb_stv *stv680, struct video_picture *p){ /* This sets values for v4l interface. max/min = 65535/0 */ p->brightness = stv680->brightness; p->whiteness = stv680->whiteness; /* greyscale */ p->colour = stv680->colour; p->contrast = stv680->contrast; p->hue = stv680->hue; p->palette = stv680->palette; p->depth = stv680->depth; return 0;}static int stv680_set_pict (struct usb_stv *stv680, struct video_picture *p){ /* See above stv680_get_pict */ if (p->palette != STV_VIDEO_PALETTE) { PDEBUG (2, "STV(e): Palette set error in _set_pic"); return 1; } if (stv680->brightness != p->brightness) { stv680->chgbright = 1; stv680->brightness = p->brightness; } stv680->whiteness = p->whiteness; /* greyscale */ stv680->colour = p->colour; stv680->contrast = p->contrast; stv680->hue = p->hue; stv680->palette = p->palette; stv680->depth = p->depth; return 0;}static void stv680_video_irq (struct urb *urb){ struct usb_stv *stv680 = urb->context; int length = urb->actual_length; if (length < stv680->rawbufsize) PDEBUG (2, "STV(i): Lost data in transfer: exp %li, got %i", stv680->rawbufsize, length); /* ohoh... */ if (!stv680->streaming) return; if (!stv680->udev) { PDEBUG (0, "STV(e): device vapourished in video_irq"); return; } /* 0 sized packets happen if we are to fast, but sometimes the camera keeps sending them forever... */ if (length && !urb->status) { stv680->nullpackets = 0; switch (stv680->scratch[stv680->scratch_next].state) { case BUFFER_READY: case BUFFER_BUSY: stv680->dropped++; break; case BUFFER_UNUSED: memcpy (stv680->scratch[stv680->scratch_next].data, (unsigned char *) urb->transfer_buffer, length); stv680->scratch[stv680->scratch_next].state = BUFFER_READY; stv680->scratch[stv680->scratch_next].length = length; if (waitqueue_active (&stv680->wq)) { wake_up_interruptible (&stv680->wq); } stv680->scratch_overflow = 0; stv680->scratch_next++; if (stv680->scratch_next >= STV680_NUMSCRATCH) stv680->scratch_next = 0;; break; } /* switch */ } else { stv680->nullpackets++; if (stv680->nullpackets > STV680_MAX_NULLPACKETS) { if (waitqueue_active (&stv680->wq)) { wake_up_interruptible (&stv680->wq); } } } /* if - else */ /* Resubmit urb for new data */ urb->status = 0; urb->dev = stv680->udev; if (usb_submit_urb (urb)) PDEBUG (0, "STV(e): urb burned down in video irq"); return;} /* _video_irq */static int stv680_start_stream (struct usb_stv *stv680){ urb_t *urb; int err = 0, i; stv680->streaming = 1; /* Do some memory allocation */ for (i = 0; i < STV680_NUMFRAMES; i++) { stv680->frame[i].data = stv680->fbuf + i * stv680->maxframesize; stv680->frame[i].curpix = 0; } /* packet size = 4096 */ for (i = 0; i < STV680_NUMSBUF; i++) { stv680->sbuf[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); if (stv680->sbuf[i].data == NULL) { PDEBUG (0, "STV(e): Could not kmalloc raw data buffer %i", i); return -1; } } stv680->scratch_next = 0; stv680->scratch_use = 0; stv680->scratch_overflow = 0; for (i = 0; i < STV680_NUMSCRATCH; i++) { stv680->scratch[i].data = kmalloc (stv680->rawbufsize, GFP_KERNEL); if (stv680->scratch[i].data == NULL) { PDEBUG (0, "STV(e): Could not kmalloc raw scratch buffer %i", i); return -1; } stv680->scratch[i].state = BUFFER_UNUSED; } for (i = 0; i < STV680_NUMSBUF; i++) { urb = usb_alloc_urb (0); if (!urb) return ENOMEM; /* sbuf is urb->transfer_buffer, later gets memcpyed to scratch */ usb_fill_bulk_urb (urb, stv680->udev, usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr), stv680->sbuf[i].data, stv680->rawbufsize, stv680_video_irq, stv680); urb->timeout = PENCAM_TIMEOUT * 2; urb->transfer_flags |= USB_QUEUE_BULK; stv680->urb[i] = urb; err = usb_submit_urb (stv680->urb[i]); if (err) PDEBUG (0, "STV(e): urb burned down in start stream"); } /* i STV680_NUMSBUF */ stv680->framecount = 0; return 0;}static int stv680_stop_stream (struct usb_stv *stv680){ int i; if (!stv680->streaming || !stv680->udev) return 1; stv680->streaming = 0; 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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -