On Mon, Nov 30, 2020 at 09:32:37AM +0000, Mikolaj Kucharski wrote:
> Hi,
> 
> I have very unreliable results when I use my Canon MG3250 all-in-one
> printer, scanner for scanning.
> 
> Most of the scanning attempts with scanimage fail:
> 
>       scanimage: sane_read: Error during device I/O
> 
> I spent some time with it and from what I can see scanning fails when
> libusb_cancel_transfer() from libusb returns code -12. Here is example
> of failed scan:
> 
>   export LIBUSB_DEBUG=4
>   scanimage --device-name pixma:04A91762_860FE4 \
>       --format png --mode gray --resolution 300 \
>       --output-file scan.png
> 
> 
> [ 2.024756] [0008d272] libusb: debug [libusb_alloc_transfer] transfer 
> 0xbc317170e50
> [ 2.024768] [0008d272] libusb: debug [libusb_submit_transfer] transfer 
> 0xbc317170e50
> [ 2.024814] [0008d272] libusb: debug [obsd_submit_transfer] 
> [ 2.024887] [0008d272] libusb: debug [_access_endpoint] endpoint 9 mode 0
> [ 3.033570] [0008d272] libusb: debug [libusb_get_next_timeout] first timeout 
> already expired
> [ 3.033620] [0008d272] libusb: debug [libusb_cancel_transfer] transfer 
> 0xbc317170e50
> [ 3.033634] [0008d272] libusb: debug [obsd_cancel_transfer] 
> [ 3.033645] [0008d272] libusb: error [libusb_cancel_transfer] cancel transfer 
> failed error -12
> [ 3.033658] [0008d272] libusb: warning [handle_timeout] async cancel failed 
> -12 errno=6
> [ 3.033690] [0008d272] libusb: debug [libusb_get_next_timeout] no URB with 
> timeout or all handled by OS; no timeout!
> [ 3.033730] [0008d272] libusb: debug [libusb_handle_events_timeout_completed] 
> doing our own event handling
> [ 3.033799] [0008d272] libusb: debug [handle_events] poll() 1 fds with 
> timeout in 60000ms
> [ 3.033822] [0008d272] libusb: debug [handle_events] poll() returned 1
> [ 3.033858] [0008d272] libusb: debug [handle_events] caught a fish on the 
> event pipe
> [ 3.033872] [0008d272] libusb: debug [usbi_handle_transfer_completion] 
> transfer 0xbc317170e50 has callback 0xbc2c960d550
> [ 3.033899] [0008d272] libusb: debug [sync_transfer_cb] actual_length=0
> [ 3.033947] [0008d272] libusb: debug [libusb_free_transfer] transfer 
> 0xbc317170e50
> 
> 
> Here is the same command like above, but scanning succeeds:
> 
> [ 1.974116] [0003cf01] libusb: debug [libusb_alloc_transfer] transfer 
> 0x9aeef9a1550
> [ 1.974138] [0003cf01] libusb: debug [libusb_submit_transfer] transfer 
> 0x9aeef9a1550
> [ 1.974153] [0003cf01] libusb: debug [obsd_submit_transfer] 
> [ 1.974190] [0003cf01] libusb: debug [_access_endpoint] endpoint 9 mode 0
> [ 2.384033] [0003cf01] libusb: debug [libusb_get_next_timeout] next timeout 
> in 0.590119s
> [ 2.384079] [0003cf01] libusb: debug [libusb_handle_events_timeout_completed] 
> doing our own event handling
> [ 2.384111] [0003cf01] libusb: debug [handle_events] poll() 1 fds with 
> timeout in 591ms
> [ 2.384131] [0003cf01] libusb: debug [handle_events] poll() returned 1
> [ 2.384141] [0003cf01] libusb: debug [handle_events] caught a fish on the 
> event pipe
> [ 2.384152] [0003cf01] libusb: debug [usbi_handle_transfer_completion] 
> transfer 0x9aeef9a1550 has callback 0x9aec4f75550
> [ 2.384190] [0003cf01] libusb: debug [sync_transfer_cb] actual_length=32
> [ 2.384261] [0003cf01] libusb: debug [libusb_free_transfer] transfer 
> 0x9aeef9a1550
> 
> 
> In failed scenario, actual_length=0 which then SANE interpreters
> as SANE_STATUS_EOF (file sanei/sanei_usb.c, function
> sanei_usb_read_int(), condition read_size == 0).
> 
> In successful scenario, actual_length=32 and SANE moves along and
> scanning finishes successfully.
> 
> I'm kinda stuck here, as I'm not sure how to handle this. In practical
> terms, scanning is extremely unrelaible and code most of the time hits
> cancel transfer failed error -12 (LIBUSB_ERROR_NOT_SUPPORTED) condition.
> 
> Any tips how to tackle this?

Looking at the code for the libusb's openbsd backend, it's evident
that the code simply does not support transfer cancellation:

int
obsd_cancel_transfer(struct usbi_transfer *itransfer)
{
        usbi_dbg("");

        return (LIBUSB_ERROR_NOT_SUPPORTED);
}
(see /usr/ports/pobj/libusb1-1.0.23/libusb-1.0.23/libusb/os/openbsd_usb.c)

So you could either determine what's causing the transfer to be cancelled
and whether this condition could be fixed (wrong transfer timeout values?),
or implement cancellation of transfers in the above function so that libusb
may continue and perhaps retry the transfer.

Reply via email to