📄 gspca_core.c
字号:
{USB_DEVICE(0x046d, 0x092d)}, /* Logitech QC Elch2 */ {USB_DEVICE(0x046d, 0x092e)}, /* Logitech QC Elch2 */ {USB_DEVICE(0x046d, 0x092f)}, /* Logitech QC Elch2 */ {USB_DEVICE(0x041e, 0x4051)}, /* Creative Live!Cam Notebook Pro (VF0250) */ {USB_DEVICE(0x041E, 0x4029)}, /* Creative WebCam Vista Pro */ {USB_DEVICE(0x041E, 0x041E)}, /* Creative WebCam Live! */ {USB_DEVICE(0x041e, 0x4053)}, /* Creative Live!Cam Video IM */ {USB_DEVICE(0x046d, 0x08d7)}, /* Logitech QCam STX */ {USB_DEVICE(0x046d, 0x08d8)}, /* Logitech Notebook Deluxe */ {USB_DEVICE(0x08ca, 0x2040)}, /* Aiptek PocketDV4100M */ {USB_DEVICE(0x0c45, 0x612c)}, /* Typhoon Rasy Cam 1.3MPix */ {USB_DEVICE(0x0c45, 0x613b)}, /* Surfer SN-206 */ {USB_DEVICE(0x0c45, 0x60fb)}, /* Surfer NoName */ {USB_DEVICE(0x0ac8, 0xc002)}, /* Sony embedded vimicro */ {USB_DEVICE(0x0ac8, 0x0321)}, /* Vimicro generic vc0321 */ {USB_DEVICE(0x046d, 0x0892)}, /* Logitech Orbicam */ {USB_DEVICE(0x046d, 0x0896)}, /* Logitech Orbicam */ {USB_DEVICE(0x045e, 0x00f7)}, /* MicroSoft VX1000 */ {USB_DEVICE(0x045e, 0x00f5)}, /* MicroSoft VX3000 */ {USB_DEVICE(0x0471, 0x032d)}, /* Philips spc210nc */ {USB_DEVICE(0x06d6, 0x0031)}, /* Trust 610 LCD PowerC@m Zoom (webcam mode) */ {USB_DEVICE(0x0ac8, 0xc001)}, /* Sony embedded vimicro */ {USB_DEVICE(0x0471, 0x032e)}, /* Philips spc315nc */ {USB_DEVICE(0x0c45, 0x6138)}, /* Sn9c120 Mo4000 */ {USB_DEVICE(0x041E, 0x401a)}, /* Creative Webcam Vista (PD1100) */ {USB_DEVICE(0x0458, 0x7025)}, /* Genius Eye 311Q sn9c120+Mi360 */ {USB_DEVICE(0x093a, 0x2600)}, /* PAC7311 Typhoon */ {USB_DEVICE(0x093a, 0x2601)}, /* PAC7311 Phillips SPC610NC */ {USB_DEVICE(0x093a, 0x2603)}, /* PAC7312 */ {USB_DEVICE(0x093a, 0x2608)}, /* PAC7311 Trust WB-3300p */ {USB_DEVICE(0x093a, 0x260e)}, /* PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350 */ {USB_DEVICE(0x093a, 0x260f)}, /* PAC7311 SnakeCam */ {USB_DEVICE(0x0471, 0x0322)}, /* Philips DMVC1300K */ {USB_DEVICE(0x0d64, 0x0303)}, /* Sunplus FashionCam DXG */ {USB_DEVICE(0x0ac8, 0x307b)}, /* Ldlc VC302+Ov7620 */ {USB_DEVICE(0x0ac8, 0x0328)}, /* A4Tech PK-130MG */ {USB_DEVICE(0x0c45, 0x60ec)}, /* SN9C105+MO4000 */ {USB_DEVICE(0x0471, 0x0330)}, /* Philips SPC 710NC */ {USB_DEVICE(0x0ac8, 0x0323)}, /* Vimicro Vc0323 */ {USB_DEVICE(0x17ef, 0x4802)}, /* Lenovo Vc0323+MI1310_SOC */ {USB_DEVICE(0x046d, 0x08dd)}, /* Logitech QuickCam for Notebooks */ {USB_DEVICE(0x046d, 0x08af)}, /* Logitech QuickCam Cool */ {USB_DEVICE(0x093a, 0x2472)}, /* PAC207 Genius VideoCam ge110 */ {USB_DEVICE(0x093a, 0x2463)}, /* Philips spc200nc pac207 */ {USB_DEVICE(0x0000, 0x0000)}, /* MystFromOri Unknow Camera */ {} /* Terminating entry */};MODULE_DEVICE_TABLE(usb, device_table);/*Let's include the initialization data for each camera type*/#include "utils/spcausb.h"#include "Sunplus/spca501_init.h"#include "Sunplus/spca505_init.h"#include "Sunplus/spca506.h"#include "Sunplus/spca508_init.h"#include "Sunplus/spca561.h"#include "Sunplus-jpeg/jpeg_qtables.h"#include "Sunplus-jpeg/spca500_init.h"#include "Sunplus-jpeg/sp5xxfw2.h"#include "Sonix/sonix.h"#include "Vimicro/zc3xx.h"#include "Conexant/cx11646.h"#include "Transvision/tv8532.h"#include "Etoms/et61xx51.h"#include "Mars-Semi/mr97311.h"#include "Pixart/pac207.h"#include "Pixart/pac7311.h"#include "Vimicro/vc032x.h"/* function for the tasklet */void outpict_do_tasklet(unsigned long ptr);/************************************************************************ Memory management**********************************************************************/static inline unsigned longkvirt_to_pa(unsigned long adr){ unsigned long kva, ret; kva = (unsigned long) page_address(vmalloc_to_page((void *) adr)); kva |= adr & (PAGE_SIZE - 1); ret = __pa(kva); return ret;}static void *rvmalloc(unsigned long size){ void *mem; unsigned long adr; size = PAGE_ALIGN(size); mem = vmalloc_32(size); if (!mem) return NULL; memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr = (unsigned long) mem; while ((long) size > 0) { SetPageReserved(vmalloc_to_page((void *) adr)); adr += PAGE_SIZE; size -= PAGE_SIZE; } return mem;}static voidrvfree(void *mem, unsigned long size){ unsigned long adr; if (!mem) return; adr = (unsigned long) mem; while ((long) size > 0) { ClearPageReserved(vmalloc_to_page((void *) adr)); adr += PAGE_SIZE; size -= PAGE_SIZE; } vfree(mem);}/* ------------------------------------------------------------------------ *//*** Endpoint management we assume one isoc endpoint per device* that is not true some Zoran 0x0572:0x0001 have two* assume ep adresse is static know * FIXME as I don't know how to set the bandwith budget* we allow the maximum**/static struct usb_host_endpoint *gspca_set_isoc_ep(struct usb_spca50x *spca50x, int nbalt){ int i, j; struct usb_interface *intf; struct usb_host_endpoint *ep; struct usb_device *dev = spca50x->dev; struct usb_host_interface *altsetting = NULL; int error = 0; PDEBUG(3, "enter get iso ep "); intf = usb_ifnum_to_if(dev, spca50x->iface);/* bandwith budget can be set here */ for (i = nbalt; i; i--) { altsetting = &intf->altsetting[i]; for (j = 0; j < altsetting->desc.bNumEndpoints; ++j) { ep = &altsetting->endpoint[j]; PDEBUG(3, "test ISO EndPoint %d", ep->desc.bEndpointAddress); if ((ep->desc.bEndpointAddress == (spca50x->epadr | USB_DIR_IN)) && ((ep->desc. bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC)) { PDEBUG(0, "ISO EndPoint found 0x%02X AlternateSet %d", ep->desc.bEndpointAddress, i); if ((error = usb_set_interface(dev, spca50x->iface, i)) < 0) { PDEBUG(0, "Set interface err %d", error); return NULL; } spca50x->alt = i; return ep; } } } PDEBUG(0, "FATAL ISO EndPoint not found "); return NULL;}static intgspca_set_alt0(struct usb_spca50x *spca50x){ int error = 0; if ((error = usb_set_interface(spca50x->dev, spca50x->iface, 0)) < 0) { PDEBUG(0, "Set interface err %d", error); } spca50x->alt = 0; return error;}static intgspca_kill_transfert(struct usb_spca50x *spca50x){ struct urb *urb; unsigned int i; spca50x->streaming = 0; for (i = 0; i < SPCA50X_NUMSBUF; ++i) { if ((urb = spca50x->sbuf[i].urb) == NULL) continue; usb_kill_urb(urb);/* urb->transfer_buffer_length is not touched by USB core, so* we can use it here as the buffer length.*/ if (spca50x->sbuf[i].data) {// kfree(gspca_dev->sbuf[i].data); usb_buffer_free(spca50x->dev, urb->transfer_buffer_length, spca50x->sbuf[i].data, urb->transfer_dma); spca50x->sbuf[i].data = NULL; } usb_free_urb(urb); spca50x->sbuf[i].urb = NULL; } return 0;}static intgspca_init_transfert(struct usb_spca50x *spca50x){ struct usb_host_endpoint *ep; struct usb_interface *intf; struct urb *urb; __u16 psize; int n, fx; struct usb_device *dev = spca50x->dev;// struct usb_host_interface *altsetting = NULL; int error = -ENOSPC; int nbalt = 0; if (spca50x->streaming) return -EBUSY; intf = usb_ifnum_to_if(dev, spca50x->iface); nbalt = intf->num_altsetting - 1;/* Damned Sunplus fault */ if (spca50x->bridge == BRIDGE_SPCA561) nbalt = 7; PDEBUG(3, "get iso nbalt %d", nbalt); spca50x->curframe = 0; while (nbalt && (error == -ENOSPC)) { if ((ep = gspca_set_isoc_ep(spca50x, nbalt--)) == NULL) return -EIO; psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); PDEBUG(3, "packet size %d", psize); for (n = 0; n < SPCA50X_NUMSBUF; n++) { urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL); if (!urb) { err("init isoc: usb_alloc_urb ret. NULL"); return -ENOMEM; } spca50x->sbuf[n].data = usb_buffer_alloc(spca50x->dev, psize * FRAMES_PER_DESC, GFP_KERNEL, &urb-> transfer_dma);//gspca_dev->sbuf[n].data = kmalloc((psize+1)* FRAMES_PER_DESC,GFP_KERNEL); if (spca50x->sbuf[n].data == NULL) { usb_free_urb(urb); gspca_kill_transfert(spca50x); return -ENOMEM; } spca50x->sbuf[n].urb = urb; urb->dev = spca50x->dev; urb->context = spca50x; urb->pipe = usb_rcvisocpipe(spca50x->dev, ep->desc.bEndpointAddress); urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; urb->interval = ep->desc.bInterval; urb->transfer_buffer = spca50x->sbuf[n].data; urb->complete = spca50x_isoc_irq; urb->number_of_packets = FRAMES_PER_DESC; urb->transfer_buffer_length = psize * FRAMES_PER_DESC; for (fx = 0; fx < FRAMES_PER_DESC; fx++) { urb->iso_frame_desc[fx].offset = psize * fx; urb->iso_frame_desc[fx].length = psize; } }/* mark all frame unused */ for (n = 0; n < SPCA50X_NUMFRAMES; n++) { spca50x->frame[n].grabstate = FRAME_UNUSED; spca50x->frame[n].scanstate = STATE_SCANNING; }/* start the cam and initialize the tasklet lock */ spca50x->funct.start(spca50x); spca50x->streaming = 1; atomic_set(&spca50x->in_use, 0); PDEBUG(3, "Submit URB Now");/* Submit the URBs. */ for (n = 0; n < SPCA50X_NUMSBUF; ++n) { if ((error = usb_submit_urb(spca50x->sbuf[n].urb, GFP_KERNEL)) < 0) { err("init isoc: usb_submit_urb(%d) ret %d", n, error); gspca_kill_transfert(spca50x); break; } } } return error;}/* Returns number of bits per pixel (regardless of where they are located; planar or* not), or zero for unsupported format.*/static intspca5xx_get_depth(struct usb_spca50x *spca50x, int palette){ switch (palette) {// case VIDEO_PALETTE_GREY: return 8; case VIDEO_PALETTE_RGB565: return 16; case VIDEO_PALETTE_RGB24: return 24;// case VIDEO_PALETTE_YUV422: return 16;// case VIDEO_PALETTE_YUYV:// return 16;// case VIDEO_PALETTE_YUV420: return 24; case VIDEO_PALETTE_YUV420P: return 12; /* strange need 12 this break the read method for this planar mode (6*8/4) */// case VIDEO_PALETTE_YUV422P: return 24; /* Planar */ case VIDEO_PALETTE_RGB32: return 32; case VIDEO_PALETTE_RAW_JPEG: return 24; /* raw jpeg. what should we return ?? */ case VIDEO_PALETTE_JPEG: if (spca50x->cameratype == JPEG || spca50x->cameratype == JPGH || spca50x->cameratype == JPGC || spca50x->cameratype == JPGS || spca50x->cameratype == JPGM || spca50x->cameratype == PJPG || spca50x->cameratype == JPGV ) { return 8; } else return 0; default: return 0; /* Invalid format */ }}/*********************************************************************** spca50x_isoc_irq* Function processes the finish of the USB transfer by calling * spca50x_move_data function to move data from USB buffer to internal* driver structures ***********************************************************************/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)static voidspca50x_isoc_irq(struct urb *urb, struct pt_regs *regs)#elsestatic voidspca50x_isoc_irq(struct urb *urb)#endif{ int i; struct usb_spca50x *spca50x = (struct usb_spca50x *) urb->context; int len; switch (urb->status) { case 0: break; default: PDEBUG(0, "Non-zero status (%d) in isoc " "completion handler.", urb->status); case -ENOENT: /* usb_kill_urb() called. */ case -ECONNRESET: /* usb_unlink_urb() called. */ case -ESHUTDOWN: /* The endpoint is being disabled. */ return; } if (!spca50x->dev) { PDEBUG(4, "no device "); return; } if (!spca50x->user) { PDEBUG(4, "device not open"); return; } if (!spca50x->streaming) {/* Always get some of these after close but before packet engine stops */ PDEBUG(4, "hmmm... not streaming, but got interrupt"); return; } if (!spca50x->present) {/* */ PDEBUG(4, "device disconnected ..., but got interrupt !!"); return; }/* Copy the data received into our scratch buffer */ if (spca50x->curframe >= 0) { len = spca50x_move_data(spca50x, urb); } else if (waitqueue_active(&spca50x->wq)) { wake_up_interruptible(&spca50x->wq); }/* Move to the next sbuf */ urb->dev = spca50x->dev; urb->status = 0; if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0) err("usb_submit_urb() ret %d", i); return;}static voidspca50x_stop_isoc(struct usb_spca50x *spca50x){ if (!spca50x->streaming || !spca50x->dev) return; PDEBUG(3, "*** Stopping capture ***");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -