📄 spca5xx.c
字号:
}static void create_proc_spca50x_cam(struct usb_spca50x *spca50x){ char name[PROC_NAME_LEN]; struct proc_dir_entry *ent; if (!spca50x_proc_entry || !spca50x) return;//Create videoxx proc entry sprintf(name, "video%d", spca50x->vdev->minor); PDEBUG(4, "creating /proc/video/spca50x/%s", name); ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, spca50x_proc_entry); if (!ent) return; ent->data = spca50x; ent->read_proc = spca50x_read_proc; ent->write_proc = spca50x_write_proc; spca50x->proc_entry = ent;// Create the controlxx proc entry sprintf(name, "control%d", spca50x->vdev->minor); PDEBUG(4, "creating /proc/video/spca50x/%s", name); ent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, spca50x_proc_entry); if (!ent) return; ent->data = spca50x; ent->read_proc = spca50x_ctlread_proc; ent->write_proc = spca50x_ctlwrite_proc; spca50x->ctl_proc_entry = ent;}static void destroy_proc_spca50x_cam(struct usb_spca50x *spca50x){ char name[PROC_NAME_LEN]; if (!spca50x || !spca50x_proc_entry) return; /* destroy videoxx proc entry */ if (spca50x->proc_entry != NULL) { sprintf(name, "video%d", spca50x->vdev->minor); PDEBUG(4, "destroying %s", name); remove_proc_entry(name, spca50x_proc_entry); spca50x->proc_entry = NULL; } /* destroy controlxx proc entry */ if (spca50x->ctl_proc_entry != NULL) { sprintf(name, "control%d", spca50x->vdev->minor); PDEBUG(4, "destroying %s", name); remove_proc_entry(name, spca50x_proc_entry); spca50x->ctl_proc_entry = NULL; }}static void proc_spca50x_create(void){ /* No current standard here. Alan prefers /proc/video/ as it keeps * /proc "less cluttered than /proc/randomcardifoundintheshed/" * -claudio */#ifdef CONFIG_VIDEO_PROC_FS if (video_proc_entry == NULL) { err("Unable to initialise /proc/video/spca50x"); return; } spca50x_proc_entry = create_proc_entry("spca50x", S_IFDIR, video_proc_entry);#else /* CONFIG_VIDEO_PROC_FS */ spca50x_proc_entry = create_proc_entry("spca50x", S_IFDIR, 0);#endif /* CONFIG_VIDEO_PROC_FS */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) if (spca50x_proc_entry) spca50x_proc_entry->owner = THIS_MODULE; else#ifdef CONFIG_VIDEO_PROC_FS err("Unable to initialise /proc/video/spca50x");#else /* CONFIG_VIDEO_PROC_FS */ err("Unable to initialise /proc/spca50x");#endif /* CONFIG_VIDEO_PROC_FS */#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) */}static void proc_spca50x_destroy(void){#ifdef CONFIG_VIDEO_PROC_FS PDEBUG(3, "removing /proc/video/spca50x");#else /* CONFIG_VIDEO_PROC_FS */ PDEBUG(3, "removing /proc/spca50x");#endif /* CONFIG_VIDEO_PROC_FS */ if (spca50x_proc_entry == NULL) return;#ifdef CONFIG_VIDEO_PROC_FS remove_proc_entry("spca50x", video_proc_entry);#else /* CONFIG_VIDEO_PROC_FS */ remove_proc_entry("spca50x", 0);#endif /* CONFIG_VIDEO_PROC_FS */}#endif /* CONFIG_PROC_FS */static int spca50x_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; int ep = 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_SN9CXXX || spca50x->bridge == BRIDGE_MR97311 || spca50x->bridge == BRIDGE_PAC207) { 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 size: %d %d %d", spca50x->iface, alt, size); if (usb_set_interface(spca50x->dev, spca50x->iface, alt) < 0) { err("Set packet size: set interface error"); return -EBUSY; } /* check endpoint */ if (spca50x->bridge == BRIDGE_PAC207) { ep = PAC207_ENDPOINT_ADDRESS - 1; } else { ep = SPCA50X_ENDPOINT_ADDRESS - 1; }#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[ep].desc.wMaxPacketSize);#else mysize = (interface->endpoint[ep].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[ep].wMaxPacketSize);#else mysize = (interface->endpoint[ep].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 int spca5xx_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) { 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 void spca50x_isoc_irq(struct urb *urb, struct pt_regs *regs){ int i;#elsestatic void spca50x_isoc_irq(struct urb *urb){#endif 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 */ 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 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){ spca50x->funct.start(spca50x);}static inline void spcaCameraStop2(struct usb_spca50x *spca50x){ spca50x->funct.stop0(spca50x);}static inline void spcaCameraStop(struct usb_spca50x *spca50x){/* stop on alt x */ spca50x->funct.stopN(spca50x);}static int spca50x_init_isoc(struct usb_spca50x *spca50x){ struct urb *urb; int fx, err, n; int intpipe; PDEBUG(3, "*** Initializing capture ***");/* reset iso context */ spca50x->compress = compress; spca50x->curframe = 0; spca50x->cursbuf = 0;// spca50x->frame[0].seq = -1; spca50x->lastFrameRead = -1; 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; if (spca50x->bridge == BRIDGE_PAC207) { urb->pipe = usb_rcvisocpipe(spca50x->dev, PAC207_ENDPOINT_ADDRESS); } else { 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -