📄 spca50x.c
字号:
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 void spcaCameraStart (struct usb_spca50x *spca50x){ int err_code; struct usb_device *dev=spca50x->dev; switch(spca50x->bridge) { 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 void spcaCameraStop (struct usb_spca50x *spca50x){ switch(spca50x->bridge) { 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){ /* spca504a aiptek */ spca504A_acknowledged_command(spca50x, 0x08, 6, 0, 0x86, 1); spca504A_acknowledged_command(spca50x, 0x24, 0x0000, 0x0000, 0x9d,1); spca504A_acknowledged_command(spca50x, 0x01, 0x000f, 0x0000, 0xFF,1); } else { spca504_acknowledged_command(spca50x, 0x24, 0x0000, 0x0000); spca50x_reg_write(spca50x->dev, 0x01, 0x000f, 0x0); } break; case BRIDGE_SPCA536: { spca536_stop ( spca50x ); } case BRIDGE_SPCA533: case BRIDGE_SPCA504B: { spca504B_stop ( spca50x ); break; } case BRIDGE_SPCA505: { spca50x_reg_write(spca50x->dev,0x2,0x0,0x0); //Disable ISO packet machine break; } case BRIDGE_SPCA506: spca506_stop(spca50x); break; case BRIDGE_SPCA508: { // Video ISO disable, Video Drop Packet enable: spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x20); break; } case BRIDGE_SPCA561: { // Video ISO disable, Video Drop Packet enable: spca561_stop(spca50x);//spca50x_reg_write(spca50x->dev, 0, 0x8112, 0x20); break; } case BRIDGE_TV8532: { tv8532_stop(spca50x); break; } }}static int spca50x_init_isoc(struct usb_spca50x *spca50x){ struct urb *urb; int fx, err, n; int intpipe; PDEBUG(3, "*** Initializing capture ***"); spca50x->compress = 0; spca50x->curframe = 0; spca50x->cursbuf = 0; spca50x->scratchlen = 0; spca50x_set_packet_size(spca50x, spca50x->pipe_size); PDEBUG(2, "setpacketsize %d",spca50x->pipe_size); for (n = 0; n < SPCA50X_NUMSBUF; n++) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) urb = usb_alloc_urb(FRAMES_PER_DESC,GFP_KERNEL);#else urb = usb_alloc_urb(FRAMES_PER_DESC);#endif if (!urb) { err("init isoc: usb_alloc_urb ret. NULL"); return -ENOMEM; } spca50x->sbuf[n].urb = urb; urb->dev = spca50x->dev; urb->context = spca50x; urb->pipe = usb_rcvisocpipe(spca50x->dev, SPCA50X_ENDPOINT_ADDRESS);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) urb->transfer_flags = URB_ISO_ASAP; urb->interval = 1;#else urb->transfer_flags = USB_ISO_ASAP;#endif urb->transfer_buffer = spca50x->sbuf[n].data; urb->complete = spca50x_isoc_irq; urb->number_of_packets = FRAMES_PER_DESC; urb->transfer_buffer_length = spca50x->packet_size * FRAMES_PER_DESC; for (fx = 0; fx < FRAMES_PER_DESC; fx++) { urb->iso_frame_desc[fx].offset = spca50x->packet_size * fx; urb->iso_frame_desc[fx].length = spca50x->packet_size; } }#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41) spca50x->sbuf[SPCA50X_NUMSBUF - 1].urb->next = spca50x->sbuf[0].urb; for (n = 0; n < SPCA50X_NUMSBUF - 1; n++) spca50x->sbuf[n].urb->next = spca50x->sbuf[n + 1].urb;#endif spcaCameraStart (spca50x); if(spca50x->bridge == BRIDGE_SONIX){ intpipe= usb_rcvintpipe(spca50x->dev,3); usb_clear_halt(spca50x->dev, intpipe); } PDEBUG(5, "init isoc int %d altsetting %d",spca50x->iface,spca50x->alt); for (n = 0; n < SPCA50X_NUMSBUF; n++) { spca50x->sbuf[n].urb->dev = spca50x->dev;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) err = usb_submit_urb(spca50x->sbuf[n].urb,GFP_KERNEL);#else err = usb_submit_urb(spca50x->sbuf[n].urb);#endif if (err) err("init isoc: usb_submit_urb(%d) ret %d", n, err); } for (n = 0; n < SPCA50X_NUMFRAMES; n++) { spca50x->frame[n].grabstate = FRAME_UNUSED; spca50x->frame[n].scanstate = STATE_SCANNING; } spca50x->streaming = 1; return 0;}/*********************************************************************** spca50x_stop_isoc* Function stops the USB ISO pipe by stopping the chip ISO machine* and stopping USB transfer***********************************************************************/static void spca50x_stop_isoc(struct usb_spca50x *spca50x){ int n; if (!spca50x->streaming || !spca50x->dev) return; PDEBUG (3, "*** Stopping capture ***"); spcaCameraStop ( spca50x ); spca50x->streaming = 0; /* Unschedule all of the iso td's */ for (n = SPCA50X_NUMSBUF - 1; n >= 0; n--) { if (spca50x->sbuf[n].urb) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,8) usb_kill_urb(spca50x->sbuf[n].urb);#else usb_unlink_urb(spca50x->sbuf[n].urb);#endif usb_free_urb(spca50x->sbuf[n].urb); spca50x->sbuf[n].urb = NULL; } } spca50x_set_packet_size(spca50x, 0); if (spca50x->bridge == BRIDGE_CX11646) cx11646_stop(spca50x); PDEBUG (3, "*** Capture stopped ***");}/*********************************************************************** spca50x_find_mode_index* Function finds the mode index in the modes table***********************************************************************/static inline int spca50x_find_mode_index(int width, int height, __u16 ext_modes [][6]){ int i = 0; int j = 0; /* search through the mode list until we hit one which has * a smaller or equal resolution, or we run out of modes. */ for (i = 0; ext_modes[i][0] && (ext_modes[i][0] >= width && ext_modes[i][1] >= height); i++) { if (((ext_modes[i][2] & 0xF0) >> 4) == 0 ) j = (i & 0x0F) << 4; } /* search to found the first hardware available mode */ i--; /* FIXME */ PDEBUG(2, "find Hardware mode %d soft mode %d", j >> 4 ,i); /* check whether we found the requested mode, or ran out of * modes in the list. */ if (!ext_modes[i][0] || ext_modes[i][0] != width || ext_modes[i][1] != height ) { PDEBUG(3, "Failed to find mode %d x %d", width, height); return -EINVAL; } i = (i & 0x0F) | j; PDEBUG(2, "Pass Hardware mode %d soft mode %d", (i >> 4) ,(i & 0x0F)); /* return the index of the requested mode */ return i;}/*********************************************************************** spca50x_smallest_mode_index* Function finds the mode index in the modes table of the smallest* available mode.***********************************************************************/static inline int spca50x_smallest_mode_index(__u16 ext_modes [][6], int *cols, int *rows, int *pipe){ int i; int width = INT_MAX; int height = INT_MAX; int intpipe = 1023 ; int index = -EINVAL; /* search through the mode list until we run out of modes */ /* and take the smallest hardware mode and pipe size*/ for (i = 0; ext_modes[i][0]; i++) //i=0; { if (ext_modes[i][0] < width || ext_modes[i][1] < height) { if (!(ext_modes[i][2] & 0xF0)){ width =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -