Files
gousb/usb/config.go
Sebastian Zagrodzki f13728c6e1 Set the MaxIsoPacket field in the endpoint info if the endpoint is
an isochronous endpoint. Use MaxIsoPacket as the iso packet size
when preparing the iso transfer.
2017-02-05 16:20:58 +01:00

155 lines
4.5 KiB
Go

// Copyright 2013 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package usb
// #include <libusb-1.0/libusb.h>
import "C"
import (
"fmt"
"reflect"
"unsafe"
)
type EndpointInfo struct {
Address uint8
Attributes uint8
MaxPacketSize uint16
MaxIsoPacket uint32
PollInterval uint8
RefreshRate uint8
SynchAddress uint8
}
func (e EndpointInfo) Number() int {
return int(e.Address) & ENDPOINT_NUM_MASK
}
func (e EndpointInfo) Direction() EndpointDirection {
return EndpointDirection(e.Address) & ENDPOINT_DIR_MASK
}
func (e EndpointInfo) String() string {
return fmt.Sprintf("Endpoint %d %-3s %s - %s %s [%d %d]",
e.Number(), e.Direction(),
TransferType(e.Attributes)&TRANSFER_TYPE_MASK,
IsoSyncType(e.Attributes)&ISO_SYNC_TYPE_MASK,
IsoUsageType(e.Attributes)&ISO_USAGE_TYPE_MASK,
e.MaxPacketSize, e.MaxIsoPacket,
)
}
type InterfaceInfo struct {
Number uint8
Setups []InterfaceSetup
}
func (i InterfaceInfo) String() string {
return fmt.Sprintf("Interface %02x (%d setups)", i.Number, len(i.Setups))
}
type InterfaceSetup struct {
Number uint8
Alternate uint8
IfClass uint8
IfSubClass uint8
IfProtocol uint8
Endpoints []EndpointInfo
}
func (a InterfaceSetup) String() string {
return fmt.Sprintf("Interface %02x Setup %02x", a.Number, a.Alternate)
}
type ConfigInfo struct {
Config uint8
Attributes uint8
MaxPower uint8
Interfaces []InterfaceInfo
}
func (c ConfigInfo) String() string {
return fmt.Sprintf("Config %02x", c.Config)
}
func newConfig(dev *C.libusb_device, cfg *C.struct_libusb_config_descriptor) ConfigInfo {
c := ConfigInfo{
Config: uint8(cfg.bConfigurationValue),
Attributes: uint8(cfg.bmAttributes),
MaxPower: uint8(cfg.MaxPower),
}
var ifaces []C.struct_libusb_interface
*(*reflect.SliceHeader)(unsafe.Pointer(&ifaces)) = reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cfg._interface)),
Len: int(cfg.bNumInterfaces),
Cap: int(cfg.bNumInterfaces),
}
c.Interfaces = make([]InterfaceInfo, 0, len(ifaces))
for _, iface := range ifaces {
if iface.num_altsetting == 0 {
continue
}
var alts []C.struct_libusb_interface_descriptor
*(*reflect.SliceHeader)(unsafe.Pointer(&alts)) = reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(iface.altsetting)),
Len: int(iface.num_altsetting),
Cap: int(iface.num_altsetting),
}
descs := make([]InterfaceSetup, 0, len(alts))
for _, alt := range alts {
i := InterfaceSetup{
Number: uint8(alt.bInterfaceNumber),
Alternate: uint8(alt.bAlternateSetting),
IfClass: uint8(alt.bInterfaceClass),
IfSubClass: uint8(alt.bInterfaceSubClass),
IfProtocol: uint8(alt.bInterfaceProtocol),
}
var ends []C.struct_libusb_endpoint_descriptor
*(*reflect.SliceHeader)(unsafe.Pointer(&ends)) = reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(alt.endpoint)),
Len: int(alt.bNumEndpoints),
Cap: int(alt.bNumEndpoints),
}
i.Endpoints = make([]EndpointInfo, 0, len(ends))
for _, end := range ends {
ei := EndpointInfo{
Address: uint8(end.bEndpointAddress),
Attributes: uint8(end.bmAttributes),
MaxPacketSize: uint16(end.wMaxPacketSize),
PollInterval: uint8(end.bInterval),
RefreshRate: uint8(end.bRefresh),
SynchAddress: uint8(end.bSynchAddress),
}
if TransferType(ei.Attributes)&TRANSFER_TYPE_MASK == TRANSFER_TYPE_ISOCHRONOUS {
// bits 0-10 identify the packet size, bits 11-12 are the number of additional transactions per microframe.
// Don't use libusb_get_max_iso_packet_size, as it has a bug where it returns the same value
// regardless of alternative setting used, where different alternative settings might define different
// max packet sizes.
ei.MaxIsoPacket = uint32(end.wMaxPacketSize) & 0x07ff * (uint32(end.wMaxPacketSize)>>11&3 + 1)
}
i.Endpoints = append(i.Endpoints, ei)
}
descs = append(descs, i)
}
c.Interfaces = append(c.Interfaces, InterfaceInfo{
Number: descs[0].Number,
Setups: descs,
})
}
return c
}