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

📄 zc030x_main.c

📁 中星微301摄想头最新驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
        up (&dev->sem);        /* Return */        return -ENODEV;    }        /* Stop isochronous transfers */    zc030x_isoc_stop(dev);    /* Wake up frame queue */    for (i = 0; i < ZC030X_NUMFRAMES; i++)    {        if (waitqueue_active(&dev->frame[i].wq))            wake_up_interruptible(&dev->frame[i].wq);    }            /* Check if the device is already unplugged */    if(!dev->present && !dev->open)    {        /* the device was unplugged before the file was released */        up (&dev->sem);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)              MOD_DEC_USE_COUNT;#endif        return 0;    }        /* Decrement our usage count for the device */    --dev->open;        /* How could this happen ? */    if (dev->open <= 0)     {        dev->open = 0;    }        /* decrement our usage count for the module */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)        MOD_DEC_USE_COUNT;#endif        /* Release the lock */    up (&dev->sem);        /* Okay exit */    PDEBUG(3,"<< zc030x_release()");    return 0;}/* Read a frame from the device */ssize_t zc030x_read (struct file *file, char *buf, size_t count, loff_t * ppos){    /* Iterator */    int i = 0;    /* Frame index */    int frmx = -1;    /* Check for non blocking reading */    int noblock = file->f_flags&O_NONBLOCK;    /* Need to have a temporary frame */     zc030x_frame *frame;        /* Get the video device */    struct video_device *vdev = video_devdata(file);    /* And the USB device too */    struct usb_zc030x *dev;        /* Debug this function */    PDEBUG(3,">> zc030x_read()");    /* Check parameter */    if (vdev == NULL)    {        PDEBUG (2, "vdev is NULL, returning");        return 0;    }        /* Get USB device too */    dev = video_get_drvdata(vdev);    if (dev == NULL)    {        PDEBUG (2, "dev is NULL, returning");        return 0;    }    /* Check parameter */    if (buf == NULL)    {        PDEBUG(2, "Bad NULL buffer to store the frame");        return -EFAULT;    }      /* What is this ? */    PDEBUG(4, "%d bytes, noblock=%d", count, noblock);        /* Check if a signal is pending, so return interrupted */    if (signal_pending(current))        return -EINTR;       /* Lock this object */    down (&dev->sem);        /* Verify that the device wasn't unplugged */    if (!dev->present)     {        up (&dev->sem);        return -ENODEV;    }    /* Check the device was streaming */    if(!dev->streaming)     {        up(&dev->sem);        return -EIO;    }        /* Release the device before sleeping */    up(&dev->sem);        /* Set the frame to wait on */    if (down_trylock(&dev->frame[0].Lock))    {        return -EIO;    }        /* Change this state */    /* Now this frame is ready to be grabbed into */    dev->frame[0].GrabState = FRAME_READY;    /* Release it */    up(&dev->frame[0].Lock);        /* Sleep until this frame is available */    PDEBUG(4,"sleep interruptible!");    interruptible_sleep_on(&dev->frame[0].wq);    PDEBUG(4,"signal pending test!");    /* And relock the device now */    down (&dev->sem);        /* Check if a signal is pending, so return interrupted */    if (signal_pending(current))     {        up( &dev->sem);        return -EINTR;    }        /* Now we should have a frame */    if (dev->frame[0].GrabState == FRAME_DONE)        frmx = i;            /* Found at index */    PDEBUG(4, "Frame number: %d", frmx);        if (frmx < 0)    {        /* Done frame not found */         PDEBUG(2, "frame not ready to be read %d", frmx);        up (&dev->sem);        return -EFAULT;    }        /* Get the frame */    frame = &dev->frame[frmx];    /* Lock the frame too */    down (&frame->Lock);        /* Need to check the user demand */    i = (frame->HeaderWidth * frame->HeaderHeight * frame->Depth) >> 3;    /* To avoid overflow (ie->reading kernel memory space) */    if (copy_to_user(buf, frame->Data, count < i ? count : i))     {        PDEBUG(2, "Copy failed! %d bytes not copied", i);        up (&frame->Lock);        up (&dev->sem);        return -EFAULT;    }    PDEBUG(2, "Maximum size is %dx%dx%d = %d asked %d", frame->HeaderWidth, frame->HeaderHeight, frame->Depth, i, count);        /* Release the frame */    frame->GrabState = FRAME_READY;    /* Unlock it */    up(&frame->Lock);        /* Unlock the device */    up (&dev->sem);        /* Return */    PDEBUG(3,"<< zc030x_read()");    return count < i ? count : i;}/* Map a kernel memory page to user space */int zc030x_mmap(struct file *file, struct vm_area_struct *vma){    /* Start address */    unsigned long start = vma->vm_start;    /* Size of mapping */    unsigned long size  = vma->vm_end - vma->vm_start;    /* The page */    unsigned long page;    /* And the position */    unsigned long pos;    /* Get the video device */    struct video_device *vdev = video_devdata(file);    /* And the USB device too */    struct usb_zc030x *dev;        /* Debug this function */    PDEBUG(3,">> zc030x_mmap()");    /* Check parameter */    if (vdev == NULL)    {        PDEBUG (2, "vdev is NULL, returning");        return 0;    }        /* Get USB device too */    dev = video_get_drvdata(vdev);    if (dev == NULL)    {        PDEBUG (2, "dev is NULL, returning");        return 0;    }        /* Check if the device is still here */    if (!dev->present)         return -EIO;        /* Debug here too */    PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);        /* Check the asked size */    if (size > (((ZC030X_NUMFRAMES * MAX_VIDEODATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))        return -EINVAL;    /* Convert the kernel address to userspace */    pos = (unsigned long)dev->fbuf;    /* And remap all concerned page to shared space */    while (size > 0)     {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)        page = page_to_pfn(vmalloc_to_page((void *)pos));        if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))#else                page = kvirt_to_pa(pos);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined (RH9_REMAP)        if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))#else /* RH9_REMAP */        if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))#endif /* RH9_REMAP */#endif            return -EAGAIN;        start += PAGE_SIZE;        pos += PAGE_SIZE;        if (size > PAGE_SIZE)            size -= PAGE_SIZE;        else            size = 0;    }        /* Okay return */    return 0;}/* Perform IOCTLs now */int zc030x_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){    /* Return code */	int rc ;     /* Get the video device */    struct video_device *vdev = video_devdata(file);    /* And the USB device too */    struct usb_zc030x *dev;        /* Debug this function */    PDEBUG(3,">> zc030x_ioctl()");    /* Check parameter */    if (vdev == NULL)    {        PDEBUG (2, "vdev is NULL, returning");        return 0;    }        /* Get USB device too */    dev = video_get_drvdata(vdev);    if (dev == NULL)    {        PDEBUG (2, "dev is NULL, returning");        return 0;    }        /* Check if the device is still here */    if (!dev->present)         return -EIO;            /* Zc030x specific ioctl */    switch (cmd)    {        /* Users asked register mapping */        case ZCI2CREGISTERMAP:        {            /* Call the register mapping function */            /*            //unsigned char buf[1];            unsigned char val[255];            unsigned char prev = 0;            int ret;            int i;            struct register_map * prm = (struct register_map*) arg;            zc030x_i2c_init(dev->udev, 0x0c);            // Write :            PDEBUG(2, "HHHHHH ------------------------- Separator --------------");            for (i = 0; i < 256; i ++)            {                // Save previous value (bug reported on ML)                prev = zc030x_i2c_reg_read(dev->udev, i, 1);                PDEBUG(2, "HHHHHH Read %02X at address %02X", prev, i);                prm[i].addr = i;                prm[i].value = 0xff;                prm[i].mode = RM_ReadWrite;                                zc030x_i2c_reg_write(dev->udev, i, 0xff);                val[i] = zc030x_i2c_reg_read(dev->udev, i, 1);                if (val[i] != 0xff)                {                    PDEBUG(2, "REGISTERMAP: [FF] (%02X) contains some read only bit with %02X value", i, val[i]);                    prm[i].value = val[i];                    if (val[i] == 0)                        prm[i].mode = RM_Unused;                }                zc030x_i2c_reg_write(dev->udev, i, 0x00);                ret = zc030x_i2c_reg_read(dev->udev, i, 1);                if (ret != 0x00)                {                    PDEBUG(2, "REGISTERMAP: [00] (%02X) contains some read only bit with %02X value", i, ret);                }                if (val[i] == ret && ret != 00)                {                    PDEBUG(2, "REGISTERMAP-OK: [ID] (%02X) is read only with %02X value", i, ret);                    prm[i].addr = i;                    prm[i].value = ret;                    prm[i].mode = RM_ReadOnly;                }                // Restore previous value                zc030x_i2c_reg_write(dev->udev, i, prev);             }            */            /* And return */            rc = 0;            break;        }        /* User asked sensor identification */        case ZCIDSENSOR:        {            /* Call sensor identification function now */            //unsigned char buf[1];            int ret = 0;                        /* Currently not supported */            ret = 0;            /*                        struct sensor_list * psl = (struct sensor_list*) arg;		    PDEBUG (2, ">>> ZCIDSENSOR asked for : %s, (%d)",psl->name, psl->id);                        // Let's try to read the i2c first register (I've no idea about how to read an I2C register but...)            //buf[0] = 0x00;            // Okay, try to find the sensor given its id            usb_set_interface (dev->udev, 0, 0);	    //fuck! as this has gone to main.c and is declared extern here, sizeof doesn't work!            //ret = zc030x_find_sensor_by_id(dev->udev, slist, sizeof(slist) / sizeof(slist[0]));	    ret = zc030x_find_sensor_by_id(dev->udev, slist, 16);            usb_set_interface (dev->udev, 0, 7);            if (ret != -1)            {                psl->id = slist[ret].id;                sprintf(psl->name, "%s", slist[ret].name);                psl->minwidth = slist[ret].minwidth;                psl->maxwidth = slist[ret].maxwidth;                psl->minheight = slist[ret].minheight;                psl->maxheight = slist[ret].maxheight;            } else            {                psl->id = 0;                sprintf(psl->name, "Unknown");                psl->minwidth = 0;                psl->maxwidth = 0;                psl->minheight = 0;                psl->maxheight = 0;            }            psl->i2c_sig = NULL;		    PDEBUG (2, "<<< ZCIDSENSOR asked for : %s, (%d)",psl->name, psl->id);            */            /* Okay return now */            rc = 0;            break;        }        /* Video for Linux specific IOCTLs */        default:            rc = video_usercopy(inode, file, cmd, arg, zc030x_v4l_ioctl);                }	/* Return now */    PDEBUG (2, "<< zc030x_ioctl() arg = %08X", (unsigned int)arg);	return rc;}/* Module loading */static int __init   usb_zc030x_init (void){    int result;       PDEBUG(1,"Loading experimental zc030x... \n");    /* register this driver with the USB subsystem */    result = usb_register (&zc030x_driver);    if (result < 0)    {        err ("usb_register failed for the " __FILE__ " driver. Error number %d",        result);        return -1;    }        PDEBUG (5, DRIVER_DESC " " DRIVER_VERSION);#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)//TODO: proc entry has been temorarily removed  zc030x_proc_create();#endif    return 0;}/* Module unloading */static void __exit usb_zc030x_exit (void){#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)//TODO: proc entry management  zc030x_proc_destroy();#endif    /* stop isoc stream (if streaming) ) */        /* deregister this driver with the USB subsystem */    PDEBUG (1,"Unloading experimental zc030x.\n");    usb_deregister (&zc030x_driver);}module_init (usb_zc030x_init);module_exit (usb_zc030x_exit);

⌨️ 快捷键说明

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