~ubuntu-branches/ubuntu/trusty/gnuradio/trusty

« back to all changes in this revision

Viewing changes to usrp/host/lib/legacy/fusb_linux.cc

  • Committer: Bazaar Package Importer
  • Author(s): Kamal Mostafa
  • Date: 2010-03-13 07:46:01 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100313074601-zjsa893a87bozyh7
Tags: 3.2.2.dfsg-1ubuntu1
* Fix build for Ubuntu lucid (LP: #260406)
  - add binary package dep for libusrp0, libusrp2-0: adduser
  - debian/rules clean: remove pre-built Qt moc files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- c++ -*- */
 
2
/*
 
3
 * Copyright 2003 Free Software Foundation, Inc.
 
4
 * 
 
5
 * This file is part of GNU Radio
 
6
 * 
 
7
 * GNU Radio 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 3, or (at your option)
 
10
 * any later version.
 
11
 * 
 
12
 * GNU Radio is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 * 
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with GNU Radio; see the file COPYING.  If not, write to
 
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
 
20
 * Boston, MA 02110-1301, USA.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
#include "config.h"
 
25
#endif
 
26
 
 
27
#include <fusb_linux.h>
 
28
#include <usb.h>                // libusb header
 
29
#include <stdexcept>
 
30
#ifdef HAVE_LINUX_COMPILER_H
 
31
#include <linux/compiler.h>
 
32
#endif
 
33
#include <linux/usbdevice_fs.h> // interface to kernel portion of user mode usb driver
 
34
#include <sys/ioctl.h>
 
35
#include <assert.h>
 
36
#include <string.h>
 
37
#include <algorithm>
 
38
#include <errno.h>
 
39
#include <string.h>
 
40
#include <cstdio>
 
41
 
 
42
#define MINIMIZE_TX_BUFFERING 1         // must be defined to 0 or 1
 
43
 
 
44
 
 
45
static const int MAX_BLOCK_SIZE = fusb_sysconfig::max_block_size();             // hard limit
 
46
static const int DEFAULT_BLOCK_SIZE = MAX_BLOCK_SIZE;
 
47
static const int DEFAULT_BUFFER_SIZE = 4 * (1L << 20);                          // 4 MB / endpoint
 
48
 
 
49
 
 
50
// Totally evil and fragile extraction of file descriptor from
 
51
// guts of libusb.  They don't install usbi.h, which is what we'd need
 
52
// to do this nicely.
 
53
//
 
54
// FIXME if everything breaks someday in the future, look here...
 
55
 
 
56
static int
 
57
fd_from_usb_dev_handle (usb_dev_handle *udh)
 
58
{
 
59
  return *((int *) udh);
 
60
}
 
61
 
 
62
inline static void
 
63
urb_set_ephandle (usbdevfs_urb *urb, fusb_ephandle_linux *handle)
 
64
{
 
65
  urb->usercontext = handle;
 
66
}
 
67
 
 
68
inline static fusb_ephandle_linux *
 
69
urb_get_ephandle (usbdevfs_urb *urb)
 
70
{
 
71
  return (fusb_ephandle_linux *) urb->usercontext;
 
72
}
 
73
 
 
74
// ------------------------------------------------------------------------
 
75
//                 USB request block (urb) allocation
 
76
// ------------------------------------------------------------------------
 
77
 
 
78
static usbdevfs_urb *
 
79
alloc_urb (fusb_ephandle_linux *self, int buffer_length, int endpoint,
 
80
           bool input_p, unsigned char *write_buffer)
 
81
{
 
82
  usbdevfs_urb  *urb = new usbdevfs_urb;
 
83
  memset (urb, 0, sizeof (*urb));
 
84
 
 
85
  urb->buffer_length = buffer_length;
 
86
 
 
87
  // We allocate dedicated memory only for input buffers.
 
88
  // For output buffers we reuse the same buffer (the kernel 
 
89
  // copies the data at submital time)
 
90
 
 
91
  if (input_p)
 
92
    urb->buffer = new unsigned char [buffer_length];
 
93
  else
 
94
    urb->buffer = write_buffer;
 
95
 
 
96
  // init common values
 
97
 
 
98
  urb->type = USBDEVFS_URB_TYPE_BULK;
 
99
  urb->endpoint = (endpoint & 0x7f) | (input_p ? 0x80 : 0);
 
100
 
 
101
  // USBDEVFS_URB_QUEUE_BULK goes away in linux 2.5, but is needed if
 
102
  // we are using a 2.4 usb-uhci host controller driver.  This is
 
103
  // unlikely since we're almost always going to be plugged into a
 
104
  // high speed host controller (ehci)
 
105
#if 0 && defined (USBDEVFS_URB_QUEUE_BULK)
 
106
  urb->flags = USBDEVFS_URB_QUEUE_BULK;
 
107
#endif
 
108
 
 
109
  urb->signr = 0;
 
110
  urb_set_ephandle (urb, self);
 
111
 
 
112
  return urb;
 
113
}
 
114
 
 
115
static void
 
116
free_urb (usbdevfs_urb *urb)
 
117
{
 
118
  // if this was an input urb, free the buffer
 
119
  if (urb->endpoint & 0x80)
 
120
    delete [] ((unsigned char *) urb->buffer);
 
121
 
 
122
  delete urb;
 
123
}
 
124
 
 
125
// ------------------------------------------------------------------------
 
126
//                              device handle
 
127
// ------------------------------------------------------------------------
 
128
 
 
129
fusb_devhandle_linux::fusb_devhandle_linux (usb_dev_handle *udh)
 
130
  : fusb_devhandle (udh)
 
131
{
 
132
  // that's all
 
133
}
 
134
 
 
135
fusb_devhandle_linux::~fusb_devhandle_linux ()
 
136
{
 
137
  // if there are any pending requests, cancel them and free the urbs.
 
138
  
 
139
  std::list<usbdevfs_urb*>::reverse_iterator it;
 
140
 
 
141
  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){
 
142
    _cancel_urb (*it);
 
143
    free_urb (*it);
 
144
  }
 
145
}
 
146
 
 
147
fusb_ephandle *
 
148
fusb_devhandle_linux::make_ephandle (int endpoint, bool input_p,
 
149
                                     int block_size, int nblocks)
 
150
{
 
151
  return new fusb_ephandle_linux (this, endpoint, input_p,
 
152
                                  block_size, nblocks);
 
153
}
 
154
 
 
155
 
 
156
// Attempt to cancel all transactions associated with eph.
 
157
 
 
158
void
 
159
fusb_devhandle_linux::_cancel_pending_rqsts (fusb_ephandle_linux *eph)
 
160
{
 
161
  std::list<usbdevfs_urb*>::reverse_iterator it;
 
162
 
 
163
  for (it = d_pending_rqsts.rbegin (); it != d_pending_rqsts.rend (); it++){
 
164
    if (urb_get_ephandle (*it) == eph)
 
165
      _cancel_urb (*it);
 
166
  }
 
167
}
 
168
 
 
169
void 
 
170
fusb_devhandle_linux::pending_add (usbdevfs_urb *urb)
 
171
{
 
172
  d_pending_rqsts.push_back (urb);
 
173
}
 
174
 
 
175
usbdevfs_urb *
 
176
fusb_devhandle_linux::pending_get ()
 
177
{
 
178
  if (d_pending_rqsts.empty ())
 
179
    return 0;
 
180
 
 
181
  usbdevfs_urb *urb = d_pending_rqsts.front ();
 
182
  d_pending_rqsts.pop_front ();
 
183
  return urb;
 
184
}
 
185
 
 
186
bool
 
187
fusb_devhandle_linux::pending_remove (usbdevfs_urb *urb)
 
188
{
 
189
  std::list<usbdevfs_urb*>::iterator    result = find (d_pending_rqsts.begin (),
 
190
                                                       d_pending_rqsts.end (),
 
191
                                                       urb);
 
192
  if (result == d_pending_rqsts.end ()){
 
193
    fprintf (stderr, "fusb::pending_remove: failed to find urb in pending_rqsts: %p\n", urb);
 
194
    return false;
 
195
  }
 
196
  d_pending_rqsts.erase (result);
 
197
  return true;
 
198
}
 
199
 
 
200
/*
 
201
 * Submit the urb to the kernel.
 
202
 * iff successful, the urb will be placed on the devhandle's pending list.
 
203
 */
 
204
bool
 
205
fusb_devhandle_linux::_submit_urb (usbdevfs_urb *urb)
 
206
{
 
207
  int   ret;
 
208
 
 
209
  ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_SUBMITURB, urb);
 
210
  if (ret < 0){
 
211
    perror ("fusb::_submit_urb");
 
212
    return false;
 
213
  }
 
214
  
 
215
  pending_add (urb);
 
216
  return true;
 
217
}
 
218
 
 
219
/*
 
220
 * Attempt to cancel the in pending or in-progress urb transaction.
 
221
 * Return true iff transaction was sucessfully cancelled.
 
222
 *
 
223
 * Failure to cancel should not be considered a problem.  This frequently
 
224
 * occurs if the transaction has already completed in the kernel but hasn't
 
225
 * yet been reaped by the user mode code.
 
226
 *
 
227
 * urbs which were cancelled have their status field set to -ENOENT when
 
228
 * they are reaped.
 
229
 */
 
230
bool
 
231
fusb_devhandle_linux::_cancel_urb (usbdevfs_urb *urb)
 
232
{
 
233
  int ret = ioctl (fd_from_usb_dev_handle (d_udh), USBDEVFS_DISCARDURB, urb);
 
234
  if (ret < 0){
 
235
    // perror ("fusb::_cancel_urb");
 
236
    return false;
 
237
  }
 
238
  return true;
 
239
}
 
240
 
 
241
/*
 
242
 * Check with the kernel and see if any of our outstanding requests
 
243
 * have completed.  For each completed transaction, remove it from the
 
244
 * devhandle's pending list and append it to the completed list for
 
245
 * the corresponding endpoint.
 
246
 *
 
247
 * If any transactions are reaped return true.
 
248
 *
 
249
 * If ok_to_block_p is true, then this will block until at least one
 
250
 * transaction completes or an unrecoverable error occurs.
 
251
 */
 
252
bool
 
253
fusb_devhandle_linux::_reap (bool ok_to_block_p)
 
254
{
 
255
  int           ret;
 
256
  int           nreaped = 0;
 
257
  usbdevfs_urb  *urb = 0;
 
258
 
 
259
  int   fd = fd_from_usb_dev_handle (d_udh);
 
260
  
 
261
  // try to reap as many as possible without blocking...
 
262
 
 
263
  while ((ret = ioctl (fd, USBDEVFS_REAPURBNDELAY, &urb)) == 0){
 
264
    if (urb->status != 0 && urb->status != -ENOENT){
 
265
      fprintf (stderr, "_reap: usb->status = %d, actual_length = %5d\n",
 
266
               urb->status, urb->actual_length);
 
267
    }
 
268
    pending_remove (urb);
 
269
    urb_get_ephandle (urb)->completed_list_add (urb);
 
270
    nreaped++;
 
271
  }
 
272
 
 
273
  if (nreaped > 0)              // if we got any, return w/o blocking
 
274
    return true;
 
275
 
 
276
  if (!ok_to_block_p)
 
277
    return false;
 
278
  
 
279
  ret = ioctl (fd, USBDEVFS_REAPURB, &urb);
 
280
  if (ret < 0){
 
281
    perror ("fusb::_reap");
 
282
    return false;
 
283
  }
 
284
 
 
285
  pending_remove (urb);
 
286
  urb_get_ephandle (urb)->completed_list_add (urb);
 
287
  return true;
 
288
}
 
289
 
 
290
void
 
291
fusb_devhandle_linux::_wait_for_completion ()
 
292
{
 
293
  while (!d_pending_rqsts.empty ())
 
294
    if (!_reap(true))
 
295
      break;
 
296
}
 
297
// ------------------------------------------------------------------------
 
298
//                           end point handle
 
299
// ------------------------------------------------------------------------
 
300
 
 
301
fusb_ephandle_linux::fusb_ephandle_linux (fusb_devhandle_linux *devhandle,
 
302
                                          int endpoint,
 
303
                                          bool input_p,
 
304
                                          int block_size, int nblocks)
 
305
  : fusb_ephandle (endpoint, input_p, block_size, nblocks),
 
306
    d_devhandle (devhandle), 
 
307
    d_write_work_in_progress (0), d_write_buffer (0),
 
308
    d_read_work_in_progress (0), d_read_buffer (0), d_read_buffer_end (0)
 
309
{
 
310
 
 
311
  if (d_block_size < 0 || d_block_size > MAX_BLOCK_SIZE)
 
312
    throw std::out_of_range ("fusb_ephandle_linux: block_size");
 
313
 
 
314
  if (d_nblocks < 0)
 
315
    throw std::out_of_range ("fusb_ephandle_linux: nblocks");
 
316
 
 
317
  if (d_block_size == 0)
 
318
    d_block_size = DEFAULT_BLOCK_SIZE;
 
319
 
 
320
  if (d_nblocks == 0)
 
321
    d_nblocks = std::max (1, DEFAULT_BUFFER_SIZE / d_block_size);
 
322
 
 
323
  if (!d_input_p)
 
324
    if (!MINIMIZE_TX_BUFFERING)
 
325
      d_write_buffer = new unsigned char [d_block_size];
 
326
 
 
327
  if (0)
 
328
    fprintf(stderr, "fusb_ephandle_linux::ctor: d_block_size = %d  d_nblocks = %d\n",
 
329
            d_block_size, d_nblocks);
 
330
 
 
331
  // allocate urbs
 
332
 
 
333
  for (int i = 0; i < d_nblocks; i++)
 
334
    d_free_list.push_back (alloc_urb (this, d_block_size, d_endpoint,
 
335
                                      d_input_p, d_write_buffer));
 
336
}
 
337
 
 
338
fusb_ephandle_linux::~fusb_ephandle_linux ()
 
339
{
 
340
  stop ();
 
341
 
 
342
  usbdevfs_urb *urb;
 
343
 
 
344
  while ((urb = free_list_get ()) != 0)
 
345
    free_urb (urb);
 
346
 
 
347
  while ((urb = completed_list_get ()) != 0)
 
348
    free_urb (urb);
 
349
 
 
350
  if (d_write_work_in_progress)
 
351
    free_urb (d_write_work_in_progress);
 
352
 
 
353
  delete [] d_write_buffer;
 
354
 
 
355
  if (d_read_work_in_progress)
 
356
    free_urb (d_read_work_in_progress);
 
357
}
 
358
 
 
359
// ----------------------------------------------------------------
 
360
 
 
361
bool
 
362
fusb_ephandle_linux::start ()
 
363
{
 
364
  if (d_started)
 
365
    return true;                // already running
 
366
 
 
367
  d_started = true;
 
368
 
 
369
  if (d_input_p){               // fire off all the reads
 
370
    usbdevfs_urb *urb;
 
371
 
 
372
    int nerrors = 0;
 
373
    while ((urb = free_list_get ()) != 0 && nerrors < d_nblocks){
 
374
      if (!submit_urb (urb))
 
375
        nerrors++;
 
376
    }
 
377
  }
 
378
 
 
379
  return true;
 
380
}
 
381
 
 
382
//
 
383
// kill all i/o in progress.
 
384
// kill any completed but unprocessed transactions.
 
385
//
 
386
bool
 
387
fusb_ephandle_linux::stop ()
 
388
{
 
389
  if (!d_started)
 
390
    return true;
 
391
 
 
392
  if (d_write_work_in_progress){
 
393
    free_list_add (d_write_work_in_progress);
 
394
    d_write_work_in_progress = 0;
 
395
  }
 
396
 
 
397
  if (d_read_work_in_progress){
 
398
    free_list_add (d_read_work_in_progress);
 
399
    d_read_work_in_progress = 0;
 
400
    d_read_buffer = 0;
 
401
    d_read_buffer_end = 0;
 
402
  }
 
403
 
 
404
  d_devhandle->_cancel_pending_rqsts (this);
 
405
  d_devhandle->_reap (false);
 
406
 
 
407
  while (1){
 
408
    usbdevfs_urb *urb;
 
409
    while ((urb = completed_list_get ()) != 0)
 
410
      free_list_add (urb);
 
411
 
 
412
    if (d_free_list.size () == (unsigned) d_nblocks)
 
413
      break;
 
414
 
 
415
    if (!d_devhandle->_reap(true))
 
416
      break;
 
417
  }
 
418
 
 
419
  d_started = false;
 
420
  return true;
 
421
}
 
422
 
 
423
// ----------------------------------------------------------------
 
424
//                      routines for writing 
 
425
// ----------------------------------------------------------------
 
426
 
 
427
#if (MINIMIZE_TX_BUFFERING)
 
428
 
 
429
int 
 
430
fusb_ephandle_linux::write(const void *buffer, int nbytes)
 
431
{
 
432
  if (!d_started)
 
433
    return -1;
 
434
  
 
435
  if (d_input_p)
 
436
    return -1;
 
437
 
 
438
  assert(nbytes % 512 == 0);
 
439
 
 
440
  unsigned char *src = (unsigned char *) buffer;
 
441
 
 
442
  int n = 0;
 
443
  while (n < nbytes){
 
444
 
 
445
    usbdevfs_urb *urb = get_write_work_in_progress();
 
446
    if (!urb)
 
447
      return -1;
 
448
    assert(urb->actual_length == 0);
 
449
    int m = std::min(nbytes - n, MAX_BLOCK_SIZE);
 
450
    urb->buffer = src;
 
451
    urb->buffer_length = m;
 
452
 
 
453
    n += m;
 
454
    src += m;
 
455
 
 
456
    if (!submit_urb(urb))
 
457
      return -1;
 
458
 
 
459
    d_write_work_in_progress = 0;
 
460
  }
 
461
 
 
462
  return n;
 
463
}
 
464
 
 
465
#else
 
466
 
 
467
int 
 
468
fusb_ephandle_linux::write (const void *buffer, int nbytes)
 
469
{
 
470
  if (!d_started)
 
471
    return -1;
 
472
  
 
473
  if (d_input_p)
 
474
    return -1;
 
475
 
 
476
  unsigned char *src = (unsigned char *) buffer;
 
477
 
 
478
  int n = 0;
 
479
  while (n < nbytes){
 
480
 
 
481
    usbdevfs_urb *urb = get_write_work_in_progress ();
 
482
    if (!urb)
 
483
      return -1;
 
484
    unsigned char *dst = (unsigned char *) urb->buffer;
 
485
    int m = std::min (nbytes - n, urb->buffer_length - urb->actual_length);
 
486
 
 
487
    memcpy (&dst[urb->actual_length], &src[n], m);
 
488
    urb->actual_length += m;
 
489
    n += m;
 
490
 
 
491
    if (urb->actual_length == urb->buffer_length){
 
492
      if (!submit_urb (urb))
 
493
        return -1;
 
494
      d_write_work_in_progress = 0;
 
495
    }
 
496
  }
 
497
 
 
498
  return n;
 
499
}
 
500
 
 
501
#endif
 
502
 
 
503
usbdevfs_urb *
 
504
fusb_ephandle_linux::get_write_work_in_progress ()
 
505
{
 
506
  // if we've already got some work in progress, return it
 
507
 
 
508
  if (d_write_work_in_progress)
 
509
    return d_write_work_in_progress;
 
510
 
 
511
  while (1){
 
512
 
 
513
    reap_complete_writes ();
 
514
 
 
515
    usbdevfs_urb *urb = free_list_get ();
 
516
 
 
517
    if (urb != 0){
 
518
      assert (urb->actual_length == 0);
 
519
      d_write_work_in_progress = urb;
 
520
      return urb;
 
521
    }
 
522
 
 
523
    // The free list is empty.  Tell the device handle to reap.
 
524
    // Anything it reaps for us will end up on our completed list.
 
525
 
 
526
    if (!d_devhandle->_reap (true))
 
527
      return 0;
 
528
  }
 
529
}
 
530
 
 
531
void
 
532
fusb_ephandle_linux::reap_complete_writes ()
 
533
{
 
534
  // take a look at the completed_list and xfer to free list after
 
535
  // checking for errors.
 
536
 
 
537
  usbdevfs_urb *urb;
 
538
  
 
539
  while ((urb = completed_list_get ()) != 0){
 
540
 
 
541
    // Check for any errors or short writes that were reported in the urb.
 
542
    // The kernel sets status, actual_length and error_count.
 
543
    // error_count is only used for ISO xfers.
 
544
    // status is 0 if successful, else is an errno kind of thing
 
545
 
 
546
    if (urb->status != 0){
 
547
      fprintf (stderr, "fusb: (status %d) %s\n", urb->status, strerror (-urb->status));
 
548
    }
 
549
    else if (urb->actual_length != urb->buffer_length){
 
550
      fprintf (stderr, "fusb: short write xfer: %d != %d\n",
 
551
               urb->actual_length, urb->buffer_length);
 
552
    }
 
553
 
 
554
    free_list_add (urb);
 
555
  }
 
556
}
 
557
 
 
558
void
 
559
fusb_ephandle_linux::wait_for_completion ()
 
560
{
 
561
  d_devhandle->_wait_for_completion ();
 
562
}
 
563
 
 
564
// ----------------------------------------------------------------
 
565
//                     routines for reading
 
566
// ----------------------------------------------------------------
 
567
 
 
568
int
 
569
fusb_ephandle_linux::read (void *buffer, int nbytes)
 
570
{
 
571
  if (!d_started)
 
572
    return -1;
 
573
  
 
574
  if (!d_input_p)
 
575
    return -1;
 
576
 
 
577
  unsigned char *dst = (unsigned char *) buffer;
 
578
 
 
579
  int n = 0;
 
580
  while (n < nbytes){
 
581
 
 
582
    if (d_read_buffer >= d_read_buffer_end)
 
583
      if (!reload_read_buffer ())
 
584
        return -1;
 
585
 
 
586
    int m = std::min (nbytes - n, (int) (d_read_buffer_end - d_read_buffer));
 
587
 
 
588
    memcpy (&dst[n], d_read_buffer, m);
 
589
    d_read_buffer += m;
 
590
    n += m;
 
591
  }
 
592
 
 
593
  return n;
 
594
}
 
595
 
 
596
bool
 
597
fusb_ephandle_linux::reload_read_buffer ()
 
598
{
 
599
  assert (d_read_buffer >= d_read_buffer_end);
 
600
 
 
601
  usbdevfs_urb *urb;
 
602
 
 
603
  if (d_read_work_in_progress){
 
604
    // We're done with this urb.  Fire off a read to refill it.
 
605
    urb = d_read_work_in_progress;
 
606
    d_read_work_in_progress = 0;
 
607
    d_read_buffer = 0;
 
608
    d_read_buffer_end = 0;
 
609
    urb->actual_length = 0;
 
610
    if (!submit_urb (urb))
 
611
      return false;
 
612
  }
 
613
 
 
614
  while (1){
 
615
 
 
616
    while ((urb = completed_list_get ()) == 0)
 
617
      if (!d_devhandle->_reap (true))
 
618
        return false;
 
619
 
 
620
    // check result of completed read
 
621
 
 
622
    if (urb->status != 0){
 
623
      // We've got a problem. Report it and fail.
 
624
      fprintf (stderr, "fusb: (rd status %d) %s\n", urb->status, strerror (-urb->status));
 
625
      urb->actual_length = 0;
 
626
      free_list_add (urb);
 
627
      return false;
 
628
    }
 
629
 
 
630
    // we've got a happy urb, full of data...
 
631
 
 
632
    d_read_work_in_progress = urb;
 
633
    d_read_buffer = (unsigned char *) urb->buffer;
 
634
    d_read_buffer_end = d_read_buffer + urb->actual_length;
 
635
 
 
636
    return true;
 
637
  }
 
638
}
 
639
 
 
640
// ----------------------------------------------------------------
 
641
 
 
642
void
 
643
fusb_ephandle_linux::free_list_add (usbdevfs_urb *urb)
 
644
{
 
645
  assert (urb_get_ephandle (urb) == this);
 
646
  urb->actual_length = 0;
 
647
  d_free_list.push_back (urb);
 
648
}
 
649
 
 
650
usbdevfs_urb *
 
651
fusb_ephandle_linux::free_list_get ()
 
652
{
 
653
  if (d_free_list.empty ())
 
654
    return 0;
 
655
 
 
656
  usbdevfs_urb *urb = d_free_list.front ();
 
657
  d_free_list.pop_front ();
 
658
  return urb;
 
659
}
 
660
 
 
661
void
 
662
fusb_ephandle_linux::completed_list_add (usbdevfs_urb *urb)
 
663
{
 
664
  assert (urb_get_ephandle (urb) == this);
 
665
  d_completed_list.push_back (urb);
 
666
}
 
667
 
 
668
usbdevfs_urb *
 
669
fusb_ephandle_linux::completed_list_get ()
 
670
{
 
671
  if (d_completed_list.empty ())
 
672
    return 0;
 
673
 
 
674
  usbdevfs_urb *urb = d_completed_list.front ();
 
675
  d_completed_list.pop_front ();
 
676
  return urb;
 
677
}
 
678
 
 
679
/*
 
680
 * Submit the urb.  If successful the urb ends up on the devhandle's
 
681
 * pending list, otherwise, it's back on our free list.
 
682
 */
 
683
bool
 
684
fusb_ephandle_linux::submit_urb (usbdevfs_urb *urb)
 
685
{
 
686
  if (!d_devhandle->_submit_urb (urb)){    // FIXME record the problem somewhere
 
687
    fprintf (stderr, "_submit_urb failed\n");
 
688
    free_list_add (urb);
 
689
    return false;
 
690
  }
 
691
  return true;
 
692
}