Android support via fileDescriptor (#130)
Adds a new way to initialize the context, `ContextOptions`, and a new way to open devices, `OpenDeviceWithFileDescriptor`. Combined they can be used to support Android devices, where device enumeration is not supported (can be now disabled through `ContextOptions`) and where USB devices can be opened in the Android SDK and passed over to gousb through a file descriptor. Co-authored-by: Juan <994594+juaoose@users.noreply.github.com> Co-authored-by: Kuba Raczkowski <kuba.raczkowski@spectricity.com>
This commit is contained in:
66
usb.go
66
usb.go
@@ -163,9 +163,36 @@ func newContextWithImpl(impl libusbIntf) *Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
// NewContext returns a new Context instance.
|
||||
// NewContext returns a new Context instance with default ContextOptions.
|
||||
func NewContext() *Context {
|
||||
return newContextWithImpl(libusbImpl{})
|
||||
return ContextOptions{}.New()
|
||||
}
|
||||
|
||||
// DeviceDiscovery controls USB device discovery.
|
||||
type DeviceDiscovery int
|
||||
|
||||
const (
|
||||
// EnableDeviceDiscovery means the connected USB devices will be enumerated
|
||||
// on Context initialization. This enables the use of OpenDevices and
|
||||
// OpenWithVIDPID. This is the default.
|
||||
EnableDeviceDiscovery = iota
|
||||
// DisableDeviceDiscovery means the USB devices are not enumerated and
|
||||
// OpenDevices will not return any devices.
|
||||
// Without device discovery, OpenDeviceWithFileDescriptor can be used
|
||||
// to open devices.
|
||||
DisableDeviceDiscovery
|
||||
)
|
||||
|
||||
// ContextOptions holds parameters for Context initialization.
|
||||
type ContextOptions struct {
|
||||
DeviceDiscovery DeviceDiscovery
|
||||
}
|
||||
|
||||
// New creates a Context, taking into account the optional flags contained in ContextOptions
|
||||
func (o ContextOptions) New() *Context {
|
||||
return newContextWithImpl(libusbImpl{
|
||||
discovery: o.DeviceDiscovery,
|
||||
})
|
||||
}
|
||||
|
||||
// OpenDevices calls opener with each enumerated device.
|
||||
@@ -210,6 +237,41 @@ func (c *Context) OpenDevices(opener func(desc *DeviceDesc) bool) ([]*Device, er
|
||||
return ret, reterr
|
||||
}
|
||||
|
||||
// OpenDeviceWithFileDescriptor takes a (Unix) file descriptor of an opened USB
|
||||
// device and wraps the library around it.
|
||||
// This is particularly useful when working on Android, where the USB device can be
|
||||
// opened by the SDK (Java), giving access to the device through the file descriptor
|
||||
// (https://developer.android.com/reference/android/hardware/usb/UsbDeviceConnection#getFileDescriptor()).
|
||||
//
|
||||
// Do note that for this to work the automatic device discovery must be disabled
|
||||
// at the time when the new Context is created, through the use of
|
||||
// ContextOptions.DeviceDiscovery.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// ctx := ContextOptions{DeviceDiscovery: DisableDeviceDiscovery}.New()
|
||||
// device, err := ctx.OpenDeviceWithFileDescriptor(fd)
|
||||
//
|
||||
// An error is returned in case the file descriptor is not valid.
|
||||
func (c *Context) OpenDeviceWithFileDescriptor(fd uintptr) (*Device, error) {
|
||||
handle, err := c.libusb.wrapSysDevice(c.ctx, fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dev := c.libusb.getDevice(handle)
|
||||
desc, err := c.libusb.getDeviceDesc(dev)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("device was opened, but getting device descriptor failed: %v", err)
|
||||
}
|
||||
|
||||
o := &Device{handle: handle, ctx: c, Desc: desc}
|
||||
c.mu.Lock()
|
||||
c.devices[o] = true
|
||||
c.mu.Unlock()
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// OpenDeviceWithVIDPID opens Device from specific VendorId and ProductId.
|
||||
// If none is found, it returns nil and nil error. If there are multiple devices
|
||||
// with the same VID/PID, it will return one of them, picked arbitrarily.
|
||||
|
Reference in New Issue
Block a user