Check if the device is already closed and if the interface is already
claimed.
This commit is contained in:
@@ -57,6 +57,9 @@ type Config struct {
|
|||||||
|
|
||||||
// Close releases the underlying device, allowing the caller to switch the device to a different configuration.
|
// Close releases the underlying device, allowing the caller to switch the device to a different configuration.
|
||||||
func (c *Config) Close() error {
|
func (c *Config) Close() error {
|
||||||
|
if c.dev == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
if len(c.claimed) > 0 {
|
if len(c.claimed) > 0 {
|
||||||
@@ -98,6 +101,12 @@ func (c *Config) Interface(intf, alt int) (*Interface, error) {
|
|||||||
return nil, fmt.Errorf("Inteface %d does not have alternate setting %d. Alt setting needs to be a 0-based index into the settings table, which has %d elements.", ifInfo, alt, len(ifInfo.AltSettings))
|
return nil, fmt.Errorf("Inteface %d does not have alternate setting %d. Alt setting needs to be a 0-based index into the settings table, which has %d elements.", ifInfo, alt, len(ifInfo.AltSettings))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if c.claimed[intf] {
|
||||||
|
return nil, fmt.Errorf("interface %d on %s is already claimed", intf, c)
|
||||||
|
}
|
||||||
|
|
||||||
// Claim the interface
|
// Claim the interface
|
||||||
if err := libusb.claim(c.dev.handle, uint8(intf)); err != nil {
|
if err := libusb.claim(c.dev.handle, uint8(intf)); err != nil {
|
||||||
return nil, fmt.Errorf("failed to claim interface %d on %s: %v", intf, c, err)
|
return nil, fmt.Errorf("failed to claim interface %d on %s: %v", intf, c, err)
|
||||||
@@ -108,8 +117,6 @@ func (c *Config) Interface(intf, alt int) (*Interface, error) {
|
|||||||
return nil, fmt.Errorf("failed to set alternate config %d on interface %d of %s: %v", alt, intf, c, err)
|
return nil, fmt.Errorf("failed to set alternate config %d on interface %d of %s: %v", alt, intf, c, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mu.Lock()
|
|
||||||
defer c.mu.Unlock()
|
|
||||||
c.claimed[intf] = true
|
c.claimed[intf] = true
|
||||||
return &Interface{
|
return &Interface{
|
||||||
Setting: ifInfo.AltSettings[alt],
|
Setting: ifInfo.AltSettings[alt],
|
||||||
|
@@ -35,27 +35,57 @@ func TestOpenEndpoint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
cfg, err := dev.Config(1)
|
cfg, err := dev.Config(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s Config(1): %v", dev, err)
|
t.Fatalf("%s.Config(1): %v", dev, err)
|
||||||
}
|
}
|
||||||
defer cfg.Close()
|
defer cfg.Close()
|
||||||
intf, err := cfg.Interface(1, 1)
|
intf, err := cfg.Interface(1, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s Interface(1, 1): %v", cfg, err)
|
t.Fatalf("%s.Interface(1, 1): %v", cfg, err)
|
||||||
}
|
}
|
||||||
defer intf.Close()
|
defer intf.Close()
|
||||||
got, err := intf.InEndpoint(6)
|
got, err := intf.InEndpoint(6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("InEndpoint(cfg=1, if=1, alt=1, ep=6IN): got error %v, want nil", err)
|
t.Fatalf("%s.InEndpoint(6): got error %v, want nil", intf, err)
|
||||||
}
|
}
|
||||||
if want := fakeDevices[1].Configs[0].Interfaces[1].AltSettings[1].Endpoints[1]; !reflect.DeepEqual(got.Info, want) {
|
if want := fakeDevices[1].Configs[0].Interfaces[1].AltSettings[1].Endpoints[1]; !reflect.DeepEqual(got.Info, want) {
|
||||||
t.Errorf("InEndpoint(cfg=1, if=1, alt=1, ep=6IN): got %+v, want %+v", got, want)
|
t.Errorf("%s.InEndpoint(6): got %+v, want %+v", intf, got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := cfg.Interface(1, 0); err == nil {
|
||||||
|
t.Fatalf("%s.Interface(1, 0): got nil, want non nil, because Interface 1 is already claimed.", cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// intf2 is interface #0, not claimed yet.
|
||||||
|
intf2, err := cfg.Interface(0, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s.Interface(0, 0): got %v, want nil", cfg, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cfg.Close(); err == nil {
|
if err := cfg.Close(); err == nil {
|
||||||
t.Fatalf("cfg.Close(): returned nil, want non nil, because the Interface was not release.")
|
t.Fatalf("%s.Close(): got nil, want non nil, because the Interface was not released.", cfg)
|
||||||
}
|
}
|
||||||
if err := dev.Close(); err == nil {
|
if err := dev.Close(); err == nil {
|
||||||
t.Fatalf("dev.Close(): returned nil, want non nil, because the Config was not released.")
|
t.Fatalf("%s.Close(): got nil, want non nil, because the Config was not released.", cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
intf.Close()
|
intf.Close()
|
||||||
|
if err := cfg.Close(); err == nil {
|
||||||
|
t.Fatalf("%s.Close(): got nil, want non nil, because the Interface was not released.", cfg)
|
||||||
|
}
|
||||||
|
if err := dev.Close(); err == nil {
|
||||||
|
t.Fatalf("%s.Close(): got nil, want non nil, because the Config was not released.", dev)
|
||||||
|
}
|
||||||
|
|
||||||
|
intf2.Close()
|
||||||
|
if err := dev.Close(); err == nil {
|
||||||
|
t.Fatalf("%s.Close(): got nil, want non nil, because the Config was not released.", dev)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cfg.Close(); err != nil {
|
||||||
|
t.Fatalf("%s.Close(): got error %v, want nil", cfg, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dev.Close(); err != nil {
|
||||||
|
t.Fatalf("%s.Close(): got error %v, want nil", dev, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user