diff --git a/usb/constants.go b/usb/constants.go index e6227ec..c5f8486 100644 --- a/usb/constants.go +++ b/usb/constants.go @@ -218,4 +218,14 @@ func (s DeviceSpeed) String() string { return deviceSpeedDescription[s] } +const ( + // SelfPoweredMask is the bitmask for "self powered" field of configuration + // descriptor bmAttributes. + SelfPoweredMask = 0x40 + // RemoteWakeupMask is the bitmask for "supports remote wakeup" field of + // configuration descriptor bmAttributes. + RemoteWakeupMask = 0x20 +) + +// Milliamperes is a unit of electric current consumption. type Milliamperes uint diff --git a/usb/descriptor.go b/usb/descriptor.go index 76a9b77..796ae3d 100644 --- a/usb/descriptor.go +++ b/usb/descriptor.go @@ -29,8 +29,8 @@ type Descriptor struct { Product ID // The Product identifier // Protocol information - Class uint8 // The class of this device - SubClass uint8 // The sub-class (within the class) of this device + Class Class // The class of this device + SubClass Class // The sub-class (within the class) of this device Protocol uint8 // The protocol (within the sub-class) of this device // Configuration information diff --git a/usb/libusb.go b/usb/libusb.go index e1d81b9..4b7b13a 100644 --- a/usb/libusb.go +++ b/usb/libusb.go @@ -213,9 +213,11 @@ func (libusbImpl) getDeviceDesc(d *libusbDevice) (*Descriptor, error) { return nil, err } c := ConfigInfo{ - Config: uint8(cfg.bConfigurationValue), - Attributes: uint8(cfg.bmAttributes), - MaxPower: uint8(cfg.MaxPower), + Config: uint8(cfg.bConfigurationValue), + SelfPowered: (cfg.bmAttributes & SelfPoweredMask) != 0, + RemoteWakeup: (cfg.bmAttributes & RemoteWakeupMask) != 0, + // TODO(sebek): at GenX speeds MaxPower is expressed in units of 8mA, not 2mA. + MaxPower: 2 * Milliamperes(cfg.MaxPower), } var ifaces []C.struct_libusb_interface @@ -274,8 +276,8 @@ func (libusbImpl) getDeviceDesc(d *libusbDevice) (*Descriptor, error) { Device: BCD(desc.bcdDevice), Vendor: ID(desc.idVendor), Product: ID(desc.idProduct), - Class: uint8(desc.bDeviceClass), - SubClass: uint8(desc.bDeviceSubClass), + Class: Class(desc.bDeviceClass), + SubClass: Class(desc.bDeviceSubClass), Protocol: uint8(desc.bDeviceProtocol), Configs: cfgs, }, nil diff --git a/usbid/describe.go b/usbid/describe.go index 1746a26..1f6c850 100644 --- a/usbid/describe.go +++ b/usbid/describe.go @@ -56,12 +56,15 @@ func Describe(val interface{}) string { // - *usb.Descriptor "Class (SubClass) Protocol" // - usb.InterfaceSetup "IfClass (IfSubClass) IfProtocol" func Classify(val interface{}) string { - var class, sub, proto uint8 + var ( + class, sub usb.Class + proto uint8 + ) switch val := val.(type) { case *usb.Descriptor: class, sub, proto = val.Class, val.SubClass, val.Protocol case usb.InterfaceSetup: - class, sub, proto = val.IfClass, val.IfSubClass, val.IfProtocol + class, sub, proto = usb.Class(val.IfClass), usb.Class(val.IfSubClass), val.IfProtocol default: return fmt.Sprintf("Unknown (%T)", val) } diff --git a/usbid/load.go b/usbid/load.go index b8dd5d0..65dc8f9 100644 --- a/usbid/load.go +++ b/usbid/load.go @@ -34,7 +34,7 @@ var ( Vendors map[usb.ID]*Vendor // Classes stores the class, subclass and protocol mappings. - Classes map[uint8]*Class + Classes map[usb.Class]*Class ) // LoadFromURL replaces the built-in vendor and class mappings with ones loaded diff --git a/usbid/parse.go b/usbid/parse.go index 57571b8..e5a7b38 100644 --- a/usbid/parse.go +++ b/usbid/parse.go @@ -52,7 +52,7 @@ func (p Product) String() string { // A Class contains the name of the class and mappings for each subclass. type Class struct { Name string - SubClass map[uint8]*SubClass + SubClass map[usb.Class]*SubClass } // String returns the name of the class. @@ -75,9 +75,9 @@ func (s SubClass) String() string { // should not be necessary, as a set of mappings is already embedded in the library. // If a new or specialized file is obtained, this can be used to retrieve the mappings, // which can be stored in the global Vendors and Classes map. -func ParseIDs(r io.Reader) (map[usb.ID]*Vendor, map[uint8]*Class, error) { +func ParseIDs(r io.Reader) (map[usb.ID]*Vendor, map[usb.Class]*Class, error) { vendors := make(map[usb.ID]*Vendor, 2800) - classes := make(map[uint8]*Class) // TODO(kevlar): count + classes := make(map[usb.Class]*Class) // TODO(kevlar): count split := func(s string) (kind string, level int, id uint64, name string, err error) { pieces := strings.SplitN(s, " ", 2) @@ -159,15 +159,13 @@ func ParseIDs(r io.Reader) (map[usb.ID]*Vendor, map[uint8]*Class, error) { var class *Class var subclass *SubClass - parseClass := func(level int, raw uint64, name string) error { - id := uint8(raw) - + parseClass := func(level int, id uint64, name string) error { switch level { case 0: class = &Class{ Name: name, } - classes[id] = class + classes[usb.Class(id)] = class case 1: if class == nil { @@ -178,9 +176,9 @@ func ParseIDs(r io.Reader) (map[usb.ID]*Vendor, map[uint8]*Class, error) { Name: name, } if class.SubClass == nil { - class.SubClass = make(map[uint8]*SubClass) + class.SubClass = make(map[usb.Class]*SubClass) } - class.SubClass[id] = subclass + class.SubClass[usb.Class(id)] = subclass case 2: if subclass == nil { @@ -190,7 +188,7 @@ func ParseIDs(r io.Reader) (map[usb.ID]*Vendor, map[uint8]*Class, error) { if subclass.Protocol == nil { subclass.Protocol = make(map[uint8]string) } - subclass.Protocol[id] = name + subclass.Protocol[uint8(id)] = name default: return fmt.Errorf("too many levels of nesting for class") diff --git a/usbid/testdata_test.go b/usbid/testdata_test.go index 91c8941..7b6f0fe 100644 --- a/usbid/testdata_test.go +++ b/usbid/testdata_test.go @@ -46,13 +46,13 @@ var ( }, }, } - testDBClasses = map[uint8]*Class{ + testDBClasses = map[usb.Class]*Class{ 0x00: { Name: "(Defined at Interface level)", }, 0x01: { Name: "Audio", - SubClass: map[uint8]*SubClass{ + SubClass: map[usb.Class]*SubClass{ 0x01: {Name: "Control Device"}, 0x02: {Name: "Streaming"}, 0x03: {Name: "MIDI Streaming"}, @@ -60,7 +60,7 @@ var ( }, 0x02: { Name: "Communications", - SubClass: map[uint8]*SubClass{ + SubClass: map[usb.Class]*SubClass{ 0x01: {Name: "Direct Line"}, 0x02: { Name: "Abstract (modem)",