Fail operations if Close was called before.
This commit is contained in:
@@ -69,6 +69,7 @@ func (c *Config) Close() error {
|
|||||||
c.dev.mu.Lock()
|
c.dev.mu.Lock()
|
||||||
defer c.dev.mu.Unlock()
|
defer c.dev.mu.Unlock()
|
||||||
c.dev.claimed = nil
|
c.dev.claimed = nil
|
||||||
|
c.dev = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,11 +79,17 @@ func (c *Config) String() string {
|
|||||||
|
|
||||||
// Control sends a control request to the device.
|
// Control sends a control request to the device.
|
||||||
func (c *Config) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
|
func (c *Config) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
|
||||||
|
if c.dev == nil {
|
||||||
|
return 0, fmt.Errorf("Control() called on %s after Close", c)
|
||||||
|
}
|
||||||
return libusb.control(c.dev.handle, c.ControlTimeout, rType, request, val, idx, data)
|
return libusb.control(c.dev.handle, c.ControlTimeout, rType, request, val, idx, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interface claims and returns an interface on a USB device.
|
// Interface claims and returns an interface on a USB device.
|
||||||
func (c *Config) Interface(intf, alt int) (*Interface, error) {
|
func (c *Config) Interface(intf, alt int) (*Interface, error) {
|
||||||
|
if c.dev == nil {
|
||||||
|
return nil, fmt.Errorf("Interface(%d, %d) called on %s after Close", intf, alt, c)
|
||||||
|
}
|
||||||
if intf < 0 || intf >= len(c.Info.Interfaces) {
|
if intf < 0 || intf >= len(c.Info.Interfaces) {
|
||||||
return nil, fmt.Errorf("interface %d not found in %s. Interface number needs to be a 0-based index into the interface table, which has %d elements.", intf, c, len(c.Info.Interfaces))
|
return nil, fmt.Errorf("interface %d not found in %s. Interface number needs to be a 0-based index into the interface table, which has %d elements.", intf, c, len(c.Info.Interfaces))
|
||||||
}
|
}
|
||||||
|
@@ -34,10 +34,13 @@ type Device struct {
|
|||||||
|
|
||||||
// Reset performs a USB port reset to reinitialize a device.
|
// Reset performs a USB port reset to reinitialize a device.
|
||||||
func (d *Device) Reset() error {
|
func (d *Device) Reset() error {
|
||||||
|
if d.handle == nil {
|
||||||
|
return fmt.Errorf("Reset() called on %s after Close", d)
|
||||||
|
}
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
if d.claimed != nil {
|
if d.claimed != nil {
|
||||||
return fmt.Errorf("can't reset a device with an open configuration")
|
return fmt.Errorf("can't reset device %s while it has an active configuration %s", d, d.claimed)
|
||||||
}
|
}
|
||||||
return libusb.reset(d.handle)
|
return libusb.reset(d.handle)
|
||||||
}
|
}
|
||||||
@@ -45,6 +48,9 @@ func (d *Device) Reset() error {
|
|||||||
// ActiveConfig returns the config id (not the index) of the active configuration.
|
// ActiveConfig returns the config id (not the index) of the active configuration.
|
||||||
// This corresponds to the ConfigInfo.Config field.
|
// This corresponds to the ConfigInfo.Config field.
|
||||||
func (d *Device) ActiveConfig() (int, error) {
|
func (d *Device) ActiveConfig() (int, error) {
|
||||||
|
if d.handle == nil {
|
||||||
|
return 0, fmt.Errorf("ActiveConfig() called on %s after Close", d)
|
||||||
|
}
|
||||||
ret, err := libusb.getConfig(d.handle)
|
ret, err := libusb.getConfig(d.handle)
|
||||||
return int(ret), err
|
return int(ret), err
|
||||||
}
|
}
|
||||||
@@ -55,6 +61,9 @@ func (d *Device) ActiveConfig() (int, error) {
|
|||||||
// USB supports only one active config per device at a time. Config claims the
|
// USB supports only one active config per device at a time. Config claims the
|
||||||
// device before setting the desired config and keeps it locked until Close is called.
|
// device before setting the desired config and keeps it locked until Close is called.
|
||||||
func (d *Device) Config(cfgNum int) (*Config, error) {
|
func (d *Device) Config(cfgNum int) (*Config, error) {
|
||||||
|
if d.handle == nil {
|
||||||
|
return nil, fmt.Errorf("Config(%d) called on %s after Close", cfgNum, d)
|
||||||
|
}
|
||||||
cfg := &Config{
|
cfg := &Config{
|
||||||
dev: d,
|
dev: d,
|
||||||
claimed: make(map[int]bool),
|
claimed: make(map[int]bool),
|
||||||
@@ -82,7 +91,7 @@ func (d *Device) Config(cfgNum int) (*Config, error) {
|
|||||||
// Close closes the device.
|
// Close closes the device.
|
||||||
func (d *Device) Close() error {
|
func (d *Device) Close() error {
|
||||||
if d.handle == nil {
|
if d.handle == nil {
|
||||||
return fmt.Errorf("double close on device %s", d)
|
return nil
|
||||||
}
|
}
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
@@ -99,6 +108,9 @@ func (d *Device) Close() error {
|
|||||||
// descriptor string is converted to ASCII (non-ASCII characters are replaced
|
// descriptor string is converted to ASCII (non-ASCII characters are replaced
|
||||||
// with "?").
|
// with "?").
|
||||||
func (d *Device) GetStringDescriptor(descIndex int) (string, error) {
|
func (d *Device) GetStringDescriptor(descIndex int) (string, error) {
|
||||||
|
if d.handle == nil {
|
||||||
|
return "", fmt.Errorf("GetStringDescriptor(%d) called on %s after Close", descIndex, d)
|
||||||
|
}
|
||||||
return libusb.getStringDesc(d.handle, descIndex)
|
return libusb.getStringDesc(d.handle, descIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +119,9 @@ func (d *Device) GetStringDescriptor(descIndex int) (string, error) {
|
|||||||
// on the interface and reattach it when releasing the interface.
|
// on the interface and reattach it when releasing the interface.
|
||||||
// Automatic kernel driver detachment is disabled on newly opened device handles by default.
|
// Automatic kernel driver detachment is disabled on newly opened device handles by default.
|
||||||
func (d *Device) SetAutoDetach(autodetach bool) error {
|
func (d *Device) SetAutoDetach(autodetach bool) error {
|
||||||
|
if d.handle == nil {
|
||||||
|
return fmt.Errorf("SetAutoDetach(%v) called on %s after Close", autodetach, d)
|
||||||
|
}
|
||||||
var autodetachInt int
|
var autodetachInt int
|
||||||
switch autodetach {
|
switch autodetach {
|
||||||
case true:
|
case true:
|
||||||
|
@@ -50,4 +50,12 @@ func TestOpenEndpoint(t *testing.T) {
|
|||||||
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("InEndpoint(cfg=1, if=1, alt=1, ep=6IN): got %+v, want %+v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := cfg.Close(); err == nil {
|
||||||
|
t.Fatalf("cfg.Close(): returned nil, want non nil, because the Interface was not release.")
|
||||||
|
}
|
||||||
|
if err := dev.Close(); err == nil {
|
||||||
|
t.Fatalf("dev.Close(): returned nil, want non nil, because the Config was not released.")
|
||||||
|
}
|
||||||
|
intf.Close()
|
||||||
}
|
}
|
||||||
|
@@ -71,10 +71,14 @@ func (i *Interface) String() string {
|
|||||||
|
|
||||||
// Close releases the interface.
|
// Close releases the interface.
|
||||||
func (i *Interface) Close() {
|
func (i *Interface) Close() {
|
||||||
|
if i.config == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
libusb.release(i.config.dev.handle, uint8(i.Setting.Number))
|
libusb.release(i.config.dev.handle, uint8(i.Setting.Number))
|
||||||
i.config.mu.Lock()
|
i.config.mu.Lock()
|
||||||
defer i.config.mu.Unlock()
|
defer i.config.mu.Unlock()
|
||||||
delete(i.config.claimed, i.Setting.Number)
|
delete(i.config.claimed, i.Setting.Number)
|
||||||
|
i.config = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Interface) openEndpoint(epNum int) (*endpoint, error) {
|
func (i *Interface) openEndpoint(epNum int) (*endpoint, error) {
|
||||||
@@ -100,6 +104,9 @@ func (i *Interface) openEndpoint(epNum int) (*endpoint, error) {
|
|||||||
|
|
||||||
// InEndpoint prepares an IN endpoint for transfer.
|
// InEndpoint prepares an IN endpoint for transfer.
|
||||||
func (i *Interface) InEndpoint(epNum int) (*InEndpoint, error) {
|
func (i *Interface) InEndpoint(epNum int) (*InEndpoint, error) {
|
||||||
|
if i.config == nil {
|
||||||
|
return nil, fmt.Errorf("InEndpoint(%d) called on %s after Close", epNum, i)
|
||||||
|
}
|
||||||
ep, err := i.openEndpoint(epNum)
|
ep, err := i.openEndpoint(epNum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -114,6 +121,9 @@ func (i *Interface) InEndpoint(epNum int) (*InEndpoint, error) {
|
|||||||
|
|
||||||
// OutEndpoint prepares an OUT endpoint for transfer.
|
// OutEndpoint prepares an OUT endpoint for transfer.
|
||||||
func (i *Interface) OutEndpoint(epNum int) (*OutEndpoint, error) {
|
func (i *Interface) OutEndpoint(epNum int) (*OutEndpoint, error) {
|
||||||
|
if i.config == nil {
|
||||||
|
return nil, fmt.Errorf("OutEndpoint(%d) called on %s after Close", epNum, i)
|
||||||
|
}
|
||||||
ep, err := i.openEndpoint(epNum)
|
ep, err := i.openEndpoint(epNum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Reference in New Issue
Block a user