Config and interface description (#16)

* Add APIs for config and interface descriptors. Split out the common
parts of selecting a config descriptor from device desc and
selecting a setting descriptor from a config desc.

* Parallelize the few tests that actually can be parallelized safely.
Add comments where they can't. Note to self: it would be beneficial
to restructure the fakelibusb to index all properties of the lib
with the used context. That way a libusb implementation wouldn't need
to be referred via a shared variable.
This commit is contained in:
zagrodzki
2017-09-04 14:17:34 +02:00
committed by GitHub
parent cf19eb7001
commit f9aba6fab5
12 changed files with 175 additions and 53 deletions

View File

@@ -56,6 +56,23 @@ func (d *DeviceDesc) String() string {
return fmt.Sprintf("%d.%d: %s:%s (available configs: %v)", d.Bus, d.Address, d.Vendor, d.Product, d.sortedConfigIds())
}
func (d *DeviceDesc) sortedConfigIds() []int {
var cfgs []int
for c := range d.Configs {
cfgs = append(cfgs, c)
}
sort.Ints(cfgs)
return cfgs
}
func (d *DeviceDesc) cfgDesc(cfgNum int) (*ConfigDesc, error) {
desc, ok := d.Configs[cfgNum]
if !ok {
return nil, fmt.Errorf("configuration id %d not found in the descriptor of the device. Available config ids: %v", cfgNum, d.sortedConfigIds())
}
return &desc, nil
}
// Device represents an opened USB device.
// Device allows sending USB control commands through the Command() method.
// For data transfers select a device configuration through a call to
@@ -77,15 +94,6 @@ type Device struct {
autodetach bool
}
func (d *DeviceDesc) sortedConfigIds() []int {
var cfgs []int
for c := range d.Configs {
cfgs = append(cfgs, c)
}
sort.Ints(cfgs)
return cfgs
}
// String represents a human readable representation of the device.
func (d *Device) String() string {
return fmt.Sprintf("vid=%s,pid=%s,bus=%d,addr=%d", d.Desc.Vendor, d.Desc.Product, d.Desc.Bus, d.Desc.Address)
@@ -126,12 +134,12 @@ 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)
}
desc, ok := d.Desc.Configs[cfgNum]
if !ok {
return nil, fmt.Errorf("configuration id %d not found in the descriptor of the device %s. Available config ids: %v", cfgNum, d, d.Desc.sortedConfigIds())
desc, err := d.Desc.cfgDesc(cfgNum)
if err != nil {
return nil, fmt.Errorf("device %s: %v", d, err)
}
cfg := &Config{
Desc: desc,
Desc: *desc,
dev: d,
claimed: make(map[int]bool),
}
@@ -212,6 +220,10 @@ func (d *Device) GetStringDescriptor(descIndex int) (string, error) {
if d.handle == nil {
return "", fmt.Errorf("GetStringDescriptor(%d) called on %s after Close", descIndex, d)
}
// string descriptor index value of 0 indicates no string descriptor.
if descIndex == 0 {
return "", nil
}
return libusb.getStringDesc(d.handle, descIndex)
}
@@ -233,6 +245,31 @@ func (d *Device) SerialNumber() (string, error) {
return d.GetStringDescriptor(d.Desc.iSerialNumber)
}
// ConfigDescription returns the description of the selected device
// configuration. GetStringDescriptor's string conversion rules apply.
func (d *Device) ConfigDescription(cfg int) (string, error) {
c, err := d.Desc.cfgDesc(cfg)
if err != nil {
return "", fmt.Errorf("%s: %v", d, err)
}
return d.GetStringDescriptor(c.iConfiguration)
}
// InterfaceDescription returns the description of the selected interface and
// its alternate setting in a selected configuration. GetStringDescriptor's
// string conversion rules apply.
func (d *Device) InterfaceDescription(cfgNum, intfNum, altNum int) (string, error) {
cfg, err := d.Desc.cfgDesc(cfgNum)
if err != nil {
return "", fmt.Errorf("%s: %v", d, err)
}
alt, err := cfg.intfDesc(intfNum, altNum)
if err != nil {
return "", fmt.Errorf("%s, configuration %d: %v", d, cfgNum, err)
}
return d.GetStringDescriptor(alt.iInterface)
}
// SetAutoDetach enables/disables automatic kernel driver detachment.
// When autodetach is enabled gousb will automatically detach the kernel driver
// on the interface and reattach it when releasing the interface.