?? fusb_linux.cpp
字號:
delete [] d_write_buffer; if (d_read_work_in_progress) free_urb (d_read_work_in_progress); } // ---------------------------------------------------------------- bool fusb_ephandle_linux::start () { if (d_started) return true; // already running d_started = true; if (d_input_p){ // fire off all the reads usbdevfs_urb *urb; int nerrors = 0; while ((urb = free_list_get ()) != 0 && nerrors < d_nblocks){ if (!submit_urb (urb)) nerrors++; } } return true; } // // kill all i/o in progress. // kill any completed but unprocessed transactions. // bool fusb_ephandle_linux::stop () { if (!d_started) return true; if (d_write_work_in_progress){ free_list_add (d_write_work_in_progress); d_write_work_in_progress = 0; } if (d_read_work_in_progress){ free_list_add (d_read_work_in_progress); d_read_work_in_progress = 0; d_read_buffer = 0; d_read_buffer_end = 0; } d_devhandle->_cancel_pending_rqsts (this); d_devhandle->_reap (false); while (1){ usbdevfs_urb *urb; while ((urb = completed_list_get ()) != 0) free_list_add (urb); if (d_free_list.size () == (unsigned) d_nblocks) break; if (!d_devhandle->_reap(true)) break; } d_started = false; return true; } // ---------------------------------------------------------------- // routines for writing // ---------------------------------------------------------------- #if (MINIMIZE_TX_BUFFERING) int fusb_ephandle_linux::write(const void *buffer, int nbytes) { if (!d_started) return -1; if (d_input_p) return -1; assert(nbytes % 512 == 0); unsigned char *src = (unsigned char *) buffer; int n = 0; while (n < nbytes){ usbdevfs_urb *urb = get_write_work_in_progress(); if (!urb) return -1; assert(urb->actual_length == 0); int m = std::min(nbytes - n, MAX_BLOCK_SIZE); urb->buffer = src; urb->buffer_length = m; n += m; src += m; if (!submit_urb(urb)) return -1; d_write_work_in_progress = 0; } return n; } #else int fusb_ephandle_linux::write (const void *buffer, int nbytes) { if (!d_started) return -1; if (d_input_p) return -1; unsigned char *src = (unsigned char *) buffer; int n = 0; while (n < nbytes){ usbdevfs_urb *urb = get_write_work_in_progress (); if (!urb) return -1; unsigned char *dst = (unsigned char *) urb->buffer; int m = std::min (nbytes - n, urb->buffer_length - urb->actual_length); memcpy (&dst[urb->actual_length], &src[n], m); urb->actual_length += m; n += m; if (urb->actual_length == urb->buffer_length){ if (!submit_urb (urb)) return -1; d_write_work_in_progress = 0; } } return n; } #endif usbdevfs_urb * fusb_ephandle_linux::get_write_work_in_progress () { // if we've already got some work in progress, return it if (d_write_work_in_progress) return d_write_work_in_progress; while (1){ reap_complete_writes (); usbdevfs_urb *urb = free_list_get (); if (urb != 0){ assert (urb->actual_length == 0); d_write_work_in_progress = urb; return urb; } // The free list is empty. Tell the device handle to reap. // Anything it reaps for us will end up on our completed list. if (!d_devhandle->_reap (true)) return 0; } } void fusb_ephandle_linux::reap_complete_writes () { // take a look at the completed_list and xfer to free list after // checking for errors. usbdevfs_urb *urb; while ((urb = completed_list_get ()) != 0){ // Check for any errors or short writes that were reported in the urb. // The kernel sets status, actual_length and error_count. // error_count is only used for ISO xfers. // status is 0 if successful, else is an errno kind of thing if (urb->status != 0){ fprintf (stderr, "fusb: (status %d) %s\n", urb->status, strerror (-urb->status)); } else if (urb->actual_length != urb->buffer_length){ fprintf (stderr, "fusb: short write xfer: %d != %d\n", urb->actual_length, urb->buffer_length); } free_list_add (urb); } } void fusb_ephandle_linux::wait_for_completion () { d_devhandle->_wait_for_completion (); } // ---------------------------------------------------------------- // routines for reading // ---------------------------------------------------------------- int fusb_ephandle_linux::read (void *buffer, int nbytes) { if (!d_started) return -1; if (!d_input_p) return -1; unsigned char *dst = (unsigned char *) buffer; int n = 0; while (n < nbytes){ if (d_read_buffer >= d_read_buffer_end) if (!reload_read_buffer ()) return -1; int m = std::min (nbytes - n, (int) (d_read_buffer_end - d_read_buffer)); memcpy (&dst[n], d_read_buffer, m); d_read_buffer += m; n += m; } return n; } bool fusb_ephandle_linux::reload_read_buffer () { assert (d_read_buffer >= d_read_buffer_end); usbdevfs_urb *urb; if (d_read_work_in_progress){ // We're done with this urb. Fire off a read to refill it. urb = d_read_work_in_progress; d_read_work_in_progress = 0; d_read_buffer = 0; d_read_buffer_end = 0; urb->actual_length = 0; if (!submit_urb (urb)) return false; } while (1){ while ((urb = completed_list_get ()) == 0) if (!d_devhandle->_reap (true)) return false; // check result of completed read if (urb->status != 0){ // We've got a problem. Report it and fail. fprintf (stderr, "fusb: (rd status %d) %s\n", urb->status, strerror (-urb->status)); urb->actual_length = 0; free_list_add (urb); return false; } // we've got a happy urb, full of data... d_read_work_in_progress = urb; d_read_buffer = (unsigned char *) urb->buffer; d_read_buffer_end = d_read_buffer + urb->actual_length; return true; } } // ---------------------------------------------------------------- void fusb_ephandle_linux::free_list_add (usbdevfs_urb *urb) { assert (urb_get_ephandle (urb) == this); urb->actual_length = 0; d_free_list.push_back (urb); } usbdevfs_urb * fusb_ephandle_linux::free_list_get () { if (d_free_list.empty ()) return 0; usbdevfs_urb *urb = d_free_list.front (); d_free_list.pop_front (); return urb; } void fusb_ephandle_linux::completed_list_add (usbdevfs_urb *urb) { assert (urb_get_ephandle (urb) == this); d_completed_list.push_back (urb); } usbdevfs_urb * fusb_ephandle_linux::completed_list_get () { if (d_completed_list.empty ()) return 0; usbdevfs_urb *urb = d_completed_list.front (); d_completed_list.pop_front (); return urb; } /* * Submit the urb. If successful the urb ends up on the devhandle's * pending list, otherwise, it's back on our free list. */ bool fusb_ephandle_linux::submit_urb (usbdevfs_urb *urb) { if (!d_devhandle->_submit_urb (urb)){// FIXME record the problem somewhere fprintf (stderr, "_submit_urb failed\n"); free_list_add (urb); return false; } return true; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -