Add PollInterval specifications.
This commit is contained in:
90
libusb.go
90
libusb.go
@@ -63,46 +63,62 @@ func (ep libusbEndpoint) endpointDesc(dev *DeviceDesc) EndpointDesc {
|
|||||||
ei.UsageType = IsoUsageTypeImplicit
|
ei.UsageType = IsoUsageTypeImplicit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(sebek): PollInterval does not work yet. The meaning of bInterval
|
switch {
|
||||||
// in the descriptor varies depending on the device and USB version:
|
// If the device conforms to USB1.x:
|
||||||
// - if the device conforms to USB1.x:
|
|
||||||
// Interval for polling endpoint for data transfers. Expressed in
|
// Interval for polling endpoint for data transfers. Expressed in
|
||||||
// milliseconds.
|
// milliseconds.
|
||||||
// This field is ignored for bulk and control endpoints. For
|
// This field is ignored for bulk and control endpoints. For
|
||||||
// isochronous endpoints this field must be set to 1. For interrupt
|
// isochronous endpoints this field must be set to 1. For interrupt
|
||||||
// endpoints, this field may range from 1 to 255.
|
// endpoints, this field may range from 1 to 255.
|
||||||
// - if the device conforms to USB[23].x and the device is in low speed
|
// Note: in low-speed mode, isochronous transfers are not supported.
|
||||||
// of full speed mode:
|
case dev.Spec < Version(2, 0):
|
||||||
|
ei.PollInterval = time.Duration(ep.bInterval) * time.Millisecond
|
||||||
|
|
||||||
|
// If the device conforms to USB[23].x and the device is in low or full
|
||||||
|
// speed mode:
|
||||||
// Interval for polling endpoint for data transfers. Expressed in
|
// Interval for polling endpoint for data transfers. Expressed in
|
||||||
// frames or microframes depending on the device operating speed
|
// frames (1ms)
|
||||||
// (i.e., either 1 millisecond or 125 µs units).
|
// For full-speed isochronous endpoints, the value of this field should
|
||||||
// For full-/high-speed isochronous endpoints, this value must be in
|
// be 1.
|
||||||
// the range from 1 to 16. The bInterval value is used as the exponent
|
|
||||||
// for a 2bInterval-1 value; e.g., a bInterval of 4 means a period
|
|
||||||
// of 8 (24-1).
|
|
||||||
// For full-/low-speed interrupt endpoints, the value of this field may
|
// For full-/low-speed interrupt endpoints, the value of this field may
|
||||||
// be from 1 to 255.
|
// be from 1 to 255.
|
||||||
// For high-speed interrupt endpoints, the bInterval value is used as
|
// Note: in low-speed mode, isochronous transfers are not supported.
|
||||||
// the exponent for a 2bInterval-1 value; e.g., a bInterval of 4 means
|
case dev.Speed == SpeedUnknown || dev.Speed == SpeedLow || dev.Speed == SpeedFull:
|
||||||
// a period of 8 (24-1). This value must be from 1 to 16.
|
ei.PollInterval = time.Duration(ep.bInterval) * time.Millisecond
|
||||||
|
|
||||||
|
// If the device conforms to USB[23].x and the device is in high speed
|
||||||
|
// mode:
|
||||||
|
// Interval is expressed in microframe units (125 µs).
|
||||||
// For high-speed bulk/control OUT endpoints, the bInterval must
|
// For high-speed bulk/control OUT endpoints, the bInterval must
|
||||||
// specify the maximum NAK rate of the endpoint. A value of 0 indicates
|
// specify the maximum NAK rate of the endpoint. A value of 0 indicates
|
||||||
// the endpoint never NAKs. Other values indicate at most 1 NAK each
|
// the endpoint never NAKs. Other values indicate at most 1 NAK each
|
||||||
// bInterval number of microframes. This value must be in the range
|
// bInterval number of microframes. This value must be in the range
|
||||||
// from 0 to 255.
|
// from 0 to 255.
|
||||||
// - if the device conforms to USB3.x and the device is in SuperSpeed mode:
|
case dev.Speed == SpeedHigh && ei.TransferType == TransferTypeBulk:
|
||||||
|
ei.PollInterval = time.Duration(ep.bInterval) * 125 * time.Microsecond
|
||||||
|
|
||||||
|
// If the device conforms to USB[23].x and the device is in high speed
|
||||||
|
// mode:
|
||||||
|
// For high-speed isochronous endpoints, this value must be in
|
||||||
|
// the range from 1 to 16. The bInterval value is used as the exponent
|
||||||
|
// for a 2bInterval-1 value; e.g., a bInterval of 4 means a period
|
||||||
|
// of 8 (2^(4-1)).
|
||||||
|
// For high-speed interrupt endpoints, the bInterval value is used as
|
||||||
|
// the exponent for a 2bInterval-1 value; e.g., a bInterval of 4 means
|
||||||
|
// a period of 8 (2^(4-1)). This value must be from 1 to 16.
|
||||||
|
// If the device conforms to USB3.x and the device is in SuperSpeed mode:
|
||||||
// Interval for servicing the endpoint for data transfers. Expressed in
|
// Interval for servicing the endpoint for data transfers. Expressed in
|
||||||
// 125-µs units.
|
// 125-µs units.
|
||||||
// For Enhanced SuperSpeed isochronous and interrupt endpoints, this
|
// For Enhanced SuperSpeed isochronous and interrupt endpoints, this
|
||||||
// value shall be in the range from 1 to 16. However, the valid ranges
|
// value shall be in the range from 1 to 16. However, the valid ranges
|
||||||
// are 8 to 16 for Notification type Interrupt endpoints. The bInterval
|
// are 8 to 16 for Notification type Interrupt endpoints. The bInterval
|
||||||
// value is used as the exponent for a 2(bInterval-1) value; e.g., a
|
// value is used as the exponent for a 2(^bInterval-1) value; e.g., a
|
||||||
// bInterval of 4 means a period of 8 (2(4-1) → 23 → 8).
|
// bInterval of 4 means a period of 8 (2^(4-1) → 2^3 → 8).
|
||||||
// This field is reserved and shall not be used for Enhanced SuperSpeed
|
// This field is reserved and shall not be used for Enhanced SuperSpeed
|
||||||
// bulk or control endpoints.
|
// bulk or control endpoints.
|
||||||
//
|
case dev.Speed == SpeedHigh || dev.Speed == SpeedSuper:
|
||||||
// Note: in low-speed mode, isochronous transfers are not supported.
|
ei.PollInterval = 125 * time.Microsecond << (ep.bInterval - 1)
|
||||||
ei.PollInterval = 0
|
}
|
||||||
return ei
|
return ei
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +222,18 @@ func (libusbImpl) getDeviceDesc(d *libusbDevice) (*DeviceDesc, error) {
|
|||||||
if err := fromErrNo(C.libusb_get_device_descriptor((*C.libusb_device)(d), &desc)); err != nil {
|
if err := fromErrNo(C.libusb_get_device_descriptor((*C.libusb_device)(d), &desc)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
dev := &DeviceDesc{
|
||||||
|
Bus: int(C.libusb_get_bus_number((*C.libusb_device)(d))),
|
||||||
|
Address: int(C.libusb_get_device_address((*C.libusb_device)(d))),
|
||||||
|
Speed: Speed(C.libusb_get_device_speed((*C.libusb_device)(d))),
|
||||||
|
Spec: BCD(desc.bcdUSB),
|
||||||
|
Device: BCD(desc.bcdDevice),
|
||||||
|
Vendor: ID(desc.idVendor),
|
||||||
|
Product: ID(desc.idProduct),
|
||||||
|
Class: Class(desc.bDeviceClass),
|
||||||
|
SubClass: Class(desc.bDeviceSubClass),
|
||||||
|
Protocol: Protocol(desc.bDeviceProtocol),
|
||||||
|
}
|
||||||
// Enumerate configurations
|
// Enumerate configurations
|
||||||
cfgs := make(map[int]ConfigDesc)
|
cfgs := make(map[int]ConfigDesc)
|
||||||
for i := 0; i < int(desc.bNumConfigurations); i++ {
|
for i := 0; i < int(desc.bNumConfigurations); i++ {
|
||||||
@@ -217,9 +245,12 @@ func (libusbImpl) getDeviceDesc(d *libusbDevice) (*DeviceDesc, error) {
|
|||||||
Number: int(cfg.bConfigurationValue),
|
Number: int(cfg.bConfigurationValue),
|
||||||
SelfPowered: (cfg.bmAttributes & selfPoweredMask) != 0,
|
SelfPowered: (cfg.bmAttributes & selfPoweredMask) != 0,
|
||||||
RemoteWakeup: (cfg.bmAttributes & remoteWakeupMask) != 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),
|
MaxPower: 2 * Milliamperes(cfg.MaxPower),
|
||||||
}
|
}
|
||||||
|
// at GenX speeds MaxPower is expressed in units of 8mA, not 2mA.
|
||||||
|
if dev.Speed == SpeedSuper {
|
||||||
|
c.MaxPower *= 4
|
||||||
|
}
|
||||||
|
|
||||||
var ifaces []C.struct_libusb_interface
|
var ifaces []C.struct_libusb_interface
|
||||||
*(*reflect.SliceHeader)(unsafe.Pointer(&ifaces)) = reflect.SliceHeader{
|
*(*reflect.SliceHeader)(unsafe.Pointer(&ifaces)) = reflect.SliceHeader{
|
||||||
@@ -262,8 +293,7 @@ func (libusbImpl) getDeviceDesc(d *libusbDevice) (*DeviceDesc, error) {
|
|||||||
}
|
}
|
||||||
i.Endpoints = make(map[int]EndpointDesc, len(ends))
|
i.Endpoints = make(map[int]EndpointDesc, len(ends))
|
||||||
for _, end := range ends {
|
for _, end := range ends {
|
||||||
// TODO(sebek): pass the device descriptor too.
|
epi := libusbEndpoint(end).endpointDesc(dev)
|
||||||
epi := libusbEndpoint(end).endpointDesc(nil)
|
|
||||||
i.Endpoints[epi.Number] = epi
|
i.Endpoints[epi.Number] = epi
|
||||||
}
|
}
|
||||||
descs = append(descs, i)
|
descs = append(descs, i)
|
||||||
@@ -277,18 +307,8 @@ func (libusbImpl) getDeviceDesc(d *libusbDevice) (*DeviceDesc, error) {
|
|||||||
cfgs[c.Number] = c
|
cfgs[c.Number] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DeviceDesc{
|
dev.Configs = cfgs
|
||||||
Bus: int(C.libusb_get_bus_number((*C.libusb_device)(d))),
|
return dev, nil
|
||||||
Address: int(C.libusb_get_device_address((*C.libusb_device)(d))),
|
|
||||||
Spec: BCD(desc.bcdUSB),
|
|
||||||
Device: BCD(desc.bcdDevice),
|
|
||||||
Vendor: ID(desc.idVendor),
|
|
||||||
Product: ID(desc.idProduct),
|
|
||||||
Class: Class(desc.bDeviceClass),
|
|
||||||
SubClass: Class(desc.bDeviceSubClass),
|
|
||||||
Protocol: Protocol(desc.bDeviceProtocol),
|
|
||||||
Configs: cfgs,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (libusbImpl) dereference(d *libusbDevice) {
|
func (libusbImpl) dereference(d *libusbDevice) {
|
||||||
|
Reference in New Issue
Block a user