⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zc030x_isochron.c

📁 Linux下USB接口的摄像头源码,很详细!对写USB接口驱动有很大帮助的
💻 C
📖 第 1 页 / 共 2 页
字号:
        {            PDEBUG(2, "data error: [%d] len=%d, status=%d", i, datalength, st);        }        /* Skip any zero length block or non selected frame buffer */        /* TODO I think this is a bug so I need to check this */        if (datalength <= 0 || dev->curframe < 0)            continue;                /* ...else packet data available -> cdata points to packet data! */        cData = ((unsigned char *) urb->transfer_buffer) + urb->iso_frame_desc[i].offset;        /* Save the previous pointer */        if (urb->transfer_buffer == NULL || urb->iso_frame_desc[i].offset >= ISO_BUFFER_SIZE)        {            PDEBUG(2, "URB error: [%d] len=%d, status=%d", i, urb->iso_frame_desc[i].offset, st);            continue;        }        /* Now, we can check if we have had a frame to decode */                /* TODO: frame dropping, frame error handling */        /*       Andrew got an idea about this... (interrupt messages?) */                /* Check if we find a SOI marker... */        if( ((*((int *)cData)) & 0xFFFF) == 0xD8FF )        {            /* We might be on a next frame */            /* If the frame we've received is filled, it's the case */            /* Lock it before accessing it */            if(down_trylock(&frame->Lock))            {                                return -ENOBUFS;            }            if (frame->SeqNumber > 1 && frame->GrabState != FRAME_ERROR)            {                /* Found so debug it */                PDEBUG(5,"frame compressed size: %d %p",frame->CompLen, frame->CompData);                                /* Schedule tasklet to decode this frame */                /* Launch the tasklet to decode it */                tasklet_init(&decodetasklet, decode_tasklet, (unsigned long)frame);                up(&frame->Lock);                tasklet_schedule(&decodetasklet);                            PDEBUG(5, "Scheduled the decode tasklet");                // If someone decided to wait for ANY frame - wake him up                 if (waitqueue_active(&dev->wq))                    wake_up_interruptible(&dev->wq);                PDEBUG(5, "Now changing the frame");                /* Get a new frame now */                /* Get the frame */                frame = zc030x_get_free_frame_tmp(dev);                /* And check it */                if(frame == NULL)                 {                    PDEBUG(2, "Error while locking the buffer or frame %p", frame);                    return -ENOBUFS;                }                PDEBUG(5, "DUMPIN Frame changed to %d", dev->curframe);                if(down_trylock(&frame->Lock))                {                                    return -ENOBUFS;                }            }                                     /* Read pseudo header data */            /* TODO: For PPC should make endianness independant code */            frame->SeqNumber = ((int)cData[8]<<8) | (int)cData[9];            frame->Width = ((int)cData[12]<<8) | (int)cData[13];            frame->Height = ((int)cData[14]<<8) | (int)cData[15];            frame->HeaderWidth  = frame->Width;            frame->HeaderHeight = frame->Height;            frame->Format = dev->VideoFormat;            frame->Depth  = zc030x_v4l_getdepth(dev->VideoFormat);             /* Unlock it */            up(&frame->Lock);                        /* Debug the result */            PDEBUG(5,"***SOI FOUND, seqno:%d, width:%d, height:%d", frame->SeqNumber, frame->Width, frame->Height);        }                 /* And copy the buffer */        /* Lock it before accessing it */        if(down_trylock(&frame->Lock))        {                            return -ENOBUFS;        }                /* Check the copy first */        if (frame->CompData == NULL || (frame->CompLen  + datalength) >= MAX_VIDEODATA_SIZE / 4)        {            /* Buffer too small, maybe it could be good to increase their size */            PDEBUG(2, "Error : Frame buffers too small, %d needed (%d available)", (frame->CompLen  + datalength), MAX_VIDEODATA_SIZE / 4);            PDEBUG(2, "Error : Frame will be erroneous");            frame->GrabState = FRAME_ERROR;        } else        {            /* Copy the urb data into the frame */            memcpy(frame->CompData + frame->CompLen, cData, datalength);            /* Advance pointers */            frame->CompLen += datalength;        }        /* Unlock it */        up(&frame->Lock);                /* Increase the total length */        totlen += datalength;            }	        /* UnLock the buffers */    return(totlen);}/* Isochronous transfers callback */#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)void zc030x_isoc_handler (struct urb *urb)#elsevoid zc030x_isoc_handler (struct urb *urb,  struct pt_regs *prgx)#endif{    /* Get the device pointer */    struct usb_zc030x *dev = (struct usb_zc030x *)urb->context;    /* Check input */	if (!dev)	{        PDEBUG (4, "isoc handler: no context!\n");        return;	}    /* Check if isochronous transfers have started */    if (!dev->streaming) 	{        PDEBUG(4, "isoc handler: not streaming, but got interrupt");	    return;	}    /* copy received data to a frame buffer */    zc030x_move_data(dev, urb);    /* Set the current buffer to the next one */	dev->cursbuf = (dev->cursbuf + 1) % MAX_ISO_BUFS;              //      IS THIS NEEDED? SOME CODE I FOUND DO THAT        //        //      urb->dev = dev->udev;        //      for (i = 0; i < ISO_FRAMES_PER_DESC; i++) {        //         urb->iso_frame_desc[i].status = 0;        //      }        //      urb->context = dev;        //      urb->status = 0;        	#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) // wtf does this?    {        /* Declare iterator */        int i = 0;         /* Submit ack to the transfers ? */        urb->dev = dev->udev;        if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)         {           PDEBUG(4, "Err usb_submit_urb ret %d\n",  i);        }    }#endif}/* Start the isochronous transfers */int zc030x_isoc_start (struct usb_zc030x *dev){    /* Iterators */    int i, j;    /* Return value */    int ret = 0;        /* Urb to submit */    struct urb *urb = NULL;    /* Get the usb device pointer */    struct usb_device *udev;        /* Check arguments */    if (dev == NULL)    {        PDEBUG(1,"Error no dev!!");        return -ENODEV;    }        udev = dev->udev;    if (udev == NULL)    {        PDEBUG(1,"Error no udev!!!");        return -ENODEV;    }    /* Check for available isochronous buffers */    if (dev->sbuf == NULL)    {        PDEBUG(1,"Error no dev->sbuf!!!");        return -ENODEV;    }        /* Debug this */    PDEBUG (3, ">> [ZCISO] Starting !");      /* Look for a free urb */    for (i = 0; i < MAX_ISO_BUFS; i++)    {        if (dev->sbuf[i].urb == NULL)        {            PDEBUG(1,"Error no dev->sbuf[%d].urb, allocate them now!!!",i);            if (zc030x_allocate_urbs(dev) < 0)                return -ENODEV;        }    }        /* Set streaming variables */    down(&dev->buf_lock);    dev->cursbuf = 0;    dev->curframe = 0;    dev->streaming = 0;        /* Send the gamma matrix */    zc030x_send_gamma(dev->udev, dev->Brightness, dev->Contrast, dev->Gamma);        /* Init URB structure */    for (i = 0; i < MAX_ISO_BUFS; i++)    {        urb = dev->sbuf[i].urb;                #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)         urb->next               = dev->sbuf[(i + 1) % MAX_ISO_BUFS].urb;        #endif        urb->dev                = udev;        urb->pipe               = usb_rcvisocpipe (udev, dev->isocend);        urb->transfer_flags     = URB_ISO_ASAP;        urb->transfer_buffer    = dev->sbuf[i].data;        urb->transfer_buffer_length = ISO_BUFFER_SIZE;        urb->complete           = zc030x_isoc_handler;        urb->context            = dev;        urb->start_frame        = 0;        urb->number_of_packets  = ISO_FRAMES_PER_DESC;        urb->interval           = 1;                /* Get an offset */        for (j = 0; j < ISO_FRAMES_PER_DESC; j++)        {            urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;            urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;        }    }        /* All is done... */    dev->streaming = 1;         /* Set the first frame state, application will use more buffer if it wants to */    dev->frame[0].GrabState = FRAME_GRABBING;    dev->frame[1].GrabState = FRAME_READY;    dev->frame[2].GrabState = FRAME_UNUSED;    dev->frame[3].GrabState = FRAME_UNUSED;        /* link iso buffers*/    for (i = 0; i < MAX_ISO_BUFS; i++)    {    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)         ret = usb_submit_urb (dev->sbuf[i].urb);    #else        ret = usb_submit_urb (dev->sbuf[i].urb, GFP_ATOMIC);    #endif              if (ret)        {            PDEBUG (5, "Submit_urb %d failed with error %d\n", i, ret);        }        else        {            PDEBUG (5, "URB 0x%p submitted.\n", dev->sbuf[i].urb);        }    }        up(&dev->buf_lock);    PDEBUG (3, "<< [ZCISO] Started!");    return 0;}/* Stop the isochronous transfers */int zc030x_isoc_stop (struct usb_zc030x *dev){    /* URB object */    struct urb *urb;    /* Iterator */    int i;        /* Debug this functions */    PDEBUG(3,">> [ZCISO] Stopping!");      /* Loop through iso buffers */    for (i = MAX_ISO_BUFS -1; i >= 0; i--)     {        urb = dev->sbuf[i].urb;        if (urb != 0)         {            /* TODO If streaming unlink the urb before freeing it */            if (dev->streaming)             {                PDEBUG (5, "Unlinking URB %p\n", urb);                usb_unlink_urb (urb);            }                        PDEBUG (5, "Freeing URB\n");            usb_free_urb (urb);            dev->sbuf[i].urb = NULL;        }    }    dev->streaming = 0;    /* Okay, return */    PDEBUG(3,"<< [ZCISO] Stopped!");    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -