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

📄 pvrusb2-io.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 2 页
字号:
			/* Paranoia */			sp->buffers[sp->buffer_total_count - 1] = 0;			(sp->buffer_total_count)--;			pvr2_buffer_done(bp);			kfree(bp);		}		if (scnt < sp->buffer_slot_count) {			struct pvr2_buffer **nb = 0;			if (scnt) {				nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);				if (!nb) return -ENOMEM;				memcpy(nb,sp->buffers,scnt * sizeof(*nb));			}			kfree(sp->buffers);			sp->buffers = nb;			sp->buffer_slot_count = scnt;		}	}	return 0;}static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp){	struct pvr2_buffer *bp;	unsigned int cnt;	if (sp->buffer_total_count == sp->buffer_target_count) return 0;	pvr2_trace(PVR2_TRACE_BUF_POOL,		   "/*---TRACE_FLOW---*/"		   " poolCheck      stream=%p cur=%d tgt=%d",		   sp,sp->buffer_total_count,sp->buffer_target_count);	if (sp->buffer_total_count < sp->buffer_target_count) {		return pvr2_stream_buffer_count(sp,sp->buffer_target_count);	}	cnt = 0;	while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {		bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];		if (bp->state != pvr2_buffer_state_idle) break;		cnt++;	}	if (cnt) {		pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);	}	return 0;}static void pvr2_stream_internal_flush(struct pvr2_stream *sp){	struct list_head *lp;	struct pvr2_buffer *bp1;	while ((lp = sp->queued_list.next) != &sp->queued_list) {		bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);		pvr2_buffer_wipe(bp1);		/* At this point, we should be guaranteed that no		   completion callback may happen on this buffer.  But it's		   possible that it might have completed after we noticed		   it but before we wiped it.  So double check its status		   here first. */		if (bp1->state != pvr2_buffer_state_queued) continue;		pvr2_buffer_set_idle(bp1);	}	if (sp->buffer_total_count != sp->buffer_target_count) {		pvr2_stream_achieve_buffer_count(sp);	}}static void pvr2_stream_init(struct pvr2_stream *sp){	spin_lock_init(&sp->list_lock);	mutex_init(&sp->stream_mutex);	INIT_LIST_HEAD(&sp->queued_list);	INIT_LIST_HEAD(&sp->ready_list);	INIT_LIST_HEAD(&sp->idle_list);}static void pvr2_stream_done(struct pvr2_stream *sp){	mutex_lock(&sp->stream_mutex); do {		pvr2_stream_internal_flush(sp);		pvr2_stream_buffer_count(sp,0);	} while (0); mutex_unlock(&sp->stream_mutex);}static void buffer_complete(struct urb *urb, struct pt_regs *regs){	struct pvr2_buffer *bp = urb->context;	struct pvr2_stream *sp;	unsigned long irq_flags;	BUFFER_CHECK(bp);	sp = bp->stream;	bp->used_count = 0;	bp->status = 0;	pvr2_trace(PVR2_TRACE_BUF_FLOW,		   "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",		   bp,urb->status,urb->actual_length);	spin_lock_irqsave(&sp->list_lock,irq_flags);	if ((!(urb->status)) ||	    (urb->status == -ENOENT) ||	    (urb->status == -ECONNRESET) ||	    (urb->status == -ESHUTDOWN)) {		bp->used_count = urb->actual_length;		if (sp->fail_count) {			pvr2_trace(PVR2_TRACE_TOLERANCE,				   "stream %p transfer ok"				   " - fail count reset",sp);			sp->fail_count = 0;		}	} else if (sp->fail_count < sp->fail_tolerance) {		// We can tolerate this error, because we're below the		// threshold...		(sp->fail_count)++;		pvr2_trace(PVR2_TRACE_TOLERANCE,			   "stream %p ignoring error %d"			   " - fail count increased to %u",			   sp,urb->status,sp->fail_count);	} else {		bp->status = urb->status;	}	spin_unlock_irqrestore(&sp->list_lock,irq_flags);	pvr2_buffer_set_ready(bp);	if (sp && sp->callback_func) {		sp->callback_func(sp->callback_data);	}}struct pvr2_stream *pvr2_stream_create(void){	struct pvr2_stream *sp;	sp = kmalloc(sizeof(*sp),GFP_KERNEL);	if (!sp) return sp;	memset(sp,0,sizeof(*sp));	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);	pvr2_stream_init(sp);	return sp;}void pvr2_stream_destroy(struct pvr2_stream *sp){	if (!sp) return;	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);	pvr2_stream_done(sp);	kfree(sp);}void pvr2_stream_setup(struct pvr2_stream *sp,		       struct usb_device *dev,		       int endpoint,		       unsigned int tolerance){	mutex_lock(&sp->stream_mutex); do {		pvr2_stream_internal_flush(sp);		sp->dev = dev;		sp->endpoint = endpoint;		sp->fail_tolerance = tolerance;	} while(0); mutex_unlock(&sp->stream_mutex);}void pvr2_stream_set_callback(struct pvr2_stream *sp,			      pvr2_stream_callback func,			      void *data){	unsigned long irq_flags;	mutex_lock(&sp->stream_mutex); do {		spin_lock_irqsave(&sp->list_lock,irq_flags);		sp->callback_data = data;		sp->callback_func = func;		spin_unlock_irqrestore(&sp->list_lock,irq_flags);	} while(0); mutex_unlock(&sp->stream_mutex);}/* Query / set the nominal buffer count */int pvr2_stream_get_buffer_count(struct pvr2_stream *sp){	return sp->buffer_target_count;}int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt){	int ret;	if (sp->buffer_target_count == cnt) return 0;	mutex_lock(&sp->stream_mutex); do {		sp->buffer_target_count = cnt;		ret = pvr2_stream_achieve_buffer_count(sp);	} while(0); mutex_unlock(&sp->stream_mutex);	return ret;}struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp){	struct list_head *lp = sp->idle_list.next;	if (lp == &sp->idle_list) return 0;	return list_entry(lp,struct pvr2_buffer,list_overhead);}struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp){	struct list_head *lp = sp->ready_list.next;	if (lp == &sp->ready_list) return 0;	return list_entry(lp,struct pvr2_buffer,list_overhead);}struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id){	if (id < 0) return 0;	if (id >= sp->buffer_total_count) return 0;	return sp->buffers[id];}int pvr2_stream_get_ready_count(struct pvr2_stream *sp){	return sp->r_count;}int pvr2_stream_get_idle_count(struct pvr2_stream *sp){	return sp->i_count;}void pvr2_stream_flush(struct pvr2_stream *sp){	mutex_lock(&sp->stream_mutex); do {		pvr2_stream_internal_flush(sp);	} while(0); mutex_unlock(&sp->stream_mutex);}void pvr2_stream_kill(struct pvr2_stream *sp){	struct pvr2_buffer *bp;	mutex_lock(&sp->stream_mutex); do {		pvr2_stream_internal_flush(sp);		while ((bp = pvr2_stream_get_ready_buffer(sp)) != 0) {			pvr2_buffer_set_idle(bp);		}		if (sp->buffer_total_count != sp->buffer_target_count) {			pvr2_stream_achieve_buffer_count(sp);		}	} while(0); mutex_unlock(&sp->stream_mutex);}int pvr2_buffer_queue(struct pvr2_buffer *bp){#undef SEED_BUFFER#ifdef SEED_BUFFER	unsigned int idx;	unsigned int val;#endif	int ret = 0;	struct pvr2_stream *sp;	if (!bp) return -EINVAL;	sp = bp->stream;	mutex_lock(&sp->stream_mutex); do {		pvr2_buffer_wipe(bp);		if (!sp->dev) {			ret = -EIO;			break;		}		pvr2_buffer_set_queued(bp);#ifdef SEED_BUFFER		for (idx = 0; idx < (bp->max_count) / 4; idx++) {			val = bp->id << 24;			val |= idx;			((unsigned int *)(bp->ptr))[idx] = val;		}#endif		bp->status = -EINPROGRESS;		usb_fill_bulk_urb(bp->purb,      // struct urb *urb				  sp->dev,       // struct usb_device *dev				  // endpoint (below)				  usb_rcvbulkpipe(sp->dev,sp->endpoint),				  bp->ptr,       // void *transfer_buffer				  bp->max_count, // int buffer_length				  buffer_complete,				  bp);		usb_submit_urb(bp->purb,GFP_KERNEL);	} while(0); mutex_unlock(&sp->stream_mutex);	return ret;}int pvr2_buffer_idle(struct pvr2_buffer *bp){	struct pvr2_stream *sp;	if (!bp) return -EINVAL;	sp = bp->stream;	mutex_lock(&sp->stream_mutex); do {		pvr2_buffer_wipe(bp);		pvr2_buffer_set_idle(bp);		if (sp->buffer_total_count != sp->buffer_target_count) {			pvr2_stream_achieve_buffer_count(sp);		}	} while(0); mutex_unlock(&sp->stream_mutex);	return 0;}int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt){	int ret = 0;	unsigned long irq_flags;	struct pvr2_stream *sp;	if (!bp) return -EINVAL;	sp = bp->stream;	mutex_lock(&sp->stream_mutex); do {		spin_lock_irqsave(&sp->list_lock,irq_flags);		if (bp->state != pvr2_buffer_state_idle) {			ret = -EPERM;		} else {			bp->ptr = ptr;			bp->stream->i_bcount -= bp->max_count;			bp->max_count = cnt;			bp->stream->i_bcount += bp->max_count;			pvr2_trace(PVR2_TRACE_BUF_FLOW,				   "/*---TRACE_FLOW---*/ bufferPool    "				   " %8s cap cap=%07d cnt=%02d",				   pvr2_buffer_state_decode(					   pvr2_buffer_state_idle),				   bp->stream->i_bcount,bp->stream->i_count);		}		spin_unlock_irqrestore(&sp->list_lock,irq_flags);	} while(0); mutex_unlock(&sp->stream_mutex);	return ret;}unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp){	return bp->used_count;}int pvr2_buffer_get_status(struct pvr2_buffer *bp){	return bp->status;}enum pvr2_buffer_state pvr2_buffer_get_state(struct pvr2_buffer *bp){	return bp->state;}int pvr2_buffer_get_id(struct pvr2_buffer *bp){	return bp->id;}/*  Stuff for Emacs to see, in order to encourage consistent editing style:  *** Local Variables: ***  *** mode: c ***  *** fill-column: 75 ***  *** tab-width: 8 ***  *** c-basic-offset: 8 ***  *** End: ***  */

⌨️ 快捷键说明

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