google / gousb

gousb provides low-level interface for accessing USB devices
Apache License 2.0
838 stars 124 forks source link

Cannot claim interface even when there are no other apps are using the device #123

Open c0debreaker opened 6 months ago

c0debreaker commented 6 months ago

Here is the full error message

Couldn't claim default interface: failed to select interface #0 alternate setting 0 of config 1 of device vid=2ca3,pid=001f,bus=2,addr=26: failed to claim interface 0 on vid=2ca3,pid=001f,bus=2,addr=26,config=1: libusb: device or resource busy [code -6]
exit status 1

However, if I execute either my Python or NodeJS code, I am able to read from the USB device on this same linux machine.

Here's my full code

package main

import (
    "encoding/hex"
    "flag"
    "fmt"
    "os"

    "github.com/google/gousb"
)

var (
    file        = flag.String("file", "", "output video feed to file")
    stdout      = flag.Bool("stdout", false, "send video feed to stdout for playback. eg: node index.js -o | ffplay -")
    readSize    = flag.Int("readsize", 512, "size in bytes to queue for usb bulk interface reads")
    queueSize   = flag.Int("queuesize", 3, "number of polling usb bulk read requests to keep in flight")
    verbose     = flag.Bool("verbose", false, "be noisy - doesn not play well with -o")
    deviceFound = false
)

func main() {
    flag.Parse()

    ctx := gousb.NewContext()
    defer ctx.Close()

    ctx.Debug(4)

    dev, err := ctx.OpenDeviceWithVIDPID(gousb.ID(0x2ca3), gousb.ID(0x1f))
    if err != nil {
        fmt.Fprintln(os.Stderr, "USB device not found. Please connect your device and restart the script.")
        os.Exit(1)
    }
    // dev[0].SetAutoDetach(true)
    defer dev.Close()

    iface, _, err := dev.DefaultInterface()
    if err != nil {
        fmt.Fprintf(os.Stderr, "Couldn't claim default interface: %v\n", err)
        os.Exit(1)
    }

    inpoint, err := iface.InEndpoint(1)
    if err != nil {
        fmt.Fprintln(os.Stderr, "Couldn't claim bulk interface")
        os.Exit(1)
    }

    outpoint, err := iface.OutEndpoint(0)
    if err != nil {
        fmt.Fprintln(os.Stderr, "Couldn't claim bulk interface")
        os.Exit(1)
    }

    magic, _ := hex.DecodeString("524d5654")

    _, err = outpoint.Write(magic)
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error writing magic bytes:", err)
    }

    for {
        data := make([]byte, *readSize)
        _, err := inpoint.Read(data)
        if err != nil {
            fmt.Fprintln(os.Stderr, "Error reading data:", err)
            continue
        }

        if *stdout {
            os.Stdout.Write(data)
        }

        if *verbose {
            fmt.Println("received", len(data), "bytes")
        }

        if *file != "" {
            f, err := os.OpenFile(*file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
            if err != nil {
                fmt.Fprintln(os.Stderr, "Error opening file:", err)
                os.Exit(1)
            }
            defer f.Close()

            _, err = f.Write(data)
            if err != nil {
                fmt.Fprintln(os.Stderr, "Error writing to file:", err)
            }
        }
    }
}

And here the verbose log after running go run main.go

[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.022689] [001f227f] libusb: debug [libusb_get_device_list]  
[ 0.022757] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.022754] [001f2283] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[ 0.022809] [001f2283] libusb: debug [handle_events] event sources modified, reallocating event data
[ 0.022828] [001f2283] libusb: debug [usbi_wait_for_events] poll() 2 fds with timeout in 100ms
[ 0.022791] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.022910] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.022928] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.022939] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.022962] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.022984] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.022995] [001f227f] libusb: debug [parse_configuration] skipping descriptor 0xb
[ 0.023005] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0xb
[ 0.023073] [001f227f] libusb: debug [libusb_open] open 2.26
[ 0.023111] [001f227f] libusb: debug [usbi_add_event_source] add fd 7 events 4
[ 0.023120] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023127] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023156] [001f2283] libusb: debug [usbi_wait_for_events] poll() returned 1
[ 0.023164] [001f2283] libusb: debug [handle_event_trigger] event triggered
[ 0.023168] [001f2283] libusb: debug [handle_event_trigger] someone updated the event sources
[ 0.023178] [001f2283] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[ 0.023183] [001f227f] libusb: debug [parse_configuration] skipping descriptor 0xb
[ 0.023191] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023184] [001f2283] libusb: debug [handle_events] event sources modified, reallocating event data
[ 0.023198] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0xb
[ 0.023203] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023208] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023202] [001f2283] libusb: debug [usbi_wait_for_events] poll() 3 fds with timeout in 100ms
[ 0.023212] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023230] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023235] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023239] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023243] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023247] [001f227f] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.023283] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023291] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023303] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023312] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023322] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023328] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023340] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023346] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023352] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023358] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023364] [001f227f] libusb: debug [libusb_get_device_descriptor]  
[ 0.023369] [001f227f] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.023381] [001f227f] libusb: debug [libusb_get_configuration]  
[ 0.023412] [001f227f] libusb: debug [libusb_get_configuration] active config 1
[ 0.023420] [001f227f] libusb: debug [libusb_get_configuration]  
[ 0.023439] [001f227f] libusb: debug [libusb_get_configuration] active config 1
[ 0.023447] [001f227f] libusb: debug [libusb_claim_interface] interface 0
Couldn't claim default interface: failed to select interface #0 alternate setting 0 of config 1 of device vid=2ca3,pid=001f,bus=2,addr=26: failed to claim interface 0 on vid=2ca3,pid=001f,bus=2,addr=26,config=1: libusb: device or resource busy [code -6]
exit status 1
c0debreaker commented 6 months ago

Here is the output of lsusb -v. I only displayed the device I am debugging.

Bus 002 Device 026: ID 2ca3:001f DJI Technology Co., Ltd. pigeon
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.10
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x2ca3 DJI Technology Co., Ltd.
  idProduct          0x001f 
  bcdDevice            4.09
  iManufacturer           1 DJI
  iProduct                2 pigeon
  iSerial                 3 987654321ABCDEF
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x00bb
    bNumInterfaces          6
    bConfigurationValue     1
    iConfiguration          4 rndis,mass_storage,bulk,acm
    bmAttributes         0x80
      (Bus Powered)
    MaxPower                2mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass        224 Wireless
      bFunctionSubClass       1 Radio Frequency
      bFunctionProtocol       3 RNDIS
      iFunction               7 RNDIS
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass       224 Wireless
      bInterfaceSubClass      1 Radio Frequency
      bInterfaceProtocol      3 RNDIS
      iInterface              5 RNDIS Communications Control
      ** UNRECOGNIZED:  05 24 00 10 01
      ** UNRECOGNIZED:  05 24 01 00 01
      ** UNRECOGNIZED:  04 24 02 00
      ** UNRECOGNIZED:  05 24 06 00 01
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               9
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              6 RNDIS Ethernet Data
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         8 Mass Storage
      bInterfaceSubClass      6 SCSI
      bInterfaceProtocol     80 Bulk-Only
      iInterface              9 Mass Storage
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        3
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass     67 
      bInterfaceProtocol      1 
      iInterface             11 BULK Interface
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x03  EP 3 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         4
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       1 AT-commands (v.25ter)
      iFunction              14 CDC Serial
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        4
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface             12 CDC Abstract Control Model (ACM)
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x00
        bDataInterface          5
      CDC ACM:
        bmCapabilities       0x02
          line coding and serial state
      CDC Union:
        bMasterInterface        4
        bSlaveInterface         5 
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x86  EP 6 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x000a  1x 10 bytes
        bInterval               9
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        5
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface             13 CDC ACM Data
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x85  EP 5 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
Binary Object Store Descriptor:
  bLength                 5
  bDescriptorType        15
  wTotalLength       0x0016
  bNumDeviceCaps          2
  USB 2.0 Extension Device Capability:
    bLength                 7
    bDescriptorType        16
    bDevCapabilityType      2
    bmAttributes   0x00000006
      BESL Link Power Management (LPM) Supported
  SuperSpeed USB Device Capability:
    bLength                10
    bDescriptorType        16
    bDevCapabilityType      3
    bmAttributes         0x00
    wSpeedsSupported   0x000f
      Device can operate at Low Speed (1Mbps)
      Device can operate at Full Speed (12Mbps)
      Device can operate at High Speed (480Mbps)
      Device can operate at SuperSpeed (5Gbps)
    bFunctionalitySupport   1
      Lowest fully-functional device speed is Full Speed (12Mbps)
    bU1DevExitLat           1 micro seconds
    bU2DevExitLat         500 micro seconds
Device Status:     0x0001
  Self Powered
c0debreaker commented 6 months ago

Got that issue working now. However, I have a new issue, at InEndpoint and OutEndpoint methods. It's saying "cannot claim bulk interface".

The codes that are failing is

    inpoint, err := iface.InEndpoint(1)
    if err != nil {
        fmt.Fprintln(os.Stderr, "Couldn't claim bulk interface")
        os.Exit(1)
    }

    outpoint, err := iface.OutEndpoint(0)
    if err != nil {
        fmt.Fprintln(os.Stderr, "Couldn't claim bulk interface")
        os.Exit(1)
    }

From this example, https://github.com/google/gousb/blob/master/example_test.go#L117, is the value of 6 a random number?

epIn, err := intf.InEndpoint(6)
AtharvaKamble commented 5 months ago

@c0debreaker would appreciate a lot if you could point out how you got past the "cannot claim interface - resource busy" issue? I am running into it, but not sure why.

c0debreaker commented 4 months ago

@c0debreaker would appreciate a lot if you could point out how you got past the "cannot claim interface - resource busy" issue? I am running into it, but not sure why.

I'll have to look for the code. I haven't seen it for months. I believe I just commented out some lines. I will let you know once I find the code.

michealroberts commented 2 months ago

@c0debreaker I believe we need to amend these lines in config.go:

// Select an alternate setting if needed (device has multiple alternate settings).
if len(c.Desc.Interfaces[num-1].AltSettings) > 1 {
    if err := c.dev.ctx.libusb.setAlt(c.dev.handle, uint8(num), uint8(alt)); err != nil {
        c.dev.ctx.libusb.release(c.dev.handle, uint8(num))
        return nil, fmt.Errorf("failed to set alternate config %d on interface %d of %s: %v", alt, num, c, err)
    }
}

e.g., the c.Desc.Interfaces[num].AltSettings as it currently stands in not zero indexing ...

This fixed this issue for me locally ... I will PR shortly.

zagrodzki commented 2 months ago

@michealroberts I don't believe your proposed fix is related to this issue.