• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/media/video/pvrusb2/
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 = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
358				if (!nb) return -ENOMEM;
359				memcpy(nb,sp->buffers,scnt * sizeof(*nb));
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); do {
518		spin_lock_irqsave(&sp->list_lock,irq_flags);
519		sp->callback_data = data;
520		sp->callback_func = func;
521		spin_unlock_irqrestore(&sp->list_lock,irq_flags);
522	} while(0); mutex_unlock(&sp->mutex);
523}
524
525void pvr2_stream_get_stats(struct pvr2_stream *sp,
526			   struct pvr2_stream_stats *stats,
527			   int zero_counts)
528{
529	unsigned long irq_flags;
530	spin_lock_irqsave(&sp->list_lock,irq_flags);
531	if (stats) {
532		stats->buffers_in_queue = sp->q_count;
533		stats->buffers_in_idle = sp->i_count;
534		stats->buffers_in_ready = sp->r_count;
535		stats->buffers_processed = sp->buffers_processed;
536		stats->buffers_failed = sp->buffers_failed;
537		stats->bytes_processed = sp->bytes_processed;
538	}
539	if (zero_counts) {
540		sp->buffers_processed = 0;
541		sp->buffers_failed = 0;
542		sp->bytes_processed = 0;
543	}
544	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
545}
546
547/* Query / set the nominal buffer count */
548int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
549{
550	return sp->buffer_target_count;
551}
552
553int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
554{
555	int ret;
556	if (sp->buffer_target_count == cnt) return 0;
557	mutex_lock(&sp->mutex); do {
558		sp->buffer_target_count = cnt;
559		ret = pvr2_stream_achieve_buffer_count(sp);
560	} while(0); mutex_unlock(&sp->mutex);
561	return ret;
562}
563
564struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
565{
566	struct list_head *lp = sp->idle_list.next;
567	if (lp == &sp->idle_list) return NULL;
568	return list_entry(lp,struct pvr2_buffer,list_overhead);
569}
570
571struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
572{
573	struct list_head *lp = sp->ready_list.next;
574	if (lp == &sp->ready_list) return NULL;
575	return list_entry(lp,struct pvr2_buffer,list_overhead);
576}
577
578struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
579{
580	if (id < 0) return NULL;
581	if (id >= sp->buffer_total_count) return NULL;
582	return sp->buffers[id];
583}
584
585int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
586{
587	return sp->r_count;
588}
589
590void pvr2_stream_kill(struct pvr2_stream *sp)
591{
592	struct pvr2_buffer *bp;
593	mutex_lock(&sp->mutex); do {
594		pvr2_stream_internal_flush(sp);
595		while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
596			pvr2_buffer_set_idle(bp);
597		}
598		if (sp->buffer_total_count != sp->buffer_target_count) {
599			pvr2_stream_achieve_buffer_count(sp);
600		}
601	} while(0); mutex_unlock(&sp->mutex);
602}
603
604int pvr2_buffer_queue(struct pvr2_buffer *bp)
605{
606#undef SEED_BUFFER
607#ifdef SEED_BUFFER
608	unsigned int idx;
609	unsigned int val;
610#endif
611	int ret = 0;
612	struct pvr2_stream *sp;
613	if (!bp) return -EINVAL;
614	sp = bp->stream;
615	mutex_lock(&sp->mutex); do {
616		pvr2_buffer_wipe(bp);
617		if (!sp->dev) {
618			ret = -EIO;
619			break;
620		}
621		pvr2_buffer_set_queued(bp);
622#ifdef SEED_BUFFER
623		for (idx = 0; idx < (bp->max_count) / 4; idx++) {
624			val = bp->id << 24;
625			val |= idx;
626			((unsigned int *)(bp->ptr))[idx] = val;
627		}
628#endif
629		bp->status = -EINPROGRESS;
630		usb_fill_bulk_urb(bp->purb,      // struct urb *urb
631				  sp->dev,       // struct usb_device *dev
632				  // endpoint (below)
633				  usb_rcvbulkpipe(sp->dev,sp->endpoint),
634				  bp->ptr,       // void *transfer_buffer
635				  bp->max_count, // int buffer_length
636				  buffer_complete,
637				  bp);
638		usb_submit_urb(bp->purb,GFP_KERNEL);
639	} while(0); mutex_unlock(&sp->mutex);
640	return ret;
641}
642
643int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
644{
645	int ret = 0;
646	unsigned long irq_flags;
647	struct pvr2_stream *sp;
648	if (!bp) return -EINVAL;
649	sp = bp->stream;
650	mutex_lock(&sp->mutex); do {
651		spin_lock_irqsave(&sp->list_lock,irq_flags);
652		if (bp->state != pvr2_buffer_state_idle) {
653			ret = -EPERM;
654		} else {
655			bp->ptr = ptr;
656			bp->stream->i_bcount -= bp->max_count;
657			bp->max_count = cnt;
658			bp->stream->i_bcount += bp->max_count;
659			pvr2_trace(PVR2_TRACE_BUF_FLOW,
660				   "/*---TRACE_FLOW---*/ bufferPool    "
661				   " %8s cap cap=%07d cnt=%02d",
662				   pvr2_buffer_state_decode(
663					   pvr2_buffer_state_idle),
664				   bp->stream->i_bcount,bp->stream->i_count);
665		}
666		spin_unlock_irqrestore(&sp->list_lock,irq_flags);
667	} while(0); mutex_unlock(&sp->mutex);
668	return ret;
669}
670
671unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
672{
673	return bp->used_count;
674}
675
676int pvr2_buffer_get_status(struct pvr2_buffer *bp)
677{
678	return bp->status;
679}
680
681int pvr2_buffer_get_id(struct pvr2_buffer *bp)
682{
683	return bp->id;
684}
685
686
687/*
688  Stuff for Emacs to see, in order to encourage consistent editing style:
689  *** Local Variables: ***
690  *** mode: c ***
691  *** fill-column: 75 ***
692  *** tab-width: 8 ***
693  *** c-basic-offset: 8 ***
694  *** End: ***
695  */
696