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