📄 spca5xx.c
字号:
/* Poll the status register for a ready status */ retry = 60; while (--retry) { err_code = spca50x_reg_read (dev, ctrl, SPCA50X_I2C_STATUS, 2); if (err_code < 0) PDEBUG (1, "Error reading I2C status register"); if (!err_code) break; } if (!retry) PDEBUG (1, "Too many retries polling I2C status after write to register"); if (debug > 2) { err_code = spca50x_read_i2c (spca50x, device, subaddress); if (err_code < 0) { PDEBUG (3, "Can't read back I2C register value for %d:%d", device, subaddress); } else if ((err_code & 0xff) != (data & 0xff)) PDEBUG (3, "Read back %x should be %x at subaddr %x", err_code, data, subaddress); } return 0;}static intspca50x_write_i2c_vector (struct usb_spca50x *spca50x, __u16 device, __u16 data[][2]){ int I = 0; while (data[I][0]) { spca50x_write_i2c (spca50x, device, data[I][0], data[I][1]); I++; } return 0;}static intspca50x_set_packet_size (struct usb_spca50x *spca50x, int size){ int alt; /**********************************************************************/ /******** Try to find real Packet size from usb struct ****************/ struct usb_device *dev = spca50x->dev;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) struct usb_interface_descriptor *interface = NULL; struct usb_config_descriptor *config = dev->actconfig;#else struct usb_host_interface *interface = NULL; struct usb_interface *intf;#endif int mysize = 0; /**********************************************************************/ if (size == 0) alt = SPCA50X_ALT_SIZE_0; else if (size == 128) alt = SPCA50X_ALT_SIZE_128; else if (size == 256) alt = SPCA50X_ALT_SIZE_256; else if (size == 384) alt = SPCA50X_ALT_SIZE_384; else if (size == 512) alt = SPCA50X_ALT_SIZE_512; else if (size == 640) alt = SPCA50X_ALT_SIZE_640; else if (size == 768) alt = SPCA50X_ALT_SIZE_768; else if (size == 896) alt = SPCA50X_ALT_SIZE_896; else if (size ==1000) alt = ETOMS_ALT_SIZE_1000; else if (size == 1023) if (spca50x->bridge == BRIDGE_SONIX || spca50x->bridge == BRIDGE_SN9C102P) { alt = 8; } else { alt = SPCA50X_ALT_SIZE_1023; } else { /* if an unrecognised size, default to the minimum */ PDEBUG (5, "Set packet size: invalid size (%d), defaulting to %d", size, SPCA50X_ALT_SIZE_128); alt = SPCA50X_ALT_SIZE_128; } PDEBUG (5, "iface alt: %d %d ", spca50x->iface, alt); if (usb_set_interface (spca50x->dev, spca50x->iface, alt) < 0) { err ("Set packet size: set interface error"); return -EBUSY; }#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,3) intf = usb_ifnum_to_if (dev, spca50x->iface); if (intf) { interface = usb_altnum_to_altsetting (intf, alt); } else { PDEBUG (0, "intf not found"); return -ENXIO; }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) mysize = le16_to_cpu(interface->endpoint[0].desc.wMaxPacketSize);#else mysize = (interface->endpoint[0].desc.wMaxPacketSize);#endif#else interface = &config->interface[spca50x->iface].altsetting[alt];#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) mysize = le16_to_cpu(interface->endpoint[0].wMaxPacketSize);#else mysize = (interface->endpoint[0].wMaxPacketSize);#endif #endif spca50x->packet_size = mysize & 0x03ff; spca50x->alt = alt; PDEBUG (1, "set real packet size: %d, alt=%d", mysize, alt); return 0;}/* 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 ) { 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,5,0)static voidspca50x_isoc_irq (struct urb *urb, struct pt_regs *regs){ int i;#elsestatic voidspca50x_isoc_irq (struct urb *urb){#endif int len; struct usb_spca50x *spca50x; if (!urb->context) { PDEBUG (4, "no context"); return; } spca50x = (struct usb_spca50x *) urb->context; 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 */ spca50x->cursbuf = (spca50x->cursbuf + 1) % SPCA50X_NUMSBUF; urb->dev = spca50x->dev; urb->status = 0;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4) if ((i = usb_submit_urb (urb, GFP_ATOMIC)) != 0) err ("usb_submit_urb() ret %d", i);#else/* If we use urb->next usb_submit_urb() is not need in 2.4.x */ //if ((i = usb_submit_urb(urb)) != 0) //err("usb_submit_urb() ret %d", i);#endif /* let's try to set up brightness for the next frame */ if (autoadjust && !spca50x->bh_requested) { spca50x->task.data = spca50x;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) spca50x->task.func = auto_bh; schedule_work (&spca50x->task);#else spca50x->task.sync = 0; spca50x->task.routine = auto_bh; SCHEDULE_TASK (&spca50x->task);#endif spca50x->bh_requested = 1; } return;}/*********************************************************************** spca50x_init_isoc* Function starts the ISO USB transfer by enabling this process* from USB side and enabling ISO machine from the chip side***********************************************************************/static inline voidspcaCameraStart (struct usb_spca50x *spca50x){ int err_code; struct usb_device *dev = spca50x->dev; switch (spca50x->bridge) { case BRIDGE_SN9C102P: sn9c102p_start(spca50x); break; case BRIDGE_ETOMS: Et_startCamera(spca50x); break; case BRIDGE_CX11646: cx11646_start (spca50x); break; case BRIDGE_ZC3XX: zc3xx_start (spca50x); break; case BRIDGE_SONIX: sonix_start (spca50x); break; case BRIDGE_SPCA500: { err_code = spca500_initialise (spca50x); break; } case BRIDGE_SPCA501: { /* Enable ISO packet machine CTRL reg=2, * index=1 bitmask=0x2 (bit ordinal 1) */ err_code = spca50x_reg_write (dev, SPCA501_REG_CTLRL, (__u16) 0x1, (__u16) 0x2); break; } case BRIDGE_SPCA504: spca504_initialize (spca50x); break; case BRIDGE_SPCA504_PCCAM600: { /* specific code for clicsmart is in pccam600 */ spca504_pccam600_initialize (spca50x); break; } case BRIDGE_SPCA536: { spca536_start (spca50x); break; } case BRIDGE_SPCA533: case BRIDGE_SPCA504B: { spca504B_start (spca50x); break; } case BRIDGE_SPCA506: spca506_start (spca50x); break; case BRIDGE_SPCA505: { //nessesary because without it we can see stream only once after loading module //stopping usb registers Tomasz change spca50x_reg_write (dev, 0x2, 0x0, 0x0); /* Enable ISO packet machine - should we do this here or in ISOC init ? */ err_code = spca50x_reg_write (dev, SPCA50X_REG_USB, SPCA50X_USB_CTRL, SPCA50X_CUSB_ENABLE);// spca50x_reg_write(dev, 0x5, 0x0, 0x0);// spca50x_reg_write(dev, 0x5, 0x0, 0x1);// spca50x_reg_write(dev, 0x5, 0x11, 0x2); break; } case BRIDGE_SPCA508: err_code = spca50x_reg_write (dev, 0, 0x8112, 0x10 | 0x20); break; case BRIDGE_SPCA561: { /* Video ISO enable, Video Drop Packet enable: */ spca561_start (spca50x); //spca50x_reg_write(dev, 0, 0x8112, 0x10 | 0x20); break; } case BRIDGE_TV8532: { tv8532_start (spca50x); break; } }}static inline voidspcaCameraStop (struct usb_spca50x *spca50x){ switch (spca50x->bridge) { case BRIDGE_SN9C102P: sn9c102p_stop (spca50x); break; case BRIDGE_ETOMS: Et_stopCamera(spca50x); break; case BRIDGE_CX11646: /* deferred after set_alt(0,0) cx11646_stop(spca50x); */ break; case BRIDGE_ZC3XX: zc3xx_stop (spca50x); break; case BRIDGE_SONIX: sonix_stop (spca50x); break; case BRIDGE_SPCA500: { /* stop the transfer */ // Tha's the code need for familycam 300 //spca50x_reg_write(spca50x->dev, 0x00, 0x8000, 0x0000); /* spca50x_reg_write(spca50x->dev, 0xe1, 0x0001, 0x0000); if (spca50x_reg_readwait(spca50x->dev, 0x06, 0, 0) != 0) { PDEBUG(2, "spca50x_reg_readwait() failed"); } spca50x_reg_write(spca50x->dev, 0x0c, 0x0000, 0x0000); spca50x_reg_write(spca50x->dev, 0x30, 0x0000, 0x0004); if (spca500_full_reset(spca50x) < 0) { PDEBUG(2, "spca50x_full_reset() failed"); } */ break; } case BRIDGE_SPCA501: { /* Disable ISO packet machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */ spca50x_reg_write (spca50x->dev, SPCA501_REG_CTLRL, (__u16) 0x1, (__u16) 0x0); break; } case BRIDGE_SPCA504_PCCAM600: case BRIDGE_SPCA504: spca50x_reg_write (spca50x->dev, 0x00, 0x2000, 0x0000); if (spca50x->desc == AiptekMiniPenCam13) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -