Add PollInterval specifications.

This commit is contained in:
Sebastian Zagrodzki
2017-05-06 13:16:48 +02:00
parent bcc0b02135
commit b0df83bff6

View File

@@ -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) {