usbvision-core.c
来自「linux 内核源代码」· C语言 代码 · 共 2,307 行 · 第 1/5 页
C
2,307 行
usbvision->isocDataCount += packet_len; usbvision->isocPacketCount++; }#if ENABLE_HEXDUMP if (totlen > 0) { static int foo = 0; if (foo < 1) { printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen); usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen); ++foo; } }#endif return totlen;}static void usbvision_isocIrq(struct urb *urb){ int errCode = 0; int len; struct usb_usbvision *usbvision = urb->context; int i; unsigned long startTime = jiffies; struct usbvision_frame **f; /* We don't want to do anything if we are about to be removed! */ if (!USBVISION_IS_OPERATIONAL(usbvision)) return; /* any urb with wrong status is ignored without acknowledgement */ if (urb->status == -ENOENT) { return; } f = &usbvision->curFrame; /* Manage streaming interruption */ if (usbvision->streaming == Stream_Interrupt) { usbvision->streaming = Stream_Idle; if ((*f)) { (*f)->grabstate = FrameState_Ready; (*f)->scanstate = ScanState_Scanning; } PDEBUG(DBG_IRQ, "stream interrupted"); wake_up_interruptible(&usbvision->wait_stream); } /* Copy the data received into our scratch buffer */ len = usbvision_compress_isochronous(usbvision, urb); usbvision->isocUrbCount++; usbvision->urb_length = len; if (usbvision->streaming == Stream_On) { /* If we collected enough data let's parse! */ if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) && (!list_empty(&(usbvision->inqueue))) ) { if (!(*f)) { (*f) = list_entry(usbvision->inqueue.next, struct usbvision_frame, frame); } usbvision_parse_data(usbvision); } else { /*If we don't have a frame we're current working on, complain */ PDEBUG(DBG_IRQ, "received data, but no one needs it"); scratch_reset(usbvision); } } else { PDEBUG(DBG_IRQ, "received data, but no one needs it"); scratch_reset(usbvision); } usbvision->timeInIrq += jiffies - startTime; for (i = 0; i < USBVISION_URB_FRAMES; i++) { urb->iso_frame_desc[i].status = 0; urb->iso_frame_desc[i].actual_length = 0; } urb->status = 0; urb->dev = usbvision->dev; errCode = usb_submit_urb (urb, GFP_ATOMIC); if(errCode) { err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); } return;}/*************************************//* Low level usbvision access functions *//*************************************//* * usbvision_read_reg() * * return < 0 -> Error * >= 0 -> Data */int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg){ int errCode = 0; unsigned char buffer[1]; if (!USBVISION_IS_OPERATIONAL(usbvision)) return -1; errCode = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) reg, buffer, 1, HZ); if (errCode < 0) { err("%s: failed: error %d", __FUNCTION__, errCode); return errCode; } return buffer[0];}/* * usbvision_write_reg() * * return 1 -> Reg written * 0 -> usbvision is not yet ready * -1 -> Something went wrong */int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg, unsigned char value){ int errCode = 0; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ); if (errCode < 0) { err("%s: failed: error %d", __FUNCTION__, errCode); } return errCode;}static void usbvision_ctrlUrb_complete(struct urb *urb){ struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context; PDEBUG(DBG_IRQ, ""); usbvision->ctrlUrbBusy = 0; if (waitqueue_active(&usbvision->ctrlUrb_wq)) { wake_up_interruptible(&usbvision->ctrlUrb_wq); }}static int usbvision_write_reg_irq(struct usb_usbvision *usbvision,int address, unsigned char *data, int len){ int errCode = 0; PDEBUG(DBG_IRQ, ""); if (len > 8) { return -EFAULT; }// down(&usbvision->ctrlUrbLock); if (usbvision->ctrlUrbBusy) {// up(&usbvision->ctrlUrbLock); return -EBUSY; } usbvision->ctrlUrbBusy = 1;// up(&usbvision->ctrlUrbLock); usbvision->ctrlUrbSetup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; usbvision->ctrlUrbSetup.bRequest = USBVISION_OP_CODE; usbvision->ctrlUrbSetup.wValue = 0; usbvision->ctrlUrbSetup.wIndex = cpu_to_le16(address); usbvision->ctrlUrbSetup.wLength = cpu_to_le16(len); usb_fill_control_urb (usbvision->ctrlUrb, usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), (unsigned char *)&usbvision->ctrlUrbSetup, (void *)usbvision->ctrlUrbBuffer, len, usbvision_ctrlUrb_complete, (void *)usbvision); memcpy(usbvision->ctrlUrbBuffer, data, len); errCode = usb_submit_urb(usbvision->ctrlUrb, GFP_ATOMIC); if (errCode < 0) { // error in usb_submit_urb() usbvision->ctrlUrbBusy = 0; } PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, errCode); return errCode;}static int usbvision_init_compression(struct usb_usbvision *usbvision){ int errCode = 0; usbvision->lastIsocFrameNum = -1; usbvision->isocDataCount = 0; usbvision->isocPacketCount = 0; usbvision->isocSkipCount = 0; usbvision->comprLevel = 50; usbvision->lastComprLevel = -1; usbvision->isocUrbCount = 0; usbvision->requestIntra = 1; usbvision->isocMeasureBandwidthCount = 0; return errCode;}/* this function measures the used bandwidth since last call * return: 0 : no error * sets usedBandwidth to 1-100 : 1-100% of full bandwidth resp. to isocPacketSize */static int usbvision_measure_bandwidth (struct usb_usbvision *usbvision){ int errCode = 0; if (usbvision->isocMeasureBandwidthCount < 2) { // this gives an average bandwidth of 3 frames usbvision->isocMeasureBandwidthCount++; return errCode; } if ((usbvision->isocPacketSize > 0) && (usbvision->isocPacketCount > 0)) { usbvision->usedBandwidth = usbvision->isocDataCount / (usbvision->isocPacketCount + usbvision->isocSkipCount) * 100 / usbvision->isocPacketSize; } usbvision->isocMeasureBandwidthCount = 0; usbvision->isocDataCount = 0; usbvision->isocPacketCount = 0; usbvision->isocSkipCount = 0; return errCode;}static int usbvision_adjust_compression (struct usb_usbvision *usbvision){ int errCode = 0; unsigned char buffer[6]; PDEBUG(DBG_IRQ, ""); if ((adjustCompression) && (usbvision->usedBandwidth > 0)) { usbvision->comprLevel += (usbvision->usedBandwidth - 90) / 2; RESTRICT_TO_RANGE(usbvision->comprLevel, 0, 100); if (usbvision->comprLevel != usbvision->lastComprLevel) { int distorsion; if (usbvision->bridgeType == BRIDGE_NT1004 || usbvision->bridgeType == BRIDGE_NT1005) { buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM Threshold 1 buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM Threshold 2 distorsion = 7 + 248 * usbvision->comprLevel / 100; buffer[2] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (inter) buffer[3] = (unsigned char)(distorsion & 0xFF); // Average distorsion Threshold (intra) distorsion = 1 + 42 * usbvision->comprLevel / 100; buffer[4] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (inter) buffer[5] = (unsigned char)(distorsion & 0xFF); // Maximum distorsion Threshold (intra) } else { //BRIDGE_NT1003 buffer[0] = (unsigned char)(4 + 16 * usbvision->comprLevel / 100); // PCM threshold 1 buffer[1] = (unsigned char)(4 + 8 * usbvision->comprLevel / 100); // PCM threshold 2 distorsion = 2 + 253 * usbvision->comprLevel / 100; buffer[2] = (unsigned char)(distorsion & 0xFF); // distorsion threshold bit0-7 buffer[3] = 0; //(unsigned char)((distorsion >> 8) & 0x0F); // distorsion threshold bit 8-11 distorsion = 0 + 43 * usbvision->comprLevel / 100; buffer[4] = (unsigned char)(distorsion & 0xFF); // maximum distorsion bit0-7 buffer[5] = 0; //(unsigned char)((distorsion >> 8) & 0x01); // maximum distorsion bit 8 } errCode = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6); if (errCode == 0){ PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); usbvision->lastComprLevel = usbvision->comprLevel; } } } return errCode;}static int usbvision_request_intra (struct usb_usbvision *usbvision){ int errCode = 0; unsigned char buffer[1]; PDEBUG(DBG_IRQ, ""); usbvision->requestIntra = 1; buffer[0] = 1; usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); return errCode;}static int usbvision_unrequest_intra (struct usb_usbvision *usbvision){ int errCode = 0; unsigned char buffer[1]; PDEBUG(DBG_IRQ, ""); usbvision->requestIntra = 0; buffer[0] = 0; usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1); return errCode;}/******************************* * usbvision utility functions *******************************/int usbvision_power_off(struct usb_usbvision *usbvision){ int errCode = 0; PDEBUG(DBG_FUNC, ""); errCode = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN); if (errCode == 1) { usbvision->power = 0; } PDEBUG(DBG_FUNC, "%s: errCode %d", (errCode!=1)?"ERROR":"power is off", errCode); return errCode;}/* * usbvision_set_video_format() * */static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format){ static const char proc[] = "usbvision_set_video_format"; int rc; unsigned char value[2]; if (!USBVISION_IS_OPERATIONAL(usbvision)) return 0; PDEBUG(DBG_FUNC, "isocMode %#02x", format); if ((format != ISOC_MODE_YUV422) && (format != ISOC_MODE_YUV420) && (format != ISOC_MODE_COMPRESS)) { printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420", format); format = ISOC_MODE_YUV420; } value[0] = 0x0A; //TODO: See the effect of the filter value[1] = format; // Sets the VO_MODE register which follows FILT_CONT rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_FILT_CONT, value, 2, HZ); if (rc < 0) { printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - " "reconnect or reload driver.\n", proc, rc); } usbvision->isocMode = format; return rc;}/* * usbvision_set_output() * */int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height){ int errCode = 0; int UsbWidth, UsbHeight; unsigned int frameRate=0, frameDrop=0; unsigned char value[4]; if (!USBVISION_IS_OPERATIONAL(usbvision)) { return 0; } if (width > MAX_USB_WIDTH) { UsbWidth = width / 2; usbvision->stretch_width = 2; } else { UsbWidth = width; usbvision->stretch_width = 1; } if (height > MAX_USB_HEIGHT) { UsbHeight = height / 2; usbvision->stretch_height = 2; } else { UsbHeight = height; usbvision->stretch_height = 1; } RESTRICT_TO_RANGE(UsbWidth, MIN_FRAME_WIDTH, MAX_USB_WIDTH); UsbWidth &= ~(MIN_FRAME_WIDTH-1); RESTRICT_TO_RANGE(UsbHeight, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT); UsbHeight &= ~(1); PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d", UsbWidth, UsbHeight, width, height, usbvision->stretch_width, usbvision->stretch_height); /* I'll not rewrite the same values */ if ((UsbWidth != usbvision->curwidth) || (UsbHeight != usbvision->curheight)) { value[0] = UsbWidth & 0xff; //LSB value[1] = (UsbWidth >> 8) & 0x03; //MSB value[2] = UsbHeight & 0xff; //LSB value[3] = (UsbHeight >> 8) & 0x03; //MSB errCode = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1), USBVISION_OP_CODE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ); if (errCode < 0) { err("%s failed: error %d", __FUNCTION__, errCode); return errCode; } usbvision->curwidth = usbvision->stretch_width * UsbWidth; usbvision->curheight = usbvision->stretch_height * UsbHeight; } if (usbvision->isocMode == ISOC_MODE_YUV422) { frameRate = (usbvision->isocPacketSize * 1000) / (UsbWidth * UsbHeight * 2); } else if (usbvision->isocMode == ISOC_MODE_YUV420) { frameRate = (usbvision->isocPacketSize * 1000) / ((UsbWidth * UsbHeight * 12) / 8); } else { frameRate = FRAMERATE_MAX; } if (usbvision->tvnormId & V4L2_STD_625_50) { frameDrop = frameRate * 32 / 25 - 1; } else if (usbvision->tvnormId & V4L2_STD_525_60) { frameDrop = frameRate * 32 / 30 - 1; } RESTRICT_TO_RANGE(frameDrop, FRAMERATE_MIN, FRAMERATE_MAX); PDEBUG(DBG_FUNC, "frameRate %d fps, frameDrop %d", frameRate, frameDrop); frameDrop = FRAMERATE_MAX; // We can allow the maximum here, because dropping is controlled /* frameDrop = 7; => framePhase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ... => frameSkip = 4; => frameRate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?