Checkpoint
This commit is contained in:
@@ -26,7 +26,7 @@ func main() {
|
|||||||
// ListDevices is used to find the devices to open.
|
// ListDevices is used to find the devices to open.
|
||||||
devs, err := ctx.ListDevices(func(desc *usb.Descriptor) bool {
|
devs, err := ctx.ListDevices(func(desc *usb.Descriptor) bool {
|
||||||
// The usbid package can be used to print out human readable information.
|
// The usbid package can be used to print out human readable information.
|
||||||
fmt.Printf("%03d.%03d %s\n", desc.Bus, desc.Address, usbid.Describe(desc))
|
fmt.Printf("%03d.%03d %s:%s %s\n", desc.Bus, desc.Address, desc.Vendor, desc.Product, usbid.Describe(desc))
|
||||||
fmt.Printf(" Protocol: %s\n", usbid.Classify(desc))
|
fmt.Printf(" Protocol: %s\n", usbid.Classify(desc))
|
||||||
|
|
||||||
// The configurations can be examined from the Descriptor, though they can only
|
// The configurations can be examined from the Descriptor, though they can only
|
||||||
|
89
rawread/main.go
Normal file
89
rawread/main.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/kylelemons/gousb/usb"
|
||||||
|
"github.com/kylelemons/gousb/usbid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
device = flag.String("device", "vend:prod", "Device to which to connect")
|
||||||
|
config = flag.Int("config", 1, "Endpoint to which to connect")
|
||||||
|
iface = flag.Int("interface", 0, "Endpoint to which to connect")
|
||||||
|
setup = flag.Int("setup", 0, "Endpoint to which to connect")
|
||||||
|
endpoint = flag.Int("endpoint", 1, "Endpoint to which to connect")
|
||||||
|
debug = flag.Int("debug", 3, "Debug level for libusb")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Only one context should be needed for an application. It should always be closed.
|
||||||
|
ctx := usb.NewContext()
|
||||||
|
defer ctx.Close()
|
||||||
|
|
||||||
|
ctx.Debug(*debug)
|
||||||
|
|
||||||
|
log.Printf("Scanning for device %q...", *device)
|
||||||
|
|
||||||
|
// ListDevices is used to find the devices to open.
|
||||||
|
devs, err := ctx.ListDevices(func(desc *usb.Descriptor) bool {
|
||||||
|
if fmt.Sprintf("%s:%s", desc.Vendor, desc.Product) != *device {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// The usbid package can be used to print out human readable information.
|
||||||
|
fmt.Printf(" Protocol: %s\n", usbid.Classify(desc))
|
||||||
|
|
||||||
|
// The configurations can be examined from the Descriptor, though they can only
|
||||||
|
// be set once the device is opened. All configuration references must be closed,
|
||||||
|
// to free up the memory in libusb.
|
||||||
|
for _, cfg := range desc.Configs {
|
||||||
|
// This loop just uses more of the built-in and usbid pretty printing to list
|
||||||
|
// the USB devices.
|
||||||
|
fmt.Printf(" %s:\n", cfg)
|
||||||
|
for _, alt := range cfg.Interfaces {
|
||||||
|
fmt.Printf(" --------------\n")
|
||||||
|
for _, iface := range alt.Setups {
|
||||||
|
fmt.Printf(" %s\n", iface)
|
||||||
|
fmt.Printf(" %s\n", usbid.Classify(iface))
|
||||||
|
for _, end := range iface.Endpoints {
|
||||||
|
fmt.Printf(" %s\n", end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Printf(" --------------\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
// All Devices returned from ListDevices must be closed.
|
||||||
|
defer func() {
|
||||||
|
for _, d := range devs {
|
||||||
|
d.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// ListDevices can occaionally fail, so be sure to check its return value.
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("list: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(devs) == 0 {
|
||||||
|
log.Fatalf("no devices found")
|
||||||
|
}
|
||||||
|
|
||||||
|
dev := devs[0]
|
||||||
|
|
||||||
|
log.Printf("Connecting to endpoint...")
|
||||||
|
log.Printf("- %#v", dev.Descriptor)
|
||||||
|
ep, err := dev.OpenEndpoint(uint8(*config), uint8(*iface), uint8(*setup), uint8(*endpoint) | uint8(usb.ENDPOINT_DIR_IN))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("open: %s", err)
|
||||||
|
}
|
||||||
|
_ = ep
|
||||||
|
}
|
BIN
rawread/rawread
Executable file
BIN
rawread/rawread
Executable file
Binary file not shown.
@@ -1,6 +1,5 @@
|
|||||||
package usb
|
package usb
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lusb-1.0
|
|
||||||
// #include <libusb-1.0/libusb.h>
|
// #include <libusb-1.0/libusb.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
package usb
|
package usb
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lusb-1.0
|
|
||||||
// #include <libusb-1.0/libusb.h>
|
// #include <libusb-1.0/libusb.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
package usb
|
package usb
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lusb-1.0
|
|
||||||
// #include <libusb-1.0/libusb.h>
|
// #include <libusb-1.0/libusb.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
168
usb/device.go
168
usb/device.go
@@ -1,177 +1,9 @@
|
|||||||
package usb
|
package usb
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lusb-1.0
|
|
||||||
// #include <libusb-1.0/libusb.h>
|
// #include <libusb-1.0/libusb.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var DefaultReadTimeout = 1 * time.Second
|
|
||||||
var DefaultWriteTimeout = 1 * time.Second
|
|
||||||
var DefaultControlTimeout = 5 * time.Second
|
|
||||||
|
|
||||||
type Device struct {
|
|
||||||
handle *C.libusb_device_handle
|
|
||||||
|
|
||||||
// Embed the device information for easy access
|
|
||||||
*Descriptor
|
|
||||||
|
|
||||||
// Timeouts
|
|
||||||
ReadTimeout time.Duration
|
|
||||||
WriteTimeout time.Duration
|
|
||||||
ControlTimeout time.Duration
|
|
||||||
|
|
||||||
// Claimed interfaces
|
|
||||||
lock *sync.Mutex
|
|
||||||
claimed map[uint8]int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDevice(handle *C.libusb_device_handle, desc *Descriptor) *Device {
|
|
||||||
ifaces := 0
|
|
||||||
d := &Device{
|
|
||||||
handle: handle,
|
|
||||||
Descriptor: desc,
|
|
||||||
ReadTimeout: DefaultReadTimeout,
|
|
||||||
WriteTimeout: DefaultWriteTimeout,
|
|
||||||
ControlTimeout: DefaultControlTimeout,
|
|
||||||
lock: new(sync.Mutex),
|
|
||||||
claimed: make(map[uint8]int, ifaces),
|
|
||||||
}
|
|
||||||
|
|
||||||
// This doesn't seem to actually get called
|
|
||||||
runtime.SetFinalizer(d, (*Device).Close)
|
|
||||||
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Device) Reset() error {
|
|
||||||
if errno := C.libusb_reset_device(d.handle); errno != 0 {
|
|
||||||
return usbError(errno)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
|
|
||||||
dataSlice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
|
||||||
n := C.libusb_control_transfer(
|
|
||||||
d.handle,
|
|
||||||
C.uint8_t(rType),
|
|
||||||
C.uint8_t(request),
|
|
||||||
C.uint16_t(val),
|
|
||||||
C.uint16_t(idx),
|
|
||||||
(*C.uchar)(unsafe.Pointer(dataSlice.Data)),
|
|
||||||
C.uint16_t(len(data)),
|
|
||||||
C.uint(d.ControlTimeout/time.Millisecond))
|
|
||||||
if n < 0 {
|
|
||||||
return int(n), usbError(n)
|
|
||||||
}
|
|
||||||
return int(n), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ActiveConfig returns the config id (not the index) of the active configuration.
|
|
||||||
// This corresponds to the ConfigInfo.Config field.
|
|
||||||
func (d *Device) ActiveConfig() (uint8, error) {
|
|
||||||
var cfg C.int
|
|
||||||
if errno := C.libusb_get_configuration(d.handle, &cfg); errno < 0 {
|
|
||||||
return 0, usbError(errno)
|
|
||||||
}
|
|
||||||
return uint8(cfg), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetConfig attempts to change the active configuration.
|
|
||||||
// The cfg provided is the config id (not the index) of the configuration to set,
|
|
||||||
// which corresponds to the ConfigInfo.Config field.
|
|
||||||
func (d *Device) SetConfig(cfg uint8) error {
|
|
||||||
if errno := C.libusb_set_configuration(d.handle, C.int(cfg)); errno < 0 {
|
|
||||||
return usbError(errno)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the device.
|
|
||||||
func (d *Device) Close() error {
|
|
||||||
if d.handle == nil {
|
|
||||||
return fmt.Errorf("usb: double close on device")
|
|
||||||
}
|
|
||||||
d.lock.Lock()
|
|
||||||
defer d.lock.Unlock()
|
|
||||||
for iface := range d.claimed {
|
|
||||||
C.libusb_release_interface(d.handle, C.int(iface))
|
|
||||||
}
|
|
||||||
C.libusb_close(d.handle)
|
|
||||||
d.handle = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Device) OpenEndpoint(conf, iface, setup, epoint uint8) (Endpoint, error) {
|
|
||||||
end := &endpoint{
|
|
||||||
Device: d,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range d.Configs {
|
|
||||||
if c.Config != conf {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, i := range c.Interfaces {
|
|
||||||
if i.Number != iface {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, s := range i.Setups {
|
|
||||||
if s.Alternate != setup {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, e := range s.Endpoints {
|
|
||||||
if e.Address != epoint {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
end.InterfaceSetup = s
|
|
||||||
end.EndpointInfo = e
|
|
||||||
switch tt := TransferType(e.Attributes) & TRANSFER_TYPE_MASK; tt {
|
|
||||||
case TRANSFER_TYPE_BULK:
|
|
||||||
end.xfer = bulk_xfer
|
|
||||||
case TRANSFER_TYPE_INTERRUPT:
|
|
||||||
end.xfer = interrupt_xfer
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("usb: %s transfer is unsupported", tt)
|
|
||||||
}
|
|
||||||
goto found
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("usb: unknown endpoint %02x", epoint)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("usb: unknown setup %02x", setup)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("usb: unknown interface %02x", iface)
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("usb: unknown configuration %02x", conf)
|
|
||||||
|
|
||||||
found:
|
|
||||||
|
|
||||||
// Claim the interface
|
|
||||||
if errno := C.libusb_claim_interface(d.handle, C.int(iface)); errno < 0 {
|
|
||||||
return nil, fmt.Errorf("usb: claim: %s", usbError(errno))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment the claim count
|
|
||||||
d.lock.Lock()
|
|
||||||
d.claimed[iface]++
|
|
||||||
d.lock.Unlock() // unlock immediately because the next calls may block
|
|
||||||
|
|
||||||
// Set the configuration
|
|
||||||
if errno := C.libusb_set_configuration(d.handle, C.int(conf)); errno < 0 {
|
|
||||||
return nil, fmt.Errorf("usb: setcfg: %s", usbError(errno))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose the alternate
|
|
||||||
if errno := C.libusb_set_interface_alt_setting(d.handle, C.int(iface), C.int(setup)); errno < 0 {
|
|
||||||
return nil, fmt.Errorf("usb: setalt: %s", usbError(errno))
|
|
||||||
}
|
|
||||||
|
|
||||||
return end, nil
|
|
||||||
}
|
|
||||||
|
86
usb/endpoint.go
Normal file
86
usb/endpoint.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
package usb
|
||||||
|
|
||||||
|
// #include <libusb-1.0/libusb.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Endpoint interface {
|
||||||
|
Read(b []byte) (int, error)
|
||||||
|
Write(b []byte) (int, error)
|
||||||
|
Interface() InterfaceSetup
|
||||||
|
Info() EndpointInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type endpoint struct {
|
||||||
|
*Device
|
||||||
|
InterfaceSetup
|
||||||
|
EndpointInfo
|
||||||
|
xfer func(*endpoint, []byte, time.Duration) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpoint) Read(buf []byte) (int, error) {
|
||||||
|
if EndpointDirection(e.Address) & ENDPOINT_DIR_MASK != ENDPOINT_DIR_OUT {
|
||||||
|
return 0, fmt.Errorf("usb: read: not an IN endpoint")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.xfer(e, buf, e.ReadTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpoint) Write(buf []byte) (int, error) {
|
||||||
|
if EndpointDirection(e.Address) & ENDPOINT_DIR_MASK != ENDPOINT_DIR_OUT {
|
||||||
|
return 0, fmt.Errorf("usb: write: not an OUT endpoint")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.xfer(e, buf, e.WriteTimeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *endpoint) Interface() InterfaceSetup { return InterfaceSetup{} }
|
||||||
|
func (e *endpoint) Info() EndpointInfo { return EndpointInfo{} }
|
||||||
|
|
||||||
|
// TODO(kevlar): (*Endpoint).Close
|
||||||
|
|
||||||
|
func bulk_xfer(e *endpoint, buf []byte, timeout time.Duration) (int, error) {
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data
|
||||||
|
|
||||||
|
var cnt C.int
|
||||||
|
if errno := C.libusb_bulk_transfer(
|
||||||
|
e.handle,
|
||||||
|
C.uchar(e.Address),
|
||||||
|
(*C.uchar)(unsafe.Pointer(data)),
|
||||||
|
C.int(len(buf)),
|
||||||
|
&cnt,
|
||||||
|
C.uint(timeout/time.Millisecond)); errno < 0 {
|
||||||
|
return 0, usbError(errno)
|
||||||
|
}
|
||||||
|
return int(cnt), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func interrupt_xfer(e *endpoint, buf []byte, timeout time.Duration) (int, error) {
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
data := (*reflect.SliceHeader)(unsafe.Pointer(&buf)).Data
|
||||||
|
|
||||||
|
var cnt C.int
|
||||||
|
if errno := C.libusb_interrupt_transfer(
|
||||||
|
e.handle,
|
||||||
|
C.uchar(e.Address),
|
||||||
|
(*C.uchar)(unsafe.Pointer(data)),
|
||||||
|
C.int(len(buf)),
|
||||||
|
&cnt,
|
||||||
|
C.uint(timeout/time.Millisecond)); errno < 0 {
|
||||||
|
return 0, usbError(errno)
|
||||||
|
}
|
||||||
|
return int(cnt), nil
|
||||||
|
}
|
@@ -1,6 +1,5 @@
|
|||||||
package usb
|
package usb
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lusb-1.0
|
|
||||||
// #include <libusb-1.0/libusb.h>
|
// #include <libusb-1.0/libusb.h>
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
182
usb/iso.go
Normal file
182
usb/iso.go
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
package usb
|
||||||
|
|
||||||
|
// #include <libusb-1.0/libusb.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DefaultReadTimeout = 1 * time.Second
|
||||||
|
var DefaultWriteTimeout = 1 * time.Second
|
||||||
|
var DefaultControlTimeout = 5 * time.Second
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
handle *C.libusb_device_handle
|
||||||
|
|
||||||
|
// Embed the device information for easy access
|
||||||
|
*Descriptor
|
||||||
|
|
||||||
|
// Timeouts
|
||||||
|
ReadTimeout time.Duration
|
||||||
|
WriteTimeout time.Duration
|
||||||
|
ControlTimeout time.Duration
|
||||||
|
|
||||||
|
// Claimed interfaces
|
||||||
|
lock *sync.Mutex
|
||||||
|
claimed map[uint8]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDevice(handle *C.libusb_device_handle, desc *Descriptor) *Device {
|
||||||
|
ifaces := 0
|
||||||
|
d := &Device{
|
||||||
|
handle: handle,
|
||||||
|
Descriptor: desc,
|
||||||
|
ReadTimeout: DefaultReadTimeout,
|
||||||
|
WriteTimeout: DefaultWriteTimeout,
|
||||||
|
ControlTimeout: DefaultControlTimeout,
|
||||||
|
lock: new(sync.Mutex),
|
||||||
|
claimed: make(map[uint8]int, ifaces),
|
||||||
|
}
|
||||||
|
|
||||||
|
// This doesn't seem to actually get called
|
||||||
|
runtime.SetFinalizer(d, (*Device).Close)
|
||||||
|
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) Reset() error {
|
||||||
|
if errno := C.libusb_reset_device(d.handle); errno != 0 {
|
||||||
|
return usbError(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
|
||||||
|
dataSlice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
||||||
|
n := C.libusb_control_transfer(
|
||||||
|
d.handle,
|
||||||
|
C.uint8_t(rType),
|
||||||
|
C.uint8_t(request),
|
||||||
|
C.uint16_t(val),
|
||||||
|
C.uint16_t(idx),
|
||||||
|
(*C.uchar)(unsafe.Pointer(dataSlice.Data)),
|
||||||
|
C.uint16_t(len(data)),
|
||||||
|
C.uint(d.ControlTimeout/time.Millisecond))
|
||||||
|
if n < 0 {
|
||||||
|
return int(n), usbError(n)
|
||||||
|
}
|
||||||
|
return int(n), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ActiveConfig returns the config id (not the index) of the active configuration.
|
||||||
|
// This corresponds to the ConfigInfo.Config field.
|
||||||
|
func (d *Device) ActiveConfig() (uint8, error) {
|
||||||
|
var cfg C.int
|
||||||
|
if errno := C.libusb_get_configuration(d.handle, &cfg); errno < 0 {
|
||||||
|
return 0, usbError(errno)
|
||||||
|
}
|
||||||
|
return uint8(cfg), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfig attempts to change the active configuration.
|
||||||
|
// The cfg provided is the config id (not the index) of the configuration to set,
|
||||||
|
// which corresponds to the ConfigInfo.Config field.
|
||||||
|
func (d *Device) SetConfig(cfg uint8) error {
|
||||||
|
if errno := C.libusb_set_configuration(d.handle, C.int(cfg)); errno < 0 {
|
||||||
|
return usbError(errno)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the device.
|
||||||
|
func (d *Device) Close() error {
|
||||||
|
if d.handle == nil {
|
||||||
|
return fmt.Errorf("usb: double close on device")
|
||||||
|
}
|
||||||
|
d.lock.Lock()
|
||||||
|
defer d.lock.Unlock()
|
||||||
|
for iface := range d.claimed {
|
||||||
|
C.libusb_release_interface(d.handle, C.int(iface))
|
||||||
|
}
|
||||||
|
C.libusb_close(d.handle)
|
||||||
|
d.handle = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) OpenEndpoint(conf, iface, setup, epoint uint8) (Endpoint, error) {
|
||||||
|
end := &endpoint{
|
||||||
|
Device: d,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range d.Configs {
|
||||||
|
if c.Config != conf {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("found conf: %#v\n", c)
|
||||||
|
for _, i := range c.Interfaces {
|
||||||
|
if i.Number != iface {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("found iface: %#v\n", i)
|
||||||
|
for _, s := range i.Setups {
|
||||||
|
if s.Alternate != setup {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Printf("found setup: %#v\n", s)
|
||||||
|
for _, e := range s.Endpoints {
|
||||||
|
fmt.Printf("ep %02x search: %#v\n", epoint, s)
|
||||||
|
if e.Address != epoint {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
end.InterfaceSetup = s
|
||||||
|
end.EndpointInfo = e
|
||||||
|
switch tt := TransferType(e.Attributes) & TRANSFER_TYPE_MASK; tt {
|
||||||
|
case TRANSFER_TYPE_BULK:
|
||||||
|
end.xfer = bulk_xfer
|
||||||
|
case TRANSFER_TYPE_INTERRUPT:
|
||||||
|
end.xfer = interrupt_xfer
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("usb: %s transfer is unsupported", tt)
|
||||||
|
}
|
||||||
|
goto found
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("usb: unknown endpoint %02x", epoint)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("usb: unknown setup %02x", setup)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("usb: unknown interface %02x", iface)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("usb: unknown configuration %02x", conf)
|
||||||
|
|
||||||
|
found:
|
||||||
|
|
||||||
|
// Claim the interface
|
||||||
|
if errno := C.libusb_claim_interface(d.handle, C.int(iface)); errno < 0 {
|
||||||
|
return nil, fmt.Errorf("usb: claim: %s", usbError(errno))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the claim count
|
||||||
|
d.lock.Lock()
|
||||||
|
d.claimed[iface]++
|
||||||
|
d.lock.Unlock() // unlock immediately because the next calls may block
|
||||||
|
|
||||||
|
// Set the configuration
|
||||||
|
if errno := C.libusb_set_configuration(d.handle, C.int(conf)); errno < 0 {
|
||||||
|
return nil, fmt.Errorf("usb: setcfg: %s", usbError(errno))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose the alternate
|
||||||
|
/* This doesn't seem to work...
|
||||||
|
if errno := C.libusb_set_interface_alt_setting(d.handle, C.int(iface), C.int(setup)); errno < 0 {
|
||||||
|
return nil, fmt.Errorf("usb: setalt: %s", usbError(errno))
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return end, nil
|
||||||
|
}
|
@@ -39,13 +39,13 @@ func Describe(val interface{}) string {
|
|||||||
//
|
//
|
||||||
// The given val must be one of the following:
|
// The given val must be one of the following:
|
||||||
// - *usb.Descriptor "Class (SubClass) Protocol"
|
// - *usb.Descriptor "Class (SubClass) Protocol"
|
||||||
// - *usb.InterfaceSetup "IfClass (IfSubClass) IfProtocol"
|
// - usb.InterfaceSetup "IfClass (IfSubClass) IfProtocol"
|
||||||
func Classify(val interface{}) string {
|
func Classify(val interface{}) string {
|
||||||
var class, sub, proto uint8
|
var class, sub, proto uint8
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case *usb.Descriptor:
|
case *usb.Descriptor:
|
||||||
class, sub, proto = val.Class, val.SubClass, val.Protocol
|
class, sub, proto = val.Class, val.SubClass, val.Protocol
|
||||||
case *usb.InterfaceSetup:
|
case usb.InterfaceSetup:
|
||||||
class, sub, proto = val.IfClass, val.IfSubClass, val.IfProtocol
|
class, sub, proto = val.IfClass, val.IfSubClass, val.IfProtocol
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("Unknown (%T)", val)
|
return fmt.Sprintf("Unknown (%T)", val)
|
||||||
|
Reference in New Issue
Block a user