1/*
2 *
3 *
4 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 2 of the License
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 *
19 */
20
21#include "pvrusb2-io.h"
22#include "pvrusb2-debug.h"
23#include <linux/errno.h>
24#include <linux/string.h>
25#include <linux/slab.h>
26#include <linux/mutex.h>
27
28static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
29
30#define BUFFER_SIG 0x47653271
31
32// #define SANITY_CHECK_BUFFERS
33
34
35#ifdef SANITY_CHECK_BUFFERS
36#define BUFFER_CHECK(bp) do { \
37	if ((bp)->signature != BUFFER_SIG) { \
38		pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
39		"Buffer %p is bad at %s:%d", \
40		(bp),__FILE__,__LINE__); \
41		pvr2_buffer_describe(bp,"BadSig"); \
42		BUG(); \
43	} \
44} while (0)
45#else
46#define BUFFER_CHECK(bp) do {} while(0)
47#endif
48
49struct pvr2_stream {
50	/* Buffers queued for reading */
51	struct list_head queued_list;
52	unsigned int q_count;
53	unsigned int q_bcount;
54	/* Buffers with retrieved data */
55	struct list_head ready_list;
56	unsigned int r_count;
57	unsigned int r_bcount;
58	/* Buffers available for use */
59	struct list_head idle_list;
60	unsigned int i_count;
61	unsigned int i_bcount;
62	/* Pointers to all buffers */
63	struct pvr2_buffer **buffers;
64	/* Array size of buffers */
65	unsigned int buffer_slot_count;
66	/* Total buffers actually in circulation */
67	unsigned int buffer_total_count;
68	/* Designed number of buffers to be in circulation */
69	unsigned int buffer_target_count;
70	/* Executed when ready list become non-empty */
71	pvr2_stream_callback callback_func;
72	void *callback_data;
73	/* Context for transfer endpoint */
74	struct usb_device *dev;
75	int endpoint;
76	/* Overhead for mutex enforcement */
77	spinlock_t list_lock;
78	struct mutex mutex;
79	/* Tracking state for tolerating errors */
80	unsigned int fail_count;
81	unsigned int fail_tolerance;
82
83	unsigned int buffers_processed;
84	unsigned int buffers_failed;
85	unsigned int bytes_processed;
86};
87
88struct pvr2_buffer {
89	int id;
90	int signature;
91	enum pvr2_buffer_state state;
92	void *ptr;               /* Pointer to storage area */
93	unsigned int max_count;  /* Size of storage area */
94	unsigned int used_count; /* Amount of valid data in storage area */
95	int status;              /* Transfer result status */
96	struct pvr2_stream *stream;
97	struct list_head list_overhead;
98	struct urb *purb;
99};
100
101static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
102{
103	switch (st) {
104	case pvr2_buffer_state_none: return "none";
105	case pvr2_buffer_state_idle: return "idle";
106	case pvr2_buffer_state_queued: return "queued";
107	case pvr2_buffer_state_ready: return "ready";
108	}
109	return "unknown";
110}
111
112#ifdef SANITY_CHECK_BUFFERS
113static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
114{
115	pvr2_trace(PVR2_TRACE_INFO,
116		   "buffer%s%s %p state=%s id=%d status=%d"
117		   " stream=%p purb=%p sig=0x%x",
118		   (msg ? " " : ""),
119		   (msg ? msg : ""),
120		   bp,
121		   (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
122		   (bp ? bp->id : 0),
123		   (bp ? bp->status : 0),
124		   (bp ? bp->stream : NULL),
125		   (bp ? bp->purb : NULL),
126		   (bp ? bp->signature : 0));
127}
128#endif  /*  SANITY_CHECK_BUFFERS  */
129
130static void pvr2_buffer_remove(struct pvr2_buffer *bp)
131{
132	unsigned int *cnt;
133	unsigned int *bcnt;
134	unsigned int ccnt;
135	struct pvr2_stream *sp = bp->stream;
136	switch (bp->state) {
137	case pvr2_buffer_state_idle:
138		cnt = &sp->i_count;
139		bcnt = &sp->i_bcount;
140		ccnt = bp->max_count;
141		break;
142	case pvr2_buffer_state_queued:
143		cnt = &sp->q_count;
144		bcnt = &sp->q_bcount;
145		ccnt = bp->max_count;
146		break;
147	case pvr2_buffer_state_ready:
148		cnt = &sp->r_count;
149		bcnt = &sp->r_bcount;
150		ccnt = bp->used_count;
151		break;
152	default:
153		return;
154	}
155	list_del_init(&bp->list_overhead);
156	(*cnt)--;
157	(*bcnt) -= ccnt;
158	pvr2_trace(PVR2_TRACE_BUF_FLOW,
159		   "/*---TRACE_FLOW---*/"
160		   " bufferPool     %8s dec cap=%07d cnt=%02d",
161		   pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
162	bp->state = pvr2_buffer_state_none;
163}
164
165static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
166{
167	unsigned long irq_flags;
168	struct pvr2_stream *sp;
169	BUFFER_CHECK(bp);
170	sp = bp->stream;
171	pvr2_trace(PVR2_TRACE_BUF_FLOW,
172		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
173		   bp,
174		   pvr2_buffer_state_decode(bp->state),
175		   pvr2_buffer_state_decode(pvr2_buffer_state_none));
176	spin_lock_irqsave(&sp->list_lock,irq_flags);
177	pvr2_buffer_remove(bp);
178	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
179}
180
181static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
182{
183	int fl;
184	unsigned long irq_flags;
185	struct pvr2_stream *sp;
186	BUFFER_CHECK(bp);
187	sp = bp->stream;
188	pvr2_trace(PVR2_TRACE_BUF_FLOW,
189		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
190		   bp,
191		   pvr2_buffer_state_decode(bp->state),
192		   pvr2_buffer_state_decode(pvr2_buffer_state_ready));
193	spin_lock_irqsave(&sp->list_lock,irq_flags);
194	fl = (sp->r_count == 0);
195	pvr2_buffer_remove(bp);
196	list_add_tail(&bp->list_overhead,&sp->ready_list);
197	bp->state = pvr2_buffer_state_ready;
198	(sp->r_count)++;
199	sp->r_bcount += bp->used_count;
200	pvr2_trace(PVR2_TRACE_BUF_FLOW,
201		   "/*---TRACE_FLOW---*/"
202		   " bufferPool     %8s inc cap=%07d cnt=%02d",
203		   pvr2_buffer_state_decode(bp->state),
204		   sp->r_bcount,sp->r_count);
205	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
206	return fl;
207}
208
209static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
210{
211	unsigned long irq_flags;
212	struct pvr2_stream *sp;
213	BUFFER_CHECK(bp);
214	sp = bp->stream;
215	pvr2_trace(PVR2_TRACE_BUF_FLOW,
216		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
217		   bp,
218		   pvr2_buffer_state_decode(bp->state),
219		   pvr2_buffer_state_decode(pvr2_buffer_state_idle));
220	spin_lock_irqsave(&sp->list_lock,irq_flags);
221	pvr2_buffer_remove(bp);
222	list_add_tail(&bp->list_overhead,&sp->idle_list);
223	bp->state = pvr2_buffer_state_idle;
224	(sp->i_count)++;
225	sp->i_bcount += bp->max_count;
226	pvr2_trace(PVR2_TRACE_BUF_FLOW,
227		   "/*---TRACE_FLOW---*/"
228		   " bufferPool     %8s inc cap=%07d cnt=%02d",
229		   pvr2_buffer_state_decode(bp->state),
230		   sp->i_bcount,sp->i_count);
231	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
232}
233
234static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
235{
236	unsigned long irq_flags;
237	struct pvr2_stream *sp;
238	BUFFER_CHECK(bp);
239	sp = bp->stream;
240	pvr2_trace(PVR2_TRACE_BUF_FLOW,
241		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
242		   bp,
243		   pvr2_buffer_state_decode(bp->state),
244		   pvr2_buffer_state_decode(pvr2_buffer_state_queued));
245	spin_lock_irqsave(&sp->list_lock,irq_flags);
246	pvr2_buffer_remove(bp);
247	list_add_tail(&bp->list_overhead,&sp->queued_list);
248	bp->state = pvr2_buffer_state_queued;
249	(sp->q_count)++;
250	sp->q_bcount += bp->max_count;
251	pvr2_trace(PVR2_TRACE_BUF_FLOW,
252		   "/*---TRACE_FLOW---*/"
253		   " bufferPool     %8s inc cap=%07d cnt=%02d",
254		   pvr2_buffer_state_decode(bp->state),
255		   sp->q_bcount,sp->q_count);
256	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
257}
258
259static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
260{
261	if (bp->state == pvr2_buffer_state_queued) {
262		usb_kill_urb(bp->purb);
263	}
264}
265
266static int pvr2_buffer_init(struct pvr2_buffer *bp,
267			    struct pvr2_stream *sp,
268			    unsigned int id)
269{
270	memset(bp,0,sizeof(*bp));
271	bp->signature = BUFFER_SIG;
272	bp->id = id;
273	pvr2_trace(PVR2_TRACE_BUF_POOL,
274		   "/*---TRACE_FLOW---*/ bufferInit     %p stream=%p",bp,sp);
275	bp->stream = sp;
276	bp->state = pvr2_buffer_state_none;
277	INIT_LIST_HEAD(&bp->list_overhead);
278	bp->purb = usb_alloc_urb(0,GFP_KERNEL);
279	if (! bp->purb) return -ENOMEM;
280#ifdef SANITY_CHECK_BUFFERS
281	pvr2_buffer_describe(bp,"create");
282#endif
283	return 0;
284}
285
286static void pvr2_buffer_done(struct pvr2_buffer *bp)
287{
288#ifdef SANITY_CHECK_BUFFERS
289	pvr2_buffer_describe(bp,"delete");
290#endif
291	pvr2_buffer_wipe(bp);
292	pvr2_buffer_set_none(bp);
293	bp->signature = 0;
294	bp->stream = NULL;
295	usb_free_urb(bp->purb);
296	pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
297		   " bufferDone     %p",bp);
298}
299
300static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
301{
302	int ret;
303	unsigned int scnt;
304
305	/* Allocate buffers pointer array in multiples of 32 entries */
306	if (cnt == sp->buffer_total_count) return 0;
307
308	pvr2_trace(PVR2_TRACE_BUF_POOL,
309		   "/*---TRACE_FLOW---*/ poolResize    "
310		   " stream=%p cur=%d adj=%+d",
311		   sp,
312		   sp->buffer_total_count,
313		   cnt-sp->buffer_total_count);
314
315	scnt = cnt & ~0x1f;
316	if (cnt > scnt) scnt += 0x20;
317
318	if (cnt > sp->buffer_total_count) {
319		if (scnt > sp->buffer_slot_count) {
320			struct pvr2_buffer **nb;
321			nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
322			if (!nb) return -ENOMEM;
323			if (sp->buffer_slot_count) {
324				memcpy(nb,sp->buffers,
325				       sp->buffer_slot_count * sizeof(*nb));
326				kfree(sp->buffers);
327			}
328			sp->buffers = nb;
329			sp->buffer_slot_count = scnt;
330		}
331		while (sp->buffer_total_count < cnt) {
332			struct pvr2_buffer *bp;
333			bp = kmalloc(sizeof(*bp),GFP_KERNEL);
334			if (!bp) return -ENOMEM;
335			ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count);
336			if (ret) {
337				kfree(bp);
338				return -ENOMEM;
339			}
340			sp->buffers[sp->buffer_total_count] = bp;
341			(sp->buffer_total_count)++;
342			pvr2_buffer_set_idle(bp);
343		}
344	} else {
345		while (sp->buffer_total_count > cnt) {
346			struct pvr2_buffer *bp;
347			bp = sp->buffers[sp->buffer_total_count - 1];
348			/* Paranoia */
349			sp->buffers[sp->buffer_total_count - 1] = NULL;
350			(sp->buffer_total_count)--;
351			pvr2_buffer_done(bp);
352			kfree(bp);
353		}
354		if (scnt < sp->buffer_slot_count) {
355			struct pvr2_buffer **nb = NULL;
356			if (scnt) {
357				nb = kmemdup(sp->buffers, scnt * sizeof(*nb),
358					     GFP_KERNEL);
359				if (!nb) return -ENOMEM;
360			}
361			kfree(sp->buffers);
362			sp->buffers = nb;
363			sp->buffer_slot_count = scnt;
364		}
365	}
366	return 0;
367}
368
369static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
370{
371	struct pvr2_buffer *bp;
372	unsigned int cnt;
373
374	if (sp->buffer_total_count == sp->buffer_target_count) return 0;
375
376	pvr2_trace(PVR2_TRACE_BUF_POOL,
377		   "/*---TRACE_FLOW---*/"
378		   " poolCheck      stream=%p cur=%d tgt=%d",
379		   sp,sp->buffer_total_count,sp->buffer_target_count);
380
381	if (sp->buffer_total_count < sp->buffer_target_count) {
382		return pvr2_stream_buffer_count(sp,sp->buffer_target_count);
383	}
384
385	cnt = 0;
386	while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
387		bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
388		if (bp->state != pvr2_buffer_state_idle) break;
389		cnt++;
390	}
391	if (cnt) {
392		pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);
393	}
394
395	return 0;
396}
397
398static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
399{
400	struct list_head *lp;
401	struct pvr2_buffer *bp1;
402	while ((lp = sp->queued_list.next) != &sp->queued_list) {
403		bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);
404		pvr2_buffer_wipe(bp1);
405		/* At this point, we should be guaranteed that no
406		   completion callback may happen on this buffer.  But it's
407		   possible that it might have completed after we noticed
408		   it but before we wiped it.  So double check its status
409		   here first. */
410		if (bp1->state != pvr2_buffer_state_queued) continue;
411		pvr2_buffer_set_idle(bp1);
412	}
413	if (sp->buffer_total_count != sp->buffer_target_count) {
414		pvr2_stream_achieve_buffer_count(sp);
415	}
416}
417
418static void pvr2_stream_init(struct pvr2_stream *sp)
419{
420	spin_lock_init(&sp->list_lock);
421	mutex_init(&sp->mutex);
422	INIT_LIST_HEAD(&sp->queued_list);
423	INIT_LIST_HEAD(&sp->ready_list);
424	INIT_LIST_HEAD(&sp->idle_list);
425}
426
427static void pvr2_stream_done(struct pvr2_stream *sp)
428{
429	mutex_lock(&sp->mutex); do {
430		pvr2_stream_internal_flush(sp);
431		pvr2_stream_buffer_count(sp,0);
432	} while (0); mutex_unlock(&sp->mutex);
433}
434
435static void buffer_complete(struct urb *urb)
436{
437	struct pvr2_buffer *bp = urb->context;
438	struct pvr2_stream *sp;
439	unsigned long irq_flags;
440	BUFFER_CHECK(bp);
441	sp = bp->stream;
442	bp->used_count = 0;
443	bp->status = 0;
444	pvr2_trace(PVR2_TRACE_BUF_FLOW,
445		   "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
446		   bp,urb->status,urb->actual_length);
447	spin_lock_irqsave(&sp->list_lock,irq_flags);
448	if ((!(urb->status)) ||
449	    (urb->status == -ENOENT) ||
450	    (urb->status == -ECONNRESET) ||
451	    (urb->status == -ESHUTDOWN)) {
452		(sp->buffers_processed)++;
453		sp->bytes_processed += urb->actual_length;
454		bp->used_count = urb->actual_length;
455		if (sp->fail_count) {
456			pvr2_trace(PVR2_TRACE_TOLERANCE,
457				   "stream %p transfer ok"
458				   " - fail count reset",sp);
459			sp->fail_count = 0;
460		}
461	} else if (sp->fail_count < sp->fail_tolerance) {
462		// We can tolerate this error, because we're below the
463		// threshold...
464		(sp->fail_count)++;
465		(sp->buffers_failed)++;
466		pvr2_trace(PVR2_TRACE_TOLERANCE,
467			   "stream %p ignoring error %d"
468			   " - fail count increased to %u",
469			   sp,urb->status,sp->fail_count);
470	} else {
471		(sp->buffers_failed)++;
472		bp->status = urb->status;
473	}
474	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
475	pvr2_buffer_set_ready(bp);
476	if (sp && sp->callback_func) {
477		sp->callback_func(sp->callback_data);
478	}
479}
480
481struct pvr2_stream *pvr2_stream_create(void)
482{
483	struct pvr2_stream *sp;
484	sp = kzalloc(sizeof(*sp),GFP_KERNEL);
485	if (!sp) return sp;
486	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
487	pvr2_stream_init(sp);
488	return sp;
489}
490
491void pvr2_stream_destroy(struct pvr2_stream *sp)
492{
493	if (!sp) return;
494	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);
495	pvr2_stream_done(sp);
496	kfree(sp);
497}
498
499void pvr2_stream_setup(struct pvr2_stream *sp,
500		       struct usb_device *dev,
501		       int endpoint,
502		       unsigned int tolerance)
503{
504	mutex_lock(&sp->mutex); do {
505		pvr2_stream_internal_flush(sp);
506		sp->dev = dev;
507		sp->endpoint = endpoint;
508		sp->fail_tolerance = tolerance;
509	} while(0); mutex_unlock(&sp->mutex);
510}
511
512void pvr2_stream_set_callback(struct pvr2_stream *sp,
513			      pvr2_stream_callback func,
514			      void *data)
515{
516	unsigned long irq_flags;
517	mutex_lock(&sp->mutex);
518	do {
519		spin_lock_irqsave(&sp->list_lock,irq_flags);
520		sp->callback_data = data;
521		sp->callback_func = func;
522		spin_unlock_irqrestore(&sp->list_lock,irq_flags);
523	} while(0);
524	mutex_unlock(&sp->mutex);
525}
526
527void pvr2_stream_get_stats(struct pvr2_stream *sp,
528			   struct pvr2_stream_stats *stats,
529			   int zero_counts)
530{
531	unsigned long irq_flags;
532	spin_lock_irqsave(&sp->list_lock,irq_flags);
533	if (stats) {
534		stats->buffers_in_queue = sp->q_count;
535		stats->buffers_in_idle = sp->i_count;
536		stats->buffers_in_ready = sp->r_count;
537		stats->buffers_processed = sp->buffers_processed;
538		stats->buffers_failed = sp->buffers_failed;
539		stats->bytes_processed = sp->bytes_processed;
540	}
541	if (zero_counts) {
542		sp->buffers_processed = 0;
543		sp->buffers_failed = 0;
544		sp->bytes_processed = 0;
545	}
546	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
547}
548
549/* Query / set the nominal buffer count */
550int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
551{
552	return sp->buffer_target_count;
553}
554
555int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
556{
557	int ret;
558	if (sp->buffer_target_count == cnt) return 0;
559	mutex_lock(&sp->mutex);
560	do {
561		sp->buffer_target_count = cnt;
562		ret = pvr2_stream_achieve_buffer_count(sp);
563	} while(0);
564	mutex_unlock(&sp->mutex);
565	return ret;
566}
567
568struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
569{
570	struct list_head *lp = sp->idle_list.next;
571	if (lp == &sp->idle_list) return NULL;
572	return list_entry(lp,struct pvr2_buffer,list_overhead);
573}
574
575struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
576{
577	struct list_head *lp = sp->ready_list.next;
578	if (lp == &sp->ready_list) return NULL;
579	return list_entry(lp,struct pvr2_buffer,list_overhead);
580}
581
582struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
583{
584	if (id < 0) return NULL;
585	if (id >= sp->buffer_total_count) return NULL;
586	return sp->buffers[id];
587}
588
589int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
590{
591	return sp->r_count;
592}
593
594void pvr2_stream_kill(struct pvr2_stream *sp)
595{
596	struct pvr2_buffer *bp;
597	mutex_lock(&sp->mutex);
598	do {
599		pvr2_stream_internal_flush(sp);
600		while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
601			pvr2_buffer_set_idle(bp);
602		}
603		if (sp->buffer_total_count != sp->buffer_target_count) {
604			pvr2_stream_achieve_buffer_count(sp);
605		}
606	} while(0);
607	mutex_unlock(&sp->mutex);
608}
609
610int pvr2_buffer_queue(struct pvr2_buffer *bp)
611{
612#undef SEED_BUFFER
613#ifdef SEED_BUFFER
614	unsigned int idx;
615	unsigned int val;
616#endif
617	int ret = 0;
618	struct pvr2_stream *sp;
619	if (!bp) return -EINVAL;
620	sp = bp->stream;
621	mutex_lock(&sp->mutex);
622	do {
623		pvr2_buffer_wipe(bp);
624		if (!sp->dev) {
625			ret = -EIO;
626			break;
627		}
628		pvr2_buffer_set_queued(bp);
629#ifdef SEED_BUFFER
630		for (idx = 0; idx < (bp->max_count) / 4; idx++) {
631			val = bp->id << 24;
632			val |= idx;
633			((unsigned int *)(bp->ptr))[idx] = val;
634		}
635#endif
636		bp->status = -EINPROGRESS;
637		usb_fill_bulk_urb(bp->purb,      // struct urb *urb
638				  sp->dev,       // struct usb_device *dev
639				  // endpoint (below)
640				  usb_rcvbulkpipe(sp->dev,sp->endpoint),
641				  bp->ptr,       // void *transfer_buffer
642				  bp->max_count, // int buffer_length
643				  buffer_complete,
644				  bp);
645		usb_submit_urb(bp->purb,GFP_KERNEL);
646	} while(0);
647	mutex_unlock(&sp->mutex);
648	return ret;
649}
650
651int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
652{
653	int ret = 0;
654	unsigned long irq_flags;
655	struct pvr2_stream *sp;
656	if (!bp) return -EINVAL;
657	sp = bp->stream;
658	mutex_lock(&sp->mutex);
659	do {
660		spin_lock_irqsave(&sp->list_lock,irq_flags);
661		if (bp->state != pvr2_buffer_state_idle) {
662			ret = -EPERM;
663		} else {
664			bp->ptr = ptr;
665			bp->stream->i_bcount -= bp->max_count;
666			bp->max_count = cnt;
667			bp->stream->i_bcount += bp->max_count;
668			pvr2_trace(PVR2_TRACE_BUF_FLOW,
669				   "/*---TRACE_FLOW---*/ bufferPool    "
670				   " %8s cap cap=%07d cnt=%02d",
671				   pvr2_buffer_state_decode(
672					   pvr2_buffer_state_idle),
673				   bp->stream->i_bcount,bp->stream->i_count);
674		}
675		spin_unlock_irqrestore(&sp->list_lock,irq_flags);
676	} while(0);
677	mutex_unlock(&sp->mutex);
678	return ret;
679}
680
681unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
682{
683	return bp->used_count;
684}
685
686int pvr2_buffer_get_status(struct pvr2_buffer *bp)
687{
688	return bp->status;
689}
690
691int pvr2_buffer_get_id(struct pvr2_buffer *bp)
692{
693	return bp->id;
694}
695