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

📄 em28xx-core.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v){	u8 mode;	/* the em2800 scaler only supports scaling down to 50% */	if(dev->is_em2800)		mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);	else {		u8 buf[2];		buf[0] = h;		buf[1] = h >> 8;		em28xx_write_regs(dev, HSCALELOW_REG, (char *)buf, 2);		buf[0] = v;		buf[1] = v >> 8;		em28xx_write_regs(dev, VSCALELOW_REG, (char *)buf, 2);		/* it seems that both H and V scalers must be active to work correctly */		mode = (h || v)? 0x30: 0x00;	}	return em28xx_write_reg_bits(dev, COMPR_REG, mode, 0x30);}/* FIXME: this only function read values from dev */int em28xx_resolution_set(struct em28xx *dev){	int width, height;	width = norm_maxw(dev);	height = norm_maxh(dev) >> 1;	em28xx_outfmt_set_yuv422(dev);	em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);	em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);	return em28xx_scaler_set(dev, dev->hscale, dev->vscale);}/******************* isoc transfer handling ****************************/#ifdef ENABLE_DEBUG_ISOC_FRAMESstatic void em28xx_isoc_dump(struct urb *urb, struct pt_regs *regs){	int len = 0;	int ntrans = 0;	int i;	printk(KERN_DEBUG "isocIrq: sf=%d np=%d ec=%x\n",	       urb->start_frame, urb->number_of_packets,	       urb->error_count);	for (i = 0; i < urb->number_of_packets; i++) {		unsigned char *buf =				urb->transfer_buffer +				urb->iso_frame_desc[i].offset;		int alen = urb->iso_frame_desc[i].actual_length;		if (alen > 0) {			if (buf[0] == 0x88) {				ntrans++;				len += alen;			} else if (buf[0] == 0x22) {				printk(KERN_DEBUG						"= l=%d nt=%d bpp=%d\n",				len - 4 * ntrans, ntrans,				ntrans == 0 ? 0 : len / ntrans);				ntrans = 1;				len = alen;			} else				printk(KERN_DEBUG "!\n");		}		printk(KERN_DEBUG "   n=%d s=%d al=%d %x\n", i,		       urb->iso_frame_desc[i].status,		       urb->iso_frame_desc[i].actual_length,		       (unsigned int)				       *((unsigned char *)(urb->transfer_buffer +				       urb->iso_frame_desc[i].				       offset)));	}}#endifstatic inline int em28xx_isoc_video(struct em28xx *dev,struct em28xx_frame_t **f,				    unsigned long *lock_flags, unsigned char buf){	if (!(buf & 0x01)) {		if ((*f)->state == F_GRABBING) {			/*previous frame is incomplete */			if ((*f)->fieldbytesused < dev->field_size) {				(*f)->state = F_ERROR;				em28xx_isocdbg ("dropping incomplete bottom field (%i missing bytes)",					 dev->field_size-(*f)->fieldbytesused);			} else {				(*f)->state = F_DONE;				(*f)->buf.bytesused = dev->frame_size;			}		}		if ((*f)->state == F_DONE || (*f)->state == F_ERROR) {			/* move current frame to outqueue and get next free buffer from inqueue */			spin_lock_irqsave(&dev-> queue_lock, *lock_flags);			list_move_tail(&(*f)->frame, &dev->outqueue);			if (!list_empty(&dev->inqueue))				(*f) = list_entry(dev-> inqueue.next,			struct em28xx_frame_t,frame);			else				(*f) = NULL;			spin_unlock_irqrestore(&dev->queue_lock,*lock_flags);		}		if (!(*f)) {			em28xx_isocdbg ("new frame but no buffer is free");			return -1;		}		do_gettimeofday(&(*f)->buf.timestamp);		(*f)->buf.sequence = ++dev->frame_count;		(*f)->buf.field = V4L2_FIELD_INTERLACED;		(*f)->state = F_GRABBING;		(*f)->buf.bytesused = 0;		(*f)->top_field = 1;		(*f)->fieldbytesused = 0;	} else {					/* acquiring bottom field */		if ((*f)->state == F_GRABBING) {			if (!(*f)->top_field) {				(*f)->state = F_ERROR;				em28xx_isocdbg ("unexpected begin of bottom field; discarding it");			} else if ((*f)-> fieldbytesused < dev->field_size - 172) {				(*f)->state = F_ERROR;				em28xx_isocdbg ("dropping incomplete top field (%i missing bytes)",					 dev->field_size-(*f)->fieldbytesused);			} else {				(*f)->top_field = 0;				(*f)->fieldbytesused = 0;			}		}	}	return (0);}static inline void em28xx_isoc_video_copy(struct em28xx *dev,					  struct em28xx_frame_t **f, unsigned char *buf, int len){	void *fieldstart, *startwrite, *startread;	int linesdone, currlinedone, offset, lencopy,remain;	if(dev->frame_size != (*f)->buf.length){		em28xx_err("frame_size %i and buf.length %i are different!!!\n",dev->frame_size,(*f)->buf.length);		return;	}	if ((*f)->fieldbytesused + len > dev->field_size)		len =dev->field_size - (*f)->fieldbytesused;	if (buf[0] != 0x88 && buf[0] != 0x22) {		em28xx_isocdbg("frame is not complete\n");		startread = buf;		len+=4;	} else		startread = buf + 4;	remain = len;	if ((*f)->top_field)		fieldstart = (*f)->bufmem;	else		fieldstart = (*f)->bufmem + dev->bytesperline;	linesdone = (*f)->fieldbytesused / dev->bytesperline;	currlinedone = (*f)->fieldbytesused % dev->bytesperline;	offset = linesdone * dev->bytesperline * 2 + currlinedone;	startwrite = fieldstart + offset;	lencopy = dev->bytesperline - currlinedone;	lencopy = lencopy > remain ? remain : lencopy;	memcpy(startwrite, startread, lencopy);	remain -= lencopy;	while (remain > 0) {		startwrite += lencopy + dev->bytesperline;		startread += lencopy;		if (dev->bytesperline > remain)			lencopy = remain;		else			lencopy = dev->bytesperline;		memcpy(startwrite, startread, lencopy);		remain -= lencopy;	}	(*f)->fieldbytesused += len;}/* * em28xx_isoIrq() * handles the incoming isoc urbs and fills the frames from our inqueue */void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs){	struct em28xx *dev = urb->context;	int i, status;	struct em28xx_frame_t **f;	unsigned long lock_flags;	if (!dev)		return;#ifdef ENABLE_DEBUG_ISOC_FRAMES	if (isoc_debug>1)		em28xx_isoc_dump(urb, regs);#endif	if (urb->status == -ENOENT)		return;	f = &dev->frame_current;	if (dev->stream == STREAM_INTERRUPT) {		dev->stream = STREAM_OFF;		if ((*f))			(*f)->state = F_QUEUED;		em28xx_isocdbg("stream interrupted");		wake_up_interruptible(&dev->wait_stream);	}	if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))		return;	if (dev->stream == STREAM_ON && !list_empty(&dev->inqueue)) {		if (!(*f))			(*f) = list_entry(dev->inqueue.next,		struct em28xx_frame_t, frame);		for (i = 0; i < urb->number_of_packets; i++) {			unsigned char *buf = urb->transfer_buffer +					urb->iso_frame_desc[i].offset;			int len = urb->iso_frame_desc[i].actual_length - 4;			if (urb->iso_frame_desc[i].status) {				em28xx_isocdbg("data error: [%d] len=%d, status=%d", i,					urb->iso_frame_desc[i].actual_length,					urb->iso_frame_desc[i].status);				if (urb->iso_frame_desc[i].status != -EPROTO)					continue;			}			if (urb->iso_frame_desc[i].actual_length <= 0) {				em28xx_isocdbg("packet %d is empty",i);				continue;			}			if (urb->iso_frame_desc[i].actual_length >						 dev->max_pkt_size) {				em28xx_isocdbg("packet bigger than packet size");				continue;			}			/*new frame */			if (buf[0] == 0x22 && buf[1] == 0x5a) {				em28xx_isocdbg("Video frame, length=%i!",len);				if (em28xx_isoc_video(dev,f,&lock_flags,buf[2]))				break;			} else if (buf[0]==0x33 && buf[1]==0x95 && buf[2]==0x00) {				em28xx_isocdbg("VBI HEADER!!!");			}			/* actual copying */			if ((*f)->state == F_GRABBING) {				em28xx_isoc_video_copy(dev,f,buf, len);			}		}	}	for (i = 0; i < urb->number_of_packets; i++) {		urb->iso_frame_desc[i].status = 0;		urb->iso_frame_desc[i].actual_length = 0;	}	urb->status = 0;	if ((status = usb_submit_urb(urb, GFP_ATOMIC))) {		em28xx_errdev("resubmit of urb failed (error=%i)\n", status);		dev->state |= DEV_MISCONFIGURED;	}	wake_up_interruptible(&dev->wait_frame);	return;}/* * em28xx_uninit_isoc() * deallocates the buffers and urbs allocated during em28xx_init_iosc() */void em28xx_uninit_isoc(struct em28xx *dev){	int i;	for (i = 0; i < EM28XX_NUM_BUFS; i++) {		if (dev->urb[i]) {			usb_kill_urb(dev->urb[i]);			if (dev->transfer_buffer[i]){				usb_buffer_free(dev->udev,(EM28XX_NUM_PACKETS*dev->max_pkt_size),dev->transfer_buffer[i],dev->urb[i]->transfer_dma);			}			usb_free_urb(dev->urb[i]);		}		dev->urb[i] = NULL;		dev->transfer_buffer[i] = NULL;	}	em28xx_capture_start(dev, 0);}/* * em28xx_init_isoc() * allocates transfer buffers and submits the urbs for isoc transfer */int em28xx_init_isoc(struct em28xx *dev){	/* change interface to 3 which allowes the biggest packet sizes */	int i, errCode;	const int sb_size = EM28XX_NUM_PACKETS * dev->max_pkt_size;	/* reset streaming vars */	dev->frame_current = NULL;	dev->frame_count = 0;	/* allocate urbs */	for (i = 0; i < EM28XX_NUM_BUFS; i++) {		struct urb *urb;		int j, k;		/* allocate transfer buffer */		urb = usb_alloc_urb(EM28XX_NUM_PACKETS, GFP_KERNEL);		if (!urb){			em28xx_errdev("cannot alloc urb %i\n", i);			em28xx_uninit_isoc(dev);			return -ENOMEM;		}		dev->transfer_buffer[i] = usb_buffer_alloc(dev->udev, sb_size, GFP_KERNEL,&urb->transfer_dma);		if (!dev->transfer_buffer[i]) {			em28xx_errdev					("unable to allocate %i bytes for transfer buffer %i\n",					 sb_size, i);			em28xx_uninit_isoc(dev);			return -ENOMEM;		}		memset(dev->transfer_buffer[i], 0, sb_size);		urb->dev = dev->udev;		urb->context = dev;		urb->pipe = usb_rcvisocpipe(dev->udev, 0x82);		urb->transfer_flags = URB_ISO_ASAP;		urb->interval = 1;		urb->transfer_buffer = dev->transfer_buffer[i];		urb->complete = em28xx_isocIrq;		urb->number_of_packets = EM28XX_NUM_PACKETS;		urb->transfer_buffer_length = sb_size;		for (j = k = 0; j < EM28XX_NUM_PACKETS;				j++, k += dev->max_pkt_size) {			urb->iso_frame_desc[j].offset = k;			urb->iso_frame_desc[j].length =				dev->max_pkt_size;		}		dev->urb[i] = urb;	}	/* submit urbs */	for (i = 0; i < EM28XX_NUM_BUFS; i++) {		errCode = usb_submit_urb(dev->urb[i], GFP_KERNEL);		if (errCode) {			em28xx_errdev("submit of urb %i failed (error=%i)\n", i,				      errCode);			em28xx_uninit_isoc(dev);			return errCode;		}	}	return 0;}int em28xx_set_alternate(struct em28xx *dev){	int errCode, prev_alt = dev->alt;	dev->alt = alt;	if (dev->alt == 0) {		int i;		for(i=0;i< dev->num_alt; i++)			if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt])				dev->alt=i;	}	if (dev->alt != prev_alt) {		dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];		em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", dev->alt,		       dev->max_pkt_size);		errCode = usb_set_interface(dev->udev, 0, dev->alt);		if (errCode < 0) {			em28xx_errdev ("cannot change alternate number to %d (error=%i)\n",							dev->alt, errCode);			return errCode;		}	}	return 0;}

⌨️ 快捷键说明

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