misc: added gousb dependency

This commit is contained in:
evilsocket 2019-02-19 21:48:37 +01:00
parent c1729ab578
commit 6458a438db
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
25 changed files with 3248 additions and 0 deletions

17
Gopkg.lock generated
View file

@ -26,6 +26,14 @@
pruneopts = "UT"
revision = "1353e80bee488dc02d1f7e42759c1352492bf18b"
[[projects]]
branch = "master"
digest = "1:c93fdd8820c13c2e2000d3064c510dde1397edca5ca1533fd15943402dab92b0"
name = "github.com/bettercap/nrf24"
packages = ["."]
pruneopts = "UT"
revision = "aa37e6d0e0eb125cee9ec71ed694db2ad58b509a"
[[projects]]
digest = "1:b95738a1e6ace058b5b8544303c0871fc01d224ef0d672f778f696265d0f2917"
name = "github.com/bettercap/readline"
@ -120,6 +128,14 @@
pruneopts = "UT"
revision = "v1.1.16"
[[projects]]
branch = "master"
digest = "1:2ef895ea08a0af10ad6f1e1faf631c82fa5413dcf0ada93eb62ab5ad02df4979"
name = "github.com/google/gousb"
packages = ["."]
pruneopts = "UT"
revision = "d0c05ab7f70d6f6dc60ecd184517cb5e25860657"
[[projects]]
digest = "1:ca59b1175189b3f0e9f1793d2c350114be36eaabbe5b9f554b35edee1de50aea"
name = "github.com/gorilla/mux"
@ -277,6 +293,7 @@
input-imports = [
"github.com/adrianmo/go-nmea",
"github.com/bettercap/gatt",
"github.com/bettercap/nrf24",
"github.com/bettercap/readline",
"github.com/chifflier/nfqueue-go/nfqueue",
"github.com/dustin/go-humanize",

2
vendor/github.com/google/gousb/.gitignore generated vendored Normal file
View file

@ -0,0 +1,2 @@
*.sw[op]
.idea/

30
vendor/github.com/google/gousb/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,30 @@
language: go
dist: trusty
go:
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- tip
addons:
apt:
packages:
libusb-1.0-0-dev
install:
- go get golang.org/x/tools/cmd/cover
# Golint requires Go 1.9 or later.
- if ! [[ "$TRAVIS_GO_VERSION" =~ ^1\.7\.([0-9]+|x)$ || "$TRAVIS_GO_VERSION" =~ ^1\.8\.([0-9]+|x)$ ]]; then go get golang.org/x/lint/golint; fi
- go get github.com/mattn/goveralls
script:
# a workaround for go test not supporting coverage for multiple packages in a single invocation.
# If goveralls upload fails, ignore the result.
# Golint requires Go 1.9 or later.
- if ! [[ "$TRAVIS_GO_VERSION" =~ ^1\.7\.([0-9]+|x)+$ || "$TRAVIS_GO_VERSION" =~ ^1\.8\.([0-9]+|x)$ ]]; then $HOME/gopath/bin/golint ./...; fi
- |-
echo 'mode: count' > coverage.merged && go list ./... | xargs -n1 -I{} sh -c ': > coverage.tmp; go test -v -covermode=count -coverprofile=coverage.tmp {} && tail -n +2 coverage.tmp >> coverage.merged' && rm coverage.tmp
- |-
$HOME/gopath/bin/goveralls -coverprofile=coverage.merged -service=travis-ci -ignore libusb.go,error.go || true

16
vendor/github.com/google/gousb/AUTHORS generated vendored Normal file
View file

@ -0,0 +1,16 @@
This is the list of gousb authors for copyright purposes.
#
# This does not necessarily list everyone who has contributed code, since in
# some cases, their employer may be the copyright holder. To see the full list
# of contributors, see the revision history in source control.
Google Inc.
Kyle Lemons <kyle@kylelemons.net>
Sebastian Zagrodzki <sebek@zagrodzki.net>
Pieter Joost van de Sande <pj@born2code.net>
Ivan Krasin <imkrasin@gmail.com>
Jirawat I. <nodtem66@gmail.com>
Thordur Bjornsson <thorduri@secnorth.net>
Vincent Serpoul <vincent@serpoul.com>
Josef Filzmaier <josef.filzmaier@gmail.com>
Nico MT <nicovell3@gmail.com>
Deomid "rojer" Ryabkov <rojer@rojer.me>

28
vendor/github.com/google/gousb/CONTRIBUTING.md generated vendored Normal file
View file

@ -0,0 +1,28 @@
Want to contribute? Great! First, read this page (including the small print at
the end).
### Before you contribute
Before we can use your code, you must sign the
[Google Individual Contributor License Agreement]
(https://cla.developers.google.com/about/google-individual)
(CLA), which you can do online. The CLA is necessary mainly because you own the
copyright to your changes, even after your contribution becomes part of our
codebase, so we need your permission to use and distribute your code. We also
need to be sure of various other things—for instance that you'll tell us if you
know that your code infringes on other people's patents. You don't have to sign
the CLA until after you've submitted your code for review and a member has
approved it, but you must do it before we can put your code into our codebase.
Before you start working on a larger contribution, you should get in touch with
us first through the issue tracker with your idea so that we can help out and
possibly guide you. Coordinating up front makes it much easier to avoid
frustration later on.
### Code reviews
All submissions, including submissions by project members, require review. We
use Github pull requests for this purpose.
### The small print
Contributions made by corporations are covered by a different agreement than
the one above, the
[Software Grant and Corporate Contributor License Agreement]
(https://cla.developers.google.com/about/google-corporate).

202
vendor/github.com/google/gousb/LICENSE generated vendored Normal file
View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

87
vendor/github.com/google/gousb/README.md generated vendored Normal file
View file

@ -0,0 +1,87 @@
Introduction
============
[![Build Status][ciimg]][ci]
[![GoDoc][docimg]][doc]
[![Coverage Status][coverimg]][cover]
[![Build status][appveimg]][appveyor]
The gousb package is an attempt at wrapping the libusb library into a Go-like binding.
Supported platforms include:
- linux
- darwin
- windows
This is the release 2.0 of the package [github.com/kylelemons/gousb](https://github.com/kylelemons/gousb).
Its API is not backwards-compatible with version 1.0.
As of 2017-07-13 the 2.0 API is considered stable and 1.0 is deprecated.
[coverimg]: https://coveralls.io/repos/github/google/gousb/badge.svg
[cover]: https://coveralls.io/github/google/gousb
[ciimg]: https://travis-ci.org/google/gousb.svg
[ci]: https://travis-ci.org/google/gousb
[docimg]: https://godoc.org/github.com/google/gousb?status.svg
[doc]: https://godoc.org/github.com/google/gousb
[appveimg]: https://ci.appveyor.com/api/projects/status/661qp7x33o3wqe4o?svg=true
[appveyor]: https://ci.appveyor.com/project/zagrodzki/gousb
Documentation
=============
The documentation can be viewed via local godoc or via the excellent [godoc.org](http://godoc.org/):
- [usb](http://godoc.org/github.com/google/gousb)
- [usbid](http://godoc.org/pkg/github.com/google/gousb/usbid)
Installation
============
Dependencies
------------
You must first install [libusb-1.0]https://github.com/libusb/libusb/wiki). This is pretty straightforward on linux and darwin. The cgo package should be able to find it if you install it in the default manner or use your distribution's package manager. How to tell cgo how to find one installed in a non-default place is beyond the scope of this README.
*Note*: If you are installing this on darwin, you will probably need to run `fixlibusb_darwin.sh /usr/local/lib/libusb-1.0/libusb.h` because of an LLVM incompatibility. It shouldn't break C programs, though I haven't tried it in anger.
Example: lsusb
--------------
The gousb project provides a simple but useful example: lsusb. This binary will list the USB devices connected to your system and various interesting tidbits about them, their configurations, endpoints, etc. To install it, run the following command:
go get -v github.com/google/gousb/lsusb
gousb
-----
If you installed the lsusb example, both libraries below are already installed.
Installing the primary gousb package is really easy:
go get -v github.com/google/gousb
There is also a `usbid` package that will not be installed by default by this command, but which provides useful information including the human-readable vendor and product codes for detected hardware. It's not installed by default and not linked into the `gousb` package by default because it adds ~400kb to the resulting binary. If you want both, they can be installed thus:
go get -v github.com/google/gousb{,/usbid}
Notes for installation on Windows
---------------------------------
You'll need:
- Gcc - tested on [Win-Builds](http://win-builds.org/) and MSYS/MINGW
- pkg-config - see http://www.mingw.org/wiki/FAQ, "How do I get pkg-config installed?"
- [libusb-1.0](http://sourceforge.net/projects/libusb/files/libusb-1.0/).
Make sure the `libusb-1.0.pc` pkg-config file from libusb was installed
and that the result of the `pkg-config --cflags libusb-1.0` command shows the
correct include path for installed libusb.
After that you can continue with instructions for lsusb/gousb above.
Contributing
============
Contributing to this project will require signing the [Google CLA][cla].
This is the same agreement that is required for contributing to Go itself, so if you have
already filled it out for that, you needn't fill it out again.
[cla]: https://cla.developers.google.com/

8
vendor/github.com/google/gousb/appveyor.yml generated vendored Normal file
View file

@ -0,0 +1,8 @@
platform: x64
clone_folder: C:\msys64\go\src\github.com\google\gousb
install:
- C:\msys64\usr\bin\bash.exe -lc "cd /go/src/github.com/google/gousb/ && .appveyor/./install.sh"
build: off

140
vendor/github.com/google/gousb/config.go generated vendored Normal file
View file

@ -0,0 +1,140 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
import (
"fmt"
"sync"
)
// ConfigDesc contains the information about a USB device configuration,
// extracted from the device descriptor.
type ConfigDesc struct {
// Number is the configuration number.
Number int
// SelfPowered is true if the device is powered externally, i.e. not
// drawing power from the USB bus.
SelfPowered bool
// RemoteWakeup is true if the device supports remote wakeup, i.e.
// an external signal that will wake up a suspended USB device. An example
// might be a keyboard that can wake up through a keypress after
// the host put it in suspend mode. Note that gousb does not support
// device power management, RemoteWakeup only refers to the reported device
// capability.
RemoteWakeup bool
// MaxPower is the maximum current the device draws from the USB bus
// in this configuration.
MaxPower Milliamperes
// Interfaces has a list of USB interfaces available in this configuration.
Interfaces []InterfaceDesc
iConfiguration int // index of a string descriptor describing this configuration
}
// String returns the human-readable description of the configuration descriptor.
func (c ConfigDesc) String() string {
return fmt.Sprintf("Configuration %d", c.Number)
}
func (c ConfigDesc) intfDesc(num, alt int) (*InterfaceSetting, error) {
if num < 0 || num >= len(c.Interfaces) {
return nil, fmt.Errorf("interface %d not found, available interfaces 0..%d", num, len(c.Interfaces)-1)
}
ifInfo := c.Interfaces[num]
if alt < 0 || alt >= len(ifInfo.AltSettings) {
return nil, fmt.Errorf("alternate setting %d not found for %s, available alt settings 0..%d", alt, ifInfo, len(ifInfo.AltSettings)-1)
}
return &ifInfo.AltSettings[alt], nil
}
// Config represents a USB device set to use a particular configuration.
// Only one Config of a particular device can be used at any one time.
// To access device endpoints, claim an interface and it's alternate
// setting number through a call to Interface().
type Config struct {
Desc ConfigDesc
dev *Device
// Claimed interfaces
mu sync.Mutex
claimed map[int]bool
}
// Close releases the underlying device, allowing the caller to switch the device to a different configuration.
func (c *Config) Close() error {
if c.dev == nil {
return nil
}
c.mu.Lock()
defer c.mu.Unlock()
if len(c.claimed) > 0 {
var ifs []int
for k := range c.claimed {
ifs = append(ifs, k)
}
return fmt.Errorf("failed to release %s, interfaces %v are still open", c, ifs)
}
c.dev.mu.Lock()
defer c.dev.mu.Unlock()
c.dev.claimed = nil
c.dev = nil
return nil
}
// String returns the human-readable description of the configuration.
func (c *Config) String() string {
return fmt.Sprintf("%s,config=%d", c.dev.String(), c.Desc.Number)
}
// Interface claims and returns an interface on a USB device.
// num specifies the number of an interface to claim, and alt specifies the
// alternate setting number for that interface.
func (c *Config) Interface(num, alt int) (*Interface, error) {
if c.dev == nil {
return nil, fmt.Errorf("Interface(%d, %d) called on %s after Close", num, alt, c)
}
altInfo, err := c.Desc.intfDesc(num, alt)
if err != nil {
return nil, fmt.Errorf("descriptor of interface (%d, %d) in %s: %v", num, alt, c, err)
}
c.mu.Lock()
defer c.mu.Unlock()
if c.claimed[num] {
return nil, fmt.Errorf("interface %d on %s is already claimed", num, c)
}
// Claim the interface
if err := c.dev.ctx.libusb.claim(c.dev.handle, uint8(num)); err != nil {
return nil, fmt.Errorf("failed to claim interface %d on %s: %v", num, c, err)
}
// Select an alternate setting if needed (device has multiple alternate settings).
if len(c.Desc.Interfaces[num].AltSettings) > 1 {
if err := c.dev.ctx.libusb.setAlt(c.dev.handle, uint8(num), uint8(alt)); err != nil {
c.dev.ctx.libusb.release(c.dev.handle, uint8(num))
return nil, fmt.Errorf("failed to set alternate config %d on interface %d of %s: %v", alt, num, c, err)
}
}
c.claimed[num] = true
return &Interface{
Setting: *altInfo,
config: c,
}, nil
}

276
vendor/github.com/google/gousb/constants.go generated vendored Normal file
View file

@ -0,0 +1,276 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
// #include <libusb.h>
import "C"
import "strconv"
// Class represents a USB-IF (Implementers Forum) class or subclass code.
type Class uint8
// Standard classes defined by USB spec, see https://www.usb.org/defined-class-codes
const (
ClassPerInterface Class = 0x00
ClassAudio Class = 0x01
ClassComm Class = 0x02
ClassHID Class = 0x03
ClassPhysical Class = 0x05
ClassImage Class = 0x06
ClassPTP Class = ClassImage // legacy name for image
ClassPrinter Class = 0x07
ClassMassStorage Class = 0x08
ClassHub Class = 0x09
ClassData Class = 0x0a
ClassSmartCard Class = 0x0b
ClassContentSecurity Class = 0x0d
ClassVideo Class = 0x0e
ClassPersonalHealthcare Class = 0x0f
ClassAudioVideo Class = 0x10
ClassBillboard Class = 0x11
ClassUSBTypeCBridge Class = 0x12
ClassDiagnosticDevice Class = 0xdc
ClassWireless Class = 0xe0
ClassMiscellaneous Class = 0xef
ClassApplication Class = 0xfe
ClassVendorSpec Class = 0xff
)
var classDescription = map[Class]string{
ClassPerInterface: "per-interface",
ClassAudio: "audio",
ClassComm: "communications",
ClassHID: "human interface device",
ClassPhysical: "physical",
ClassImage: "image",
ClassPrinter: "printer",
ClassMassStorage: "mass storage",
ClassHub: "hub",
ClassData: "data",
ClassSmartCard: "smart card",
ClassContentSecurity: "content security",
ClassVideo: "video",
ClassPersonalHealthcare: "personal healthcare",
ClassAudioVideo: "audio/video",
ClassBillboard: "billboard",
ClassUSBTypeCBridge: "USB type-C bridge",
ClassDiagnosticDevice: "diagnostic device",
ClassWireless: "wireless",
ClassMiscellaneous: "miscellaneous",
ClassApplication: "application-specific",
ClassVendorSpec: "vendor-specific",
}
func (c Class) String() string {
if d, ok := classDescription[c]; ok {
return d
}
return strconv.Itoa(int(c))
}
// Protocol is the interface class protocol, qualified by the values
// of interface class and subclass.
type Protocol uint8
func (p Protocol) String() string {
return strconv.Itoa(int(p))
}
// DescriptorType identifies the type of a USB descriptor.
type DescriptorType uint8
// Descriptor types defined by the USB spec.
const (
DescriptorTypeDevice DescriptorType = C.LIBUSB_DT_DEVICE
DescriptorTypeConfig DescriptorType = C.LIBUSB_DT_CONFIG
DescriptorTypeString DescriptorType = C.LIBUSB_DT_STRING
DescriptorTypeInterface DescriptorType = C.LIBUSB_DT_INTERFACE
DescriptorTypeEndpoint DescriptorType = C.LIBUSB_DT_ENDPOINT
DescriptorTypeHID DescriptorType = C.LIBUSB_DT_HID
DescriptorTypeReport DescriptorType = C.LIBUSB_DT_REPORT
DescriptorTypePhysical DescriptorType = C.LIBUSB_DT_PHYSICAL
DescriptorTypeHub DescriptorType = C.LIBUSB_DT_HUB
)
var descriptorTypeDescription = map[DescriptorType]string{
DescriptorTypeDevice: "device",
DescriptorTypeConfig: "configuration",
DescriptorTypeString: "string",
DescriptorTypeInterface: "interface",
DescriptorTypeEndpoint: "endpoint",
DescriptorTypeHID: "HID",
DescriptorTypeReport: "HID report",
DescriptorTypePhysical: "physical",
DescriptorTypeHub: "hub",
}
func (dt DescriptorType) String() string {
return descriptorTypeDescription[dt]
}
// EndpointDirection defines the direction of data flow - IN (device to host)
// or OUT (host to device).
type EndpointDirection bool
const (
endpointNumMask = 0x0f
endpointDirectionMask = 0x80
// EndpointDirectionIn marks data flowing from device to host.
EndpointDirectionIn EndpointDirection = true
// EndpointDirectionOut marks data flowing from host to device.
EndpointDirectionOut EndpointDirection = false
)
var endpointDirectionDescription = map[EndpointDirection]string{
EndpointDirectionIn: "IN",
EndpointDirectionOut: "OUT",
}
func (ed EndpointDirection) String() string {
return endpointDirectionDescription[ed]
}
// TransferType defines the endpoint transfer type.
type TransferType uint8
// Transfer types defined by the USB spec.
const (
TransferTypeControl TransferType = C.LIBUSB_TRANSFER_TYPE_CONTROL
TransferTypeIsochronous TransferType = C.LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
TransferTypeBulk TransferType = C.LIBUSB_TRANSFER_TYPE_BULK
TransferTypeInterrupt TransferType = C.LIBUSB_TRANSFER_TYPE_INTERRUPT
transferTypeMask = 0x03
)
var transferTypeDescription = map[TransferType]string{
TransferTypeControl: "control",
TransferTypeIsochronous: "isochronous",
TransferTypeBulk: "bulk",
TransferTypeInterrupt: "interrupt",
}
// String returns a human-readable name of the endpoint transfer type.
func (tt TransferType) String() string {
return transferTypeDescription[tt]
}
// IsoSyncType defines the isochronous transfer synchronization type.
type IsoSyncType uint8
// Synchronization types defined by the USB spec.
const (
IsoSyncTypeNone IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_NONE << 2
IsoSyncTypeAsync IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ASYNC << 2
IsoSyncTypeAdaptive IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_ADAPTIVE << 2
IsoSyncTypeSync IsoSyncType = C.LIBUSB_ISO_SYNC_TYPE_SYNC << 2
isoSyncTypeMask = 0x0C
)
var isoSyncTypeDescription = map[IsoSyncType]string{
IsoSyncTypeNone: "unsynchronized",
IsoSyncTypeAsync: "asynchronous",
IsoSyncTypeAdaptive: "adaptive",
IsoSyncTypeSync: "synchronous",
}
// String returns a human-readable description of the synchronization type.
func (ist IsoSyncType) String() string {
return isoSyncTypeDescription[ist]
}
// UsageType defines the transfer usage type for isochronous and interrupt
// transfers.
type UsageType uint8
// Usage types for iso and interrupt transfers, defined by the USB spec.
const (
// Note: USB3.0 defines usage type for both isochronous and interrupt
// endpoints, with the same constants representing different usage types.
// UsageType constants do not correspond to bmAttribute values.
UsageTypeUndefined UsageType = iota
IsoUsageTypeData
IsoUsageTypeFeedback
IsoUsageTypeImplicit
InterruptUsageTypePeriodic
InterruptUsageTypeNotification
usageTypeMask = 0x30
)
var usageTypeDescription = map[UsageType]string{
UsageTypeUndefined: "undefined usage",
IsoUsageTypeData: "data",
IsoUsageTypeFeedback: "feedback",
IsoUsageTypeImplicit: "implicit data",
InterruptUsageTypePeriodic: "periodic",
InterruptUsageTypeNotification: "notification",
}
func (ut UsageType) String() string {
return usageTypeDescription[ut]
}
// Control request type bit fields as defined in the USB spec. All values are
// of uint8 type. These constants can be used with Device.Control() method to
// specify the type and destination of the control request, e.g.
// `dev.Control(ControlOut|ControlVendor|ControlDevice, ...)`.
const (
ControlIn = C.LIBUSB_ENDPOINT_IN
ControlOut = C.LIBUSB_ENDPOINT_OUT
// "Standard" is explicitly omitted, as functionality of standard requests
// is exposed through higher level operations of gousb.
ControlClass = C.LIBUSB_REQUEST_TYPE_CLASS
ControlVendor = C.LIBUSB_REQUEST_TYPE_VENDOR
// "Reserved" is explicitly omitted, should not be used.
ControlDevice = C.LIBUSB_RECIPIENT_DEVICE
ControlInterface = C.LIBUSB_RECIPIENT_INTERFACE
ControlEndpoint = C.LIBUSB_RECIPIENT_ENDPOINT
ControlOther = C.LIBUSB_RECIPIENT_OTHER
)
// Speed identifies the speed of the device.
type Speed int
// Device speeds as defined in the USB spec.
const (
SpeedUnknown Speed = C.LIBUSB_SPEED_UNKNOWN
SpeedLow Speed = C.LIBUSB_SPEED_LOW
SpeedFull Speed = C.LIBUSB_SPEED_FULL
SpeedHigh Speed = C.LIBUSB_SPEED_HIGH
SpeedSuper Speed = C.LIBUSB_SPEED_SUPER
)
var deviceSpeedDescription = map[Speed]string{
SpeedUnknown: "unknown",
SpeedLow: "low",
SpeedFull: "full",
SpeedHigh: "high",
SpeedSuper: "super",
}
// String returns a human-readable name of the device speed.
func (s Speed) String() string {
return deviceSpeedDescription[s]
}
const (
selfPoweredMask = 0x40
remoteWakeupMask = 0x20
)
// Milliamperes is a unit of electric current consumption.
type Milliamperes uint

37
vendor/github.com/google/gousb/debug.go generated vendored Normal file
View file

@ -0,0 +1,37 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
// To enable internal debugging, set the GOUSB_DEBUG environment variable.
import (
"io"
"io/ioutil"
"log" // TODO(kevlar): make a logger
"os"
)
var debug *log.Logger
const debugEnvVarName = "GOUSB_DEBUG"
func init() {
out := io.Writer(ioutil.Discard)
if os.Getenv(debugEnvVarName) != "" {
out = os.Stderr
}
debug = log.New(out, "gousb: ", log.LstdFlags|log.Lshortfile)
}

289
vendor/github.com/google/gousb/device.go generated vendored Normal file
View file

@ -0,0 +1,289 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
import (
"fmt"
"sort"
"sync"
"time"
)
// DeviceDesc is a representation of a USB device descriptor.
type DeviceDesc struct {
// Bus information
Bus int // The bus on which the device was detected
Address int // The address of the device on the bus
Speed Speed // The negotiated operating speed for the device
Port int // The usb port on which the device was detected
// Version information
Spec BCD // USB Specification Release Number
Device BCD // The device version
// Product information
Vendor ID // The Vendor identifer
Product ID // The Product identifier
// Protocol information
Class Class // The class of this device
SubClass Class // The sub-class (within the class) of this device
Protocol Protocol // The protocol (within the sub-class) of this device
MaxControlPacketSize int // Maximum size of the control transfer
// Configuration information
Configs map[int]ConfigDesc
iManufacturer int // The Manufacturer descriptor index
iProduct int // The Product descriptor index
iSerialNumber int // The SerialNumber descriptor index
}
// String returns a human-readable version of the device descriptor.
func (d *DeviceDesc) String() string {
return fmt.Sprintf("%d.%d: %s:%s (available configs: %v)", d.Bus, d.Address, d.Vendor, d.Product, d.sortedConfigIds())
}
func (d *DeviceDesc) sortedConfigIds() []int {
var cfgs []int
for c := range d.Configs {
cfgs = append(cfgs, c)
}
sort.Ints(cfgs)
return cfgs
}
func (d *DeviceDesc) cfgDesc(cfgNum int) (*ConfigDesc, error) {
desc, ok := d.Configs[cfgNum]
if !ok {
return nil, fmt.Errorf("configuration id %d not found in the descriptor of the device. Available config ids: %v", cfgNum, d.sortedConfigIds())
}
return &desc, nil
}
// Device represents an opened USB device.
// Device allows sending USB control commands through the Command() method.
// For data transfers select a device configuration through a call to
// Config().
// A Device must be Close()d after use.
type Device struct {
handle *libusbDevHandle
ctx *Context
// Embed the device information for easy access
Desc *DeviceDesc
// Timeout for control commands
ControlTimeout time.Duration
// Claimed config
mu sync.Mutex
claimed *Config
// Handle AutoDetach in this library
autodetach bool
}
// String represents a human readable representation of the device.
func (d *Device) String() string {
return fmt.Sprintf("vid=%s,pid=%s,bus=%d,addr=%d", d.Desc.Vendor, d.Desc.Product, d.Desc.Bus, d.Desc.Address)
}
// Reset performs a USB port reset to reinitialize a device.
func (d *Device) Reset() error {
if d.handle == nil {
return fmt.Errorf("Reset() called on %s after Close", d)
}
d.mu.Lock()
defer d.mu.Unlock()
if d.claimed != nil {
return fmt.Errorf("can't reset device %s while it has an active configuration %s", d, d.claimed)
}
return d.ctx.libusb.reset(d.handle)
}
// ActiveConfigNum returns the config id of the active configuration.
// The value corresponds to the ConfigInfo.Config field of one of the
// ConfigInfos of this Device.
func (d *Device) ActiveConfigNum() (int, error) {
if d.handle == nil {
return 0, fmt.Errorf("ActiveConfig() called on %s after Close", d)
}
ret, err := d.ctx.libusb.getConfig(d.handle)
return int(ret), err
}
// Config returns a USB device set to use a particular config.
// The cfgNum provided is the config id (not the index) of the configuration to
// set, which corresponds to the ConfigInfo.Config field.
// USB supports only one active config per device at a time. Config claims the
// device before setting the desired config and keeps it locked until Close is
// called.
// A claimed config needs to be Close()d after use.
func (d *Device) Config(cfgNum int) (*Config, error) {
if d.handle == nil {
return nil, fmt.Errorf("Config(%d) called on %s after Close", cfgNum, d)
}
desc, err := d.Desc.cfgDesc(cfgNum)
if err != nil {
return nil, fmt.Errorf("device %s: %v", d, err)
}
cfg := &Config{
Desc: *desc,
dev: d,
claimed: make(map[int]bool),
}
if d.autodetach {
for _, iface := range cfg.Desc.Interfaces {
if err := d.ctx.libusb.detachKernelDriver(d.handle, uint8(iface.Number)); err != nil {
return nil, fmt.Errorf("Can't detach kernel driver of the device %s and interface %d: %v", d, iface.Number, err)
}
}
}
if activeCfgNum, err := d.ActiveConfigNum(); err != nil {
return nil, fmt.Errorf("failed to query active config of the device %s: %v", d, err)
} else if cfgNum != activeCfgNum {
if err := d.ctx.libusb.setConfig(d.handle, uint8(cfgNum)); err != nil {
return nil, fmt.Errorf("failed to set active config %d for the device %s: %v", cfgNum, d, err)
}
}
d.mu.Lock()
defer d.mu.Unlock()
d.claimed = cfg
return cfg, nil
}
// DefaultInterface opens interface #0 with alternate setting #0 of the currently active
// config. It's intended as a shortcut for devices that have the simplest
// interface of a single config, interface and alternate setting.
// The done func should be called to release the claimed interface and config.
func (d *Device) DefaultInterface() (intf *Interface, done func(), err error) {
cfgNum, err := d.ActiveConfigNum()
if err != nil {
return nil, nil, fmt.Errorf("failed to get active config number of device %s: %v", d, err)
}
cfg, err := d.Config(cfgNum)
if err != nil {
return nil, nil, fmt.Errorf("failed to claim config %d of device %s: %v", cfgNum, d, err)
}
i, err := cfg.Interface(0, 0)
if err != nil {
cfg.Close()
return nil, nil, fmt.Errorf("failed to select interface #%d alternate setting %d of config %d of device %s: %v", 0, 0, cfgNum, d, err)
}
return i, func() {
intf.Close()
cfg.Close()
}, nil
}
// Control sends a control request to the device.
func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error) {
if d.handle == nil {
return 0, fmt.Errorf("Control() called on %s after Close", d)
}
return d.ctx.libusb.control(d.handle, d.ControlTimeout, rType, request, val, idx, data)
}
// Close closes the device.
func (d *Device) Close() error {
if d.handle == nil {
return nil
}
d.mu.Lock()
defer d.mu.Unlock()
if d.claimed != nil {
return fmt.Errorf("can't release the device %s, it has an open config %d", d, d.claimed.Desc.Number)
}
d.ctx.libusb.close(d.handle)
d.handle = nil
return nil
}
// GetStringDescriptor returns a device string descriptor with the given index
// number. The first supported language is always used and the returned
// descriptor string is converted to ASCII (non-ASCII characters are replaced
// with "?").
func (d *Device) GetStringDescriptor(descIndex int) (string, error) {
if d.handle == nil {
return "", fmt.Errorf("GetStringDescriptor(%d) called on %s after Close", descIndex, d)
}
// string descriptor index value of 0 indicates no string descriptor.
if descIndex == 0 {
return "", nil
}
return d.ctx.libusb.getStringDesc(d.handle, descIndex)
}
// Manufacturer returns the device's manufacturer name.
// GetStringDescriptor's string conversion rules apply.
func (d *Device) Manufacturer() (string, error) {
return d.GetStringDescriptor(d.Desc.iManufacturer)
}
// Product returns the device's product name.
// GetStringDescriptor's string conversion rules apply.
func (d *Device) Product() (string, error) {
return d.GetStringDescriptor(d.Desc.iProduct)
}
// SerialNumber returns the device's serial number.
// GetStringDescriptor's string conversion rules apply.
func (d *Device) SerialNumber() (string, error) {
return d.GetStringDescriptor(d.Desc.iSerialNumber)
}
// ConfigDescription returns the description of the selected device
// configuration. GetStringDescriptor's string conversion rules apply.
func (d *Device) ConfigDescription(cfg int) (string, error) {
c, err := d.Desc.cfgDesc(cfg)
if err != nil {
return "", fmt.Errorf("%s: %v", d, err)
}
return d.GetStringDescriptor(c.iConfiguration)
}
// InterfaceDescription returns the description of the selected interface and
// its alternate setting in a selected configuration. GetStringDescriptor's
// string conversion rules apply.
func (d *Device) InterfaceDescription(cfgNum, intfNum, altNum int) (string, error) {
cfg, err := d.Desc.cfgDesc(cfgNum)
if err != nil {
return "", fmt.Errorf("%s: %v", d, err)
}
alt, err := cfg.intfDesc(intfNum, altNum)
if err != nil {
return "", fmt.Errorf("%s, configuration %d: %v", d, cfgNum, err)
}
return d.GetStringDescriptor(alt.iInterface)
}
// SetAutoDetach enables/disables automatic kernel driver detachment.
// When autodetach is enabled gousb will automatically detach the kernel driver
// on the interface and reattach it when releasing the interface.
// Automatic kernel driver detachment is disabled on newly opened device handles by default.
func (d *Device) SetAutoDetach(autodetach bool) error {
if d.handle == nil {
return fmt.Errorf("SetAutoDetach(%v) called on %s after Close", autodetach, d)
}
d.autodetach = autodetach
var autodetachInt int
if autodetach {
autodetachInt = 1
}
return d.ctx.libusb.setAutoDetach(d.handle, autodetachInt)
}

161
vendor/github.com/google/gousb/endpoint.go generated vendored Normal file
View file

@ -0,0 +1,161 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
import (
"context"
"fmt"
"strings"
"time"
)
// EndpointAddress is a unique identifier for the endpoint, combining the endpoint number and direction.
type EndpointAddress uint8
// String implements the Stringer interface.
func (a EndpointAddress) String() string {
return fmt.Sprintf("0x%02x", uint8(a))
}
// EndpointDesc contains the information about an interface endpoint, extracted
// from the descriptor.
type EndpointDesc struct {
// Address is the unique identifier of the endpoint within the interface.
Address EndpointAddress
// Number represents the endpoint number. Note that the endpoint number is different from the
// address field in the descriptor - address 0x82 means endpoint number 2,
// with endpoint direction IN.
// The device can have up to two endpoints with the same number but with
// different directions.
Number int
// Direction defines whether the data is flowing IN or OUT from the host perspective.
Direction EndpointDirection
// MaxPacketSize is the maximum USB packet size for a single frame/microframe.
MaxPacketSize int
// TransferType defines the endpoint type - bulk, interrupt, isochronous.
TransferType TransferType
// PollInterval is the maximum time between transfers for interrupt and isochronous transfer,
// or the NAK interval for a control transfer. See endpoint descriptor bInterval documentation
// in the USB spec for details.
PollInterval time.Duration
// IsoSyncType is the isochronous endpoint synchronization type, as defined by USB spec.
IsoSyncType IsoSyncType
// UsageType is the isochronous or interrupt endpoint usage type, as defined by USB spec.
UsageType UsageType
}
// String returns the human-readable description of the endpoint.
func (e EndpointDesc) String() string {
ret := make([]string, 0, 3)
ret = append(ret, fmt.Sprintf("ep #%d %s (address %s) %s", e.Number, e.Direction, e.Address, e.TransferType))
switch e.TransferType {
case TransferTypeIsochronous:
ret = append(ret, fmt.Sprintf("- %s %s", e.IsoSyncType, e.UsageType))
case TransferTypeInterrupt:
ret = append(ret, fmt.Sprintf("- %s", e.UsageType))
}
ret = append(ret, fmt.Sprintf("[%d bytes]", e.MaxPacketSize))
return strings.Join(ret, " ")
}
type endpoint struct {
h *libusbDevHandle
InterfaceSetting
Desc EndpointDesc
ctx *Context
}
// String returns a human-readable description of the endpoint.
func (e *endpoint) String() string {
return e.Desc.String()
}
func (e *endpoint) transfer(ctx context.Context, buf []byte) (int, error) {
if len(buf) == 0 {
return 0, nil
}
t, err := newUSBTransfer(e.ctx, e.h, &e.Desc, len(buf))
if err != nil {
return 0, err
}
defer t.free()
if e.Desc.Direction == EndpointDirectionOut {
copy(t.data(), buf)
}
if err := t.submit(); err != nil {
return 0, err
}
n, err := t.wait(ctx)
if e.Desc.Direction == EndpointDirectionIn {
copy(buf, t.data())
}
if err != nil {
return n, err
}
return n, nil
}
// InEndpoint represents an IN endpoint open for transfer.
// InEndpoint implements the io.Reader interface.
// For high-throughput transfers, consider creating a bufffered read stream
// through InEndpoint.ReadStream.
type InEndpoint struct {
*endpoint
}
// Read reads data from an IN endpoint. Read returns number of bytes obtained
// from the endpoint. Read may return non-zero length even if
// the returned error is not nil (partial read).
func (e *InEndpoint) Read(buf []byte) (int, error) {
return e.transfer(context.Background(), buf)
}
// ReadContext reads data from an IN endpoint. ReadContext returns number of
// bytes obtained from the endpoint. ReadContext may return non-zero length
// even if the returned error is not nil (partial read).
// The passed context can be used to control the cancellation of the read. If
// the context is cancelled, ReadContext will cancel the underlying transfers,
// resulting in TransferCancelled error.
func (e *InEndpoint) ReadContext(ctx context.Context, buf []byte) (int, error) {
return e.transfer(ctx, buf)
}
// OutEndpoint represents an OUT endpoint open for transfer.
type OutEndpoint struct {
*endpoint
}
// Write writes data to an OUT endpoint. Write returns number of bytes comitted
// to the endpoint. Write may return non-zero length even if the returned error
// is not nil (partial write).
func (e *OutEndpoint) Write(buf []byte) (int, error) {
return e.transfer(context.Background(), buf)
}
// WriteContext writes data to an OUT endpoint. WriteContext returns number of
// bytes comitted to the endpoint. WriteContext may return non-zero length even
// if the returned error is not nil (partial write).
// The passed context can be used to control the cancellation of the write. If
// the context is cancelled, WriteContext will cancel the underlying transfers,
// resulting in TransferCancelled error.
func (e *OutEndpoint) WriteContext(ctx context.Context, buf []byte) (int, error) {
return e.transfer(ctx, buf)
}

58
vendor/github.com/google/gousb/endpoint_stream.go generated vendored Normal file
View file

@ -0,0 +1,58 @@
// Copyright 2017 the gousb Authors. 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 gousb
func (e *endpoint) newStream(size, count int) (*stream, error) {
var ts []transferIntf
for i := 0; i < count; i++ {
t, err := newUSBTransfer(e.ctx, e.h, &e.Desc, size)
if err != nil {
for _, t := range ts {
t.free()
}
return nil, err
}
ts = append(ts, t)
}
return newStream(ts), nil
}
// NewStream prepares a new read stream that will keep reading data from
// the endpoint until closed or until an error or timeout is encountered.
// Size defines a buffer size for a single read transaction and count
// defines how many transactions should be active at any time.
// By keeping multiple transfers active at the same time, a Stream reduces
// the latency between subsequent transfers and increases reading throughput.
func (e *InEndpoint) NewStream(size, count int) (*ReadStream, error) {
s, err := e.newStream(size, count)
if err != nil {
return nil, err
}
s.submitAll()
return &ReadStream{s: s}, nil
}
// NewStream prepares a new write stream that will write data in the
// background. Size defines a buffer size for a single write transaction and
// count defines how many transactions may be active at any time. By buffering
// the writes, a Stream reduces the latency between subsequent transfers and
// increases writing throughput.
func (e *OutEndpoint) NewStream(size, count int) (*WriteStream, error) {
s, err := e.newStream(size, count)
if err != nil {
return nil, err
}
return &WriteStream{s: s}, nil
}

110
vendor/github.com/google/gousb/error.go generated vendored Normal file
View file

@ -0,0 +1,110 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
import (
"fmt"
)
// #include <libusb.h>
import "C"
// Error is an error code from a USB operation. See the list of Error constants below.
type Error C.int
// Error implements the error interface.
func (e Error) Error() string {
return fmt.Sprintf("libusb: %s [code %d]", errorString[e], e)
}
func fromErrNo(errno C.int) error {
err := Error(errno)
if err == Success {
return nil
}
return err
}
// Defined result codes.
const (
Success Error = C.LIBUSB_SUCCESS
ErrorIO Error = C.LIBUSB_ERROR_IO
ErrorInvalidParam Error = C.LIBUSB_ERROR_INVALID_PARAM
ErrorAccess Error = C.LIBUSB_ERROR_ACCESS
ErrorNoDevice Error = C.LIBUSB_ERROR_NO_DEVICE
ErrorNotFound Error = C.LIBUSB_ERROR_NOT_FOUND
ErrorBusy Error = C.LIBUSB_ERROR_BUSY
ErrorTimeout Error = C.LIBUSB_ERROR_TIMEOUT
// ErrorOverflow indicates that the device tried to send more data than was
// requested and that could fit in the packet buffer.
ErrorOverflow Error = C.LIBUSB_ERROR_OVERFLOW
ErrorPipe Error = C.LIBUSB_ERROR_PIPE
ErrorInterrupted Error = C.LIBUSB_ERROR_INTERRUPTED
ErrorNoMem Error = C.LIBUSB_ERROR_NO_MEM
ErrorNotSupported Error = C.LIBUSB_ERROR_NOT_SUPPORTED
ErrorOther Error = C.LIBUSB_ERROR_OTHER
)
var errorString = map[Error]string{
Success: "success",
ErrorIO: "i/o error",
ErrorInvalidParam: "invalid param",
ErrorAccess: "bad access",
ErrorNoDevice: "no device",
ErrorNotFound: "not found",
ErrorBusy: "device or resource busy",
ErrorTimeout: "timeout",
ErrorOverflow: "overflow",
ErrorPipe: "pipe error",
ErrorInterrupted: "interrupted",
ErrorNoMem: "out of memory",
ErrorNotSupported: "not supported",
ErrorOther: "unknown error",
}
// TransferStatus contains information about the result of a transfer.
type TransferStatus uint8
// Defined Transfer status values.
const (
TransferCompleted TransferStatus = C.LIBUSB_TRANSFER_COMPLETED
TransferError TransferStatus = C.LIBUSB_TRANSFER_ERROR
TransferTimedOut TransferStatus = C.LIBUSB_TRANSFER_TIMED_OUT
TransferCancelled TransferStatus = C.LIBUSB_TRANSFER_CANCELLED
TransferStall TransferStatus = C.LIBUSB_TRANSFER_STALL
TransferNoDevice TransferStatus = C.LIBUSB_TRANSFER_NO_DEVICE
TransferOverflow TransferStatus = C.LIBUSB_TRANSFER_OVERFLOW
)
var transferStatusDescription = map[TransferStatus]string{
TransferCompleted: "transfer completed without error",
TransferError: "transfer failed",
TransferTimedOut: "transfer timed out",
TransferCancelled: "transfer was cancelled",
TransferStall: "halt condition detected (endpoint stalled) or control request not supported",
TransferNoDevice: "device was disconnected",
TransferOverflow: "device sent more data than requested",
}
// String returns a human-readable transfer status.
func (ts TransferStatus) String() string {
return transferStatusDescription[ts]
}
// Error implements the error interface.
func (ts TransferStatus) Error() string {
return ts.String()
}

220
vendor/github.com/google/gousb/fakelibusb_devices.go generated vendored Normal file
View file

@ -0,0 +1,220 @@
// Copyright 2017 the gousb Authors. 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 gousb
// fake devices connected through the fakeLibusb stack.
type fakeDevice struct {
devDesc *DeviceDesc
strDesc map[int]string
alt uint8
}
var fakeDevices = []fakeDevice{
// Bus 001 Device 001: ID 9999:0001
// One config, one interface, one setup,
// two endpoints: 0x01 OUT, 0x82 IN.
{
devDesc: &DeviceDesc{
Bus: 1,
Address: 1,
Port: 1,
Spec: Version(2, 0),
Device: Version(1, 0),
Vendor: ID(0x9999),
Product: ID(0x0001),
Protocol: 255,
Configs: map[int]ConfigDesc{1: {
Number: 1,
MaxPower: Milliamperes(100),
Interfaces: []InterfaceDesc{{
Number: 0,
AltSettings: []InterfaceSetting{{
Number: 0,
Alternate: 0,
Class: ClassVendorSpec,
Endpoints: map[EndpointAddress]EndpointDesc{
0x01: {
Address: 0x01,
Number: 1,
Direction: EndpointDirectionOut,
MaxPacketSize: 512,
TransferType: TransferTypeBulk,
},
0x82: {
Address: 0x82,
Number: 2,
Direction: EndpointDirectionIn,
MaxPacketSize: 512,
TransferType: TransferTypeBulk,
},
},
}},
}},
}},
},
},
// Bus 001 Device 002: ID 8888:0002
// One config, two interfaces. interface #0 with no endpoints,
// interface #1 with two alt setups with different packet sizes for
// endpoints. Two isochronous endpoints, 0x05 OUT and 0x86 OUT.
{
devDesc: &DeviceDesc{
Bus: 1,
Address: 2,
Port: 2,
Spec: Version(2, 0),
Device: Version(1, 3),
Vendor: ID(0x8888),
Product: ID(0x0002),
Protocol: 255,
Configs: map[int]ConfigDesc{1: {
Number: 1,
MaxPower: Milliamperes(100),
iConfiguration: 5,
Interfaces: []InterfaceDesc{{
Number: 0,
AltSettings: []InterfaceSetting{{
Number: 0,
Alternate: 0,
Class: ClassVendorSpec,
iInterface: 6,
}},
}, {
Number: 1,
AltSettings: []InterfaceSetting{{
Number: 1,
Alternate: 0,
Class: ClassVendorSpec,
Endpoints: map[EndpointAddress]EndpointDesc{
0x05: {
Address: 0x05,
Number: 5,
Direction: EndpointDirectionOut,
MaxPacketSize: 3 * 1024,
TransferType: TransferTypeIsochronous,
UsageType: IsoUsageTypeData,
},
0x86: {
Address: 0x86,
Number: 6,
Direction: EndpointDirectionIn,
MaxPacketSize: 3 * 1024,
TransferType: TransferTypeIsochronous,
UsageType: IsoUsageTypeData,
},
},
iInterface: 7,
}, {
Number: 1,
Alternate: 1,
Class: ClassVendorSpec,
Endpoints: map[EndpointAddress]EndpointDesc{
0x05: {
Address: 0x05,
Number: 5,
Direction: EndpointDirectionOut,
MaxPacketSize: 2 * 1024,
TransferType: TransferTypeIsochronous,
},
0x86: {
Address: 0x86,
Number: 6,
Direction: EndpointDirectionIn,
MaxPacketSize: 2 * 1024,
TransferType: TransferTypeIsochronous,
},
},
iInterface: 8,
}, {
Number: 1,
Alternate: 2,
Class: ClassVendorSpec,
Endpoints: map[EndpointAddress]EndpointDesc{
0x05: {
Address: 0x05,
Number: 5,
Direction: EndpointDirectionIn,
MaxPacketSize: 1024,
TransferType: TransferTypeIsochronous,
},
0x86: {
Address: 0x86,
Number: 6,
Direction: EndpointDirectionIn,
MaxPacketSize: 1024,
TransferType: TransferTypeIsochronous,
},
},
}},
}},
}},
iManufacturer: 1,
iProduct: 2,
iSerialNumber: 3,
},
strDesc: map[int]string{
1: "ACME Industries",
2: "Fidgety Gadget",
3: "01234567",
5: "Weird configuration",
6: "Boring setting",
7: "Fast streaming",
8: "Slower streaming",
},
},
// Bus 001 Device 003: ID 9999:0002
// One config, one interface, one setup,
// two endpoints: 0x01 OUT, 0x81 IN.
{
devDesc: &DeviceDesc{
Bus: 1,
Address: 3,
Port: 3,
Spec: Version(2, 0),
Device: Version(1, 0),
Vendor: ID(0x1111),
Product: ID(0x1111),
Protocol: 255,
Configs: map[int]ConfigDesc{1: {
Number: 1,
MaxPower: Milliamperes(100),
Interfaces: []InterfaceDesc{{
Number: 0,
AltSettings: []InterfaceSetting{{
Number: 0,
Alternate: 0,
Class: ClassVendorSpec,
Endpoints: map[EndpointAddress]EndpointDesc{
0x01: {
Address: 0x01,
Number: 1,
Direction: EndpointDirectionOut,
MaxPacketSize: 512,
TransferType: TransferTypeBulk,
},
0x81: {
Address: 0x81,
Number: 1,
Direction: EndpointDirectionIn,
MaxPacketSize: 512,
TransferType: TransferTypeBulk,
},
},
}},
}},
}},
},
},
}

29
vendor/github.com/google/gousb/fixlibusb_darwin.sh generated vendored Executable file
View file

@ -0,0 +1,29 @@
#!/bin/bash
function die {
echo "$@"
exit 1
}
FILE="$1"
if [[ -z "$FILE" ]]; then
die "Usage: $0 <path to libusb.h>"
fi
if [[ $(gcc --version | grep -i "llvm") == "" ]]; then
die "Error: This change is unnecessary unless your gcc uses llvm"
fi
BACKUP="${FILE}.orig"
if [[ -f "$BACKUP" ]]; then
die "It looks like you've already run this script ($BACKUP exists)"
fi
cp $FILE $BACKUP || die "Could not create backup"
{
echo 'H' # Turn on error printing
echo 'g/\[0\].*non-standard/s/\[0\]/[1]/' # Use [1] instead of [0] so the size is unambiguous
echo 'g/\[.\].*non-standard/p' # Print the lines changed
echo 'w' # Write output
} | ed $FILE

139
vendor/github.com/google/gousb/interface.go generated vendored Normal file
View file

@ -0,0 +1,139 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
import (
"fmt"
"sort"
)
// InterfaceDesc contains information about a USB interface, extracted from
// the descriptor.
type InterfaceDesc struct {
// Number is the number of this interface, a zero-based index in the array
// of interfaces supported by the device configuration.
Number int
// AltSettings is a list of alternate settings supported by the interface.
AltSettings []InterfaceSetting
}
// String returns a human-readable description of the interface descriptor and
// its alternate settings.
func (i InterfaceDesc) String() string {
return fmt.Sprintf("Interface %d (%d alternate settings)", i.Number, len(i.AltSettings))
}
// InterfaceSetting contains information about a USB interface with a particular
// alternate setting, extracted from the descriptor.
type InterfaceSetting struct {
// Number is the number of this interface, the same as in InterfaceDesc.
Number int
// Alternate is the number of this alternate setting.
Alternate int
// Class is the USB-IF (Implementers Forum) class code, as defined by the USB spec.
Class Class
// SubClass is the USB-IF (Implementers Forum) subclass code, as defined by the USB spec.
SubClass Class
// Protocol is USB protocol code, as defined by the USB spe.c
Protocol Protocol
// Endpoints enumerates the endpoints available on this interface with
// this alternate setting.
Endpoints map[EndpointAddress]EndpointDesc
iInterface int // index of a string descriptor describing this interface.
}
func (a InterfaceSetting) sortedEndpointIds() []string {
var eps []string
for _, ei := range a.Endpoints {
eps = append(eps, fmt.Sprintf("%s(%d,%s)", ei.Address, ei.Number, ei.Direction))
}
sort.Strings(eps)
return eps
}
// String returns a human-readable description of the particular
// alternate setting of an interface.
func (a InterfaceSetting) String() string {
return fmt.Sprintf("Interface %d alternate setting %d (available endpoints: %v)", a.Number, a.Alternate, a.sortedEndpointIds())
}
// Interface is a representation of a claimed interface with a particular setting.
// To access device endpoints use InEndpoint() and OutEndpoint() methods.
// The interface should be Close()d after use.
type Interface struct {
Setting InterfaceSetting
config *Config
}
func (i *Interface) String() string {
return fmt.Sprintf("%s,if=%d,alt=%d", i.config, i.Setting.Number, i.Setting.Alternate)
}
// Close releases the interface.
func (i *Interface) Close() {
if i.config == nil {
return
}
i.config.dev.ctx.libusb.release(i.config.dev.handle, uint8(i.Setting.Number))
i.config.mu.Lock()
defer i.config.mu.Unlock()
delete(i.config.claimed, i.Setting.Number)
i.config = nil
}
func (i *Interface) openEndpoint(epAddr EndpointAddress) (*endpoint, error) {
var ep EndpointDesc
ep, ok := i.Setting.Endpoints[epAddr]
if !ok {
return nil, fmt.Errorf("%s does not have endpoint with address %s. Available endpoints: %v", i, epAddr, i.Setting.sortedEndpointIds())
}
return &endpoint{
InterfaceSetting: i.Setting,
Desc: ep,
h: i.config.dev.handle,
ctx: i.config.dev.ctx,
}, nil
}
// InEndpoint prepares an IN endpoint for transfer.
func (i *Interface) InEndpoint(epNum int) (*InEndpoint, error) {
if i.config == nil {
return nil, fmt.Errorf("InEndpoint(%d) called on %s after Close", epNum, i)
}
ep, err := i.openEndpoint(EndpointAddress(0x80 | epNum))
if err != nil {
return nil, err
}
return &InEndpoint{
endpoint: ep,
}, nil
}
// OutEndpoint prepares an OUT endpoint for transfer.
func (i *Interface) OutEndpoint(epNum int) (*OutEndpoint, error) {
if i.config == nil {
return nil, fmt.Errorf("OutEndpoint(%d) called on %s after Close", epNum, i)
}
ep, err := i.openEndpoint(EndpointAddress(epNum))
if err != nil {
return nil, err
}
return &OutEndpoint{
endpoint: ep,
}, nil
}

511
vendor/github.com/google/gousb/libusb.go generated vendored Normal file
View file

@ -0,0 +1,511 @@
// Copyright 2017 the gousb Authors. 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 gousb
import (
"fmt"
"log"
"reflect"
"sync"
"time"
"unsafe"
)
/*
#cgo pkg-config: libusb-1.0
#include <libusb.h>
int gousb_compact_iso_data(struct libusb_transfer *xfer, unsigned char *status);
struct libusb_transfer *gousb_alloc_transfer_and_buffer(int bufLen, int numIsoPackets);
void gousb_free_transfer_and_buffer(struct libusb_transfer *xfer);
int submit(struct libusb_transfer *xfer);
void gousb_set_debug(libusb_context *ctx, int lvl);
*/
import "C"
type libusbContext C.libusb_context
type libusbDevice C.libusb_device
type libusbDevHandle C.libusb_device_handle
type libusbTransfer C.struct_libusb_transfer
type libusbEndpoint C.struct_libusb_endpoint_descriptor
func (ep libusbEndpoint) endpointDesc(dev *DeviceDesc) EndpointDesc {
ei := EndpointDesc{
Address: EndpointAddress(ep.bEndpointAddress),
Number: int(ep.bEndpointAddress & endpointNumMask),
Direction: EndpointDirection((ep.bEndpointAddress & endpointDirectionMask) != 0),
TransferType: TransferType(ep.bmAttributes & transferTypeMask),
MaxPacketSize: int(ep.wMaxPacketSize),
}
if ei.TransferType == TransferTypeIsochronous {
// 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.
// See http://libusb.org/ticket/77 for more background.
ei.MaxPacketSize = int(ep.wMaxPacketSize) & 0x07ff * (int(ep.wMaxPacketSize)>>11&3 + 1)
ei.IsoSyncType = IsoSyncType(ep.bmAttributes & isoSyncTypeMask)
switch ep.bmAttributes & usageTypeMask {
case C.LIBUSB_ISO_USAGE_TYPE_DATA:
ei.UsageType = IsoUsageTypeData
case C.LIBUSB_ISO_USAGE_TYPE_FEEDBACK:
ei.UsageType = IsoUsageTypeFeedback
case C.LIBUSB_ISO_USAGE_TYPE_IMPLICIT:
ei.UsageType = IsoUsageTypeImplicit
}
}
switch {
// If the device conforms to USB1.x:
// Interval for polling endpoint for data transfers. Expressed in
// milliseconds.
// This field is ignored for bulk and control endpoints. For
// isochronous endpoints this field must be set to 1. For interrupt
// endpoints, this field may range from 1 to 255.
// Note: in low-speed mode, isochronous transfers are not supported.
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
// frames (1ms)
// For full-speed isochronous endpoints, the value of this field should
// be 1.
// For full-/low-speed interrupt endpoints, the value of this field may
// be from 1 to 255.
// Note: in low-speed mode, isochronous transfers are not supported.
case dev.Speed == SpeedUnknown || dev.Speed == SpeedLow || dev.Speed == SpeedFull:
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
// 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
// bInterval number of microframes. This value must be in the range
// from 0 to 255.
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
// 125-µs units.
// For Enhanced SuperSpeed isochronous and interrupt endpoints, this
// 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
// 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) → 2^3 → 8).
// This field is reserved and shall not be used for Enhanced SuperSpeed
// bulk or control endpoints.
case dev.Speed == SpeedHigh || dev.Speed == SpeedSuper:
ei.PollInterval = 125 * time.Microsecond << (ep.bInterval - 1)
}
return ei
}
// libusbIntf is a set of trivial idiomatic Go wrappers around libusb C functions.
// The underlying code is generally not testable or difficult to test,
// since libusb interacts directly with the host USB stack.
//
// All functions here should operate on types defined on C.libusb* data types,
// and occasionally on convenience data types (like TransferType or DeviceDesc).
type libusbIntf interface {
// context
init() (*libusbContext, error)
handleEvents(*libusbContext, <-chan struct{})
getDevices(*libusbContext) ([]*libusbDevice, error)
exit(*libusbContext) error
setDebug(*libusbContext, int)
// device
dereference(*libusbDevice)
getDeviceDesc(*libusbDevice) (*DeviceDesc, error)
open(*libusbDevice) (*libusbDevHandle, error)
close(*libusbDevHandle)
reset(*libusbDevHandle) error
control(*libusbDevHandle, time.Duration, uint8, uint8, uint16, uint16, []byte) (int, error)
getConfig(*libusbDevHandle) (uint8, error)
setConfig(*libusbDevHandle, uint8) error
getStringDesc(*libusbDevHandle, int) (string, error)
setAutoDetach(*libusbDevHandle, int) error
detachKernelDriver(*libusbDevHandle, uint8) error
// interface
claim(*libusbDevHandle, uint8) error
release(*libusbDevHandle, uint8)
setAlt(*libusbDevHandle, uint8, uint8) error
// transfer
alloc(*libusbDevHandle, *EndpointDesc, int, int, chan struct{}) (*libusbTransfer, error)
cancel(*libusbTransfer) error
submit(*libusbTransfer) error
buffer(*libusbTransfer) []byte
data(*libusbTransfer) (int, TransferStatus)
free(*libusbTransfer)
setIsoPacketLengths(*libusbTransfer, uint32)
}
// libusbImpl is an implementation of libusbIntf using real CGo-wrapped libusb.
type libusbImpl struct{}
func (libusbImpl) init() (*libusbContext, error) {
var ctx *C.libusb_context
if err := fromErrNo(C.libusb_init(&ctx)); err != nil {
return nil, err
}
return (*libusbContext)(ctx), nil
}
func (libusbImpl) handleEvents(c *libusbContext, done <-chan struct{}) {
tv := C.struct_timeval{tv_usec: 100e3}
for {
select {
case <-done:
return
default:
}
if errno := C.libusb_handle_events_timeout_completed((*C.libusb_context)(c), &tv, nil); errno < 0 {
log.Printf("handle_events: error: %s", Error(errno))
}
}
}
func (libusbImpl) getDevices(ctx *libusbContext) ([]*libusbDevice, error) {
var list **C.libusb_device
cnt := C.libusb_get_device_list((*C.libusb_context)(ctx), &list)
if cnt < 0 {
return nil, fromErrNo(C.int(cnt))
}
var devs []*C.libusb_device
*(*reflect.SliceHeader)(unsafe.Pointer(&devs)) = reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(list)),
Len: int(cnt),
Cap: int(cnt),
}
var ret []*libusbDevice
for _, d := range devs {
ret = append(ret, (*libusbDevice)(d))
}
// devices will be dereferenced later, during close.
C.libusb_free_device_list(list, 0)
return ret, nil
}
func (libusbImpl) exit(c *libusbContext) error {
C.libusb_exit((*C.libusb_context)(c))
return nil
}
func (libusbImpl) setDebug(c *libusbContext, lvl int) {
C.gousb_set_debug((*C.libusb_context)(c), C.int(lvl))
}
func (libusbImpl) getDeviceDesc(d *libusbDevice) (*DeviceDesc, error) {
var desc C.struct_libusb_device_descriptor
if err := fromErrNo(C.libusb_get_device_descriptor((*C.libusb_device)(d), &desc)); err != nil {
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))),
Port: int(C.libusb_get_port_number((*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),
MaxControlPacketSize: int(desc.bMaxPacketSize0),
iManufacturer: int(desc.iManufacturer),
iProduct: int(desc.iProduct),
iSerialNumber: int(desc.iSerialNumber),
}
// Enumerate configurations
cfgs := make(map[int]ConfigDesc)
for i := 0; i < int(desc.bNumConfigurations); i++ {
var cfg *C.struct_libusb_config_descriptor
if err := fromErrNo(C.libusb_get_config_descriptor((*C.libusb_device)(d), C.uint8_t(i), &cfg)); err != nil {
return nil, err
}
c := ConfigDesc{
Number: int(cfg.bConfigurationValue),
SelfPowered: (cfg.bmAttributes & selfPoweredMask) != 0,
RemoteWakeup: (cfg.bmAttributes & remoteWakeupMask) != 0,
MaxPower: 2 * Milliamperes(cfg.MaxPower),
iConfiguration: int(cfg.iConfiguration),
}
// 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
*(*reflect.SliceHeader)(unsafe.Pointer(&ifaces)) = reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(cfg._interface)),
Len: int(cfg.bNumInterfaces),
Cap: int(cfg.bNumInterfaces),
}
c.Interfaces = make([]InterfaceDesc, 0, len(ifaces))
for ifNum, 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([]InterfaceSetting, 0, len(alts))
for altNum, alt := range alts {
i := InterfaceSetting{
Number: int(alt.bInterfaceNumber),
Alternate: int(alt.bAlternateSetting),
Class: Class(alt.bInterfaceClass),
SubClass: Class(alt.bInterfaceSubClass),
Protocol: Protocol(alt.bInterfaceProtocol),
iInterface: int(alt.iInterface),
}
if ifNum != i.Number {
return nil, fmt.Errorf("config %d interface at index %d has number %d, USB standard states they should be identical", c.Number, ifNum, i.Number)
}
if altNum != i.Alternate {
return nil, fmt.Errorf("config %d interface %d alternate settings at index %d has number %d, USB standard states they should be identical", c.Number, i.Number, altNum, i.Alternate)
}
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(map[EndpointAddress]EndpointDesc, len(ends))
for _, end := range ends {
epi := libusbEndpoint(end).endpointDesc(dev)
i.Endpoints[epi.Address] = epi
}
descs = append(descs, i)
}
c.Interfaces = append(c.Interfaces, InterfaceDesc{
Number: descs[0].Number,
AltSettings: descs,
})
}
C.libusb_free_config_descriptor(cfg)
cfgs[c.Number] = c
}
dev.Configs = cfgs
return dev, nil
}
func (libusbImpl) dereference(d *libusbDevice) {
C.libusb_unref_device((*C.libusb_device)(d))
}
func (libusbImpl) open(d *libusbDevice) (*libusbDevHandle, error) {
var handle *C.libusb_device_handle
if err := fromErrNo(C.libusb_open((*C.libusb_device)(d), &handle)); err != nil {
return nil, err
}
return (*libusbDevHandle)(handle), nil
}
func (libusbImpl) close(d *libusbDevHandle) {
C.libusb_close((*C.libusb_device_handle)(d))
}
func (libusbImpl) reset(d *libusbDevHandle) error {
return fromErrNo(C.libusb_reset_device((*C.libusb_device_handle)(d)))
}
func (libusbImpl) control(d *libusbDevHandle, timeout time.Duration, rType, request uint8, val, idx uint16, data []byte) (int, error) {
dataSlice := (*reflect.SliceHeader)(unsafe.Pointer(&data))
n := C.libusb_control_transfer(
(*C.libusb_device_handle)(d),
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(timeout/time.Millisecond))
if n < 0 {
return int(n), fromErrNo(n)
}
return int(n), nil
}
func (libusbImpl) getConfig(d *libusbDevHandle) (uint8, error) {
var cfg C.int
if errno := C.libusb_get_configuration((*C.libusb_device_handle)(d), &cfg); errno < 0 {
return 0, fromErrNo(errno)
}
return uint8(cfg), nil
}
func (libusbImpl) setConfig(d *libusbDevHandle, cfg uint8) error {
return fromErrNo(C.libusb_set_configuration((*C.libusb_device_handle)(d), C.int(cfg)))
}
// TODO(sebek): device string descriptors are natively in UTF16 and support
// multiple languages. get_string_descriptor_ascii uses always the first
// language and discards non-ascii bytes. We could do better if needed.
func (libusbImpl) getStringDesc(d *libusbDevHandle, index int) (string, error) {
// allocate 200-byte array limited the length of string descriptor
buf := make([]byte, 200)
// get string descriptor from libusb. if errno < 0 then there are any errors.
// if errno >= 0; it is a length of result string descriptor
errno := C.libusb_get_string_descriptor_ascii(
(*C.libusb_device_handle)(d),
C.uint8_t(index),
(*C.uchar)(unsafe.Pointer(&buf[0])),
200)
if errno < 0 {
return "", fmt.Errorf("failed to get string descriptor %d: %s", index, fromErrNo(errno))
}
return string(buf[:errno]), nil
}
func (libusbImpl) setAutoDetach(d *libusbDevHandle, val int) error {
err := fromErrNo(C.libusb_set_auto_detach_kernel_driver((*C.libusb_device_handle)(d), C.int(val)))
if err != nil && err != ErrorNotSupported {
return err
}
return nil
}
func (libusbImpl) detachKernelDriver(d *libusbDevHandle, iface uint8) error {
err := fromErrNo(C.libusb_detach_kernel_driver((*C.libusb_device_handle)(d), C.int(iface)))
if err != nil && err != ErrorNotSupported && err != ErrorNotFound {
// ErrorNotSupported is returned in non linux systems
// ErrorNotFound is returned if libusb's driver is already attached to the device
return err
}
return nil
}
func (libusbImpl) claim(d *libusbDevHandle, iface uint8) error {
return fromErrNo(C.libusb_claim_interface((*C.libusb_device_handle)(d), C.int(iface)))
}
func (libusbImpl) release(d *libusbDevHandle, iface uint8) {
C.libusb_release_interface((*C.libusb_device_handle)(d), C.int(iface))
}
func (libusbImpl) setAlt(d *libusbDevHandle, iface, setup uint8) error {
return fromErrNo(C.libusb_set_interface_alt_setting((*C.libusb_device_handle)(d), C.int(iface), C.int(setup)))
}
func (libusbImpl) alloc(d *libusbDevHandle, ep *EndpointDesc, isoPackets int, bufLen int, done chan struct{}) (*libusbTransfer, error) {
xfer := C.gousb_alloc_transfer_and_buffer(C.int(bufLen), C.int(isoPackets))
if xfer == nil {
return nil, fmt.Errorf("gousb_alloc_transfer_and_buffer(%d, %d) failed", bufLen, isoPackets)
}
if int(xfer.length) != bufLen {
return nil, fmt.Errorf("gousb_alloc_transfer_and_buffer(%d, %d): length = %d, want %d", bufLen, isoPackets, xfer.length, bufLen)
}
xfer.dev_handle = (*C.libusb_device_handle)(d)
xfer.endpoint = C.uchar(ep.Address)
xfer._type = C.uchar(ep.TransferType)
xfer.num_iso_packets = C.int(isoPackets)
ret := (*libusbTransfer)(xfer)
xferDoneMap.Lock()
xferDoneMap.m[ret] = done
xferDoneMap.Unlock()
return ret, nil
}
func (libusbImpl) cancel(t *libusbTransfer) error {
return fromErrNo(C.libusb_cancel_transfer((*C.struct_libusb_transfer)(t)))
}
func (libusbImpl) submit(t *libusbTransfer) error {
return fromErrNo(C.submit((*C.struct_libusb_transfer)(t)))
}
func (libusbImpl) buffer(t *libusbTransfer) []byte {
// TODO(go1.10?): replace with more user-friendly construct once
// one exists. https://github.com/golang/go/issues/13656
var ret []byte
*(*reflect.SliceHeader)(unsafe.Pointer(&ret)) = reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(t.buffer)),
Len: int(t.length),
Cap: int(t.length),
}
return ret
}
func (libusbImpl) data(t *libusbTransfer) (int, TransferStatus) {
if TransferType(t._type) == TransferTypeIsochronous {
var status TransferStatus
n := int(C.gousb_compact_iso_data((*C.struct_libusb_transfer)(t), (*C.uchar)(unsafe.Pointer(&status))))
return n, status
}
return int(t.actual_length), TransferStatus(t.status)
}
func (libusbImpl) free(t *libusbTransfer) {
xferDoneMap.Lock()
delete(xferDoneMap.m, t)
xferDoneMap.Unlock()
C.gousb_free_transfer_and_buffer((*C.struct_libusb_transfer)(t))
}
func (libusbImpl) setIsoPacketLengths(t *libusbTransfer, length uint32) {
C.libusb_set_iso_packet_lengths((*C.struct_libusb_transfer)(t), C.uint(length))
}
// xferDoneMap keeps a map of done callback channels for all allocated transfers.
var xferDoneMap = struct {
m map[*libusbTransfer]chan struct{}
sync.RWMutex
}{
m: make(map[*libusbTransfer]chan struct{}),
}
//export xferCallback
func xferCallback(xfer *C.struct_libusb_transfer) {
xferDoneMap.RLock()
ch := xferDoneMap.m[(*libusbTransfer)(xfer)]
xferDoneMap.RUnlock()
ch <- struct{}{}
}
// for benchmarking of method on implementation vs vanilla function.
func libusbSetDebug(c *libusbContext, lvl int) {
C.gousb_set_debug((*C.libusb_context)(c), C.int(lvl))
}
func newDevicePointer() *libusbDevice {
return (*libusbDevice)(unsafe.Pointer(C.malloc(1)))
}
func newFakeTransferPointer() *libusbTransfer {
return (*libusbTransfer)(unsafe.Pointer(C.malloc(1)))
}

57
vendor/github.com/google/gousb/misc.go generated vendored Normal file
View file

@ -0,0 +1,57 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb
import (
"fmt"
)
// BCD is a binary-coded decimal version number. Its first 8 bits represent
// the major version number, its last 8 bits represent the minor version number.
// Major and minor are composed of 4+4 bits, where each 4 bits represents
// a decimal digit.
// Example: BCD(0x1234) means major 12 (decimal) and minor 34 (decimal).
type BCD uint16
// Major is the major number of the BCD.
func (s BCD) Major() uint8 {
maj := uint8(s >> 8)
return 10*(maj>>4) + maj&0x0f
}
// Minor is the minor number of the BCD.
func (s BCD) Minor() uint8 {
min := uint8(s & 0xff)
return 10*(min>>4) + min&0x0f
}
// String returns a dotted representation of the BCD (major.minor).
func (s BCD) String() string {
return fmt.Sprintf("%d.%02d", s.Major(), s.Minor())
}
// Version returns a BCD version number with given major/minor.
func Version(major, minor uint8) BCD {
return (BCD(major)/10)<<12 | (BCD(major)%10)<<8 | (BCD(minor)/10)<<4 | BCD(minor)%10
}
// ID represents a vendor or product ID.
type ID uint16
// String returns a hexadecimal ID.
func (id ID) String() string {
return fmt.Sprintf("%04x", int(id))
}

100
vendor/github.com/google/gousb/transfer.c generated vendored Normal file
View file

@ -0,0 +1,100 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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.
#include <libusb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_xfer(struct libusb_transfer *xfer);
void xferCallback(struct libusb_transfer*);
int submit(struct libusb_transfer *xfer) {
xfer->callback = (libusb_transfer_cb_fn)(&xferCallback);
xfer->status = -1;
return libusb_submit_transfer(xfer);
}
void print_xfer(struct libusb_transfer *xfer) {
int i;
printf("Transfer:\n");
printf(" dev_handle: %p\n", xfer->dev_handle);
printf(" flags: %08x\n", xfer->flags);
printf(" endpoint: %x\n", xfer->endpoint);
printf(" type: %x\n", xfer->type);
printf(" timeout: %dms\n", xfer->timeout);
printf(" status: %x\n", xfer->status);
printf(" length: %d (act: %d)\n", xfer->length, xfer->actual_length);
printf(" callback: %p\n", xfer->callback);
printf(" user_data: %p\n", xfer->user_data);
printf(" buffer: %p\n", xfer->buffer);
printf(" num_iso_pkts: %d\n", xfer->num_iso_packets);
printf(" packets:\n");
for (i = 0; i < xfer->num_iso_packets; i++) {
printf(" [%04d] %d (act: %d) %x\n", i,
xfer->iso_packet_desc[i].length,
xfer->iso_packet_desc[i].actual_length,
xfer->iso_packet_desc[i].status);
}
}
// compact the data in an isochronous transfer. The contents of individual
// iso packets are shifted left, so that no gaps are left between them.
// Status is set to the first non-zero status of an iso packet.
int gousb_compact_iso_data(struct libusb_transfer *xfer, unsigned char *status) {
int i;
int sum = 0;
unsigned char *in = xfer->buffer;
unsigned char *out = xfer->buffer;
for (i = 0; i < xfer->num_iso_packets; i++) {
struct libusb_iso_packet_descriptor pkt = xfer->iso_packet_desc[i];
if (pkt.status != 0) {
*status = pkt.status;
break;
}
// Copy the data
int len = pkt.actual_length;
memmove(out, in, len);
// Increment offsets
sum += len;
in += pkt.length;
out += len;
}
return sum;
}
// allocates a libusb transfer and a buffer for packet data.
struct libusb_transfer *gousb_alloc_transfer_and_buffer(int bufLen, int isoPackets) {
struct libusb_transfer *xfer = libusb_alloc_transfer(isoPackets);
if (xfer == NULL) {
return NULL;
}
xfer->buffer = (unsigned char*)malloc(bufLen);
if (xfer->buffer == NULL) {
libusb_free_transfer(xfer);
return NULL;
}
xfer->length = bufLen;
return xfer;
}
// frees a libusb transfer and its buffer. The buffer of the given
// libusb_transfer must have been allocated with alloc_transfer_and_buffer.
void gousb_free_transfer_and_buffer(struct libusb_transfer *xfer) {
free(xfer->buffer);
xfer->length = 0;
libusb_free_transfer(xfer);
}

160
vendor/github.com/google/gousb/transfer.go generated vendored Normal file
View file

@ -0,0 +1,160 @@
// Copyright 2016 the gousb Authors. 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 gousb
import (
"context"
"errors"
"runtime"
"sync"
)
type usbTransfer struct {
// mu protects the transfer state.
mu sync.Mutex
// xfer is the allocated libusb_transfer.
xfer *libusbTransfer
// buf is the buffer allocated for the transfer. The underlying memory
// is allocated by the C code, both buf and xfer.buffer point to the same
// memory.
buf []byte
// done is blocking until the transfer is complete and data and transfer
// status are available.
done chan struct{}
// submitted is true if submit() was called on this transfer.
submitted bool
// ctx is the Context that created this transfer.
ctx *Context
}
// submits the transfer. After submit() the transfer is in flight and is owned by libusb.
// It's not safe to access the contents of the transfer until wait() returns.
// Once wait() returns, it's ok to re-use the same transfer structure by calling submit() again.
func (t *usbTransfer) submit() error {
t.mu.Lock()
defer t.mu.Unlock()
if t.submitted {
return errors.New("transfer was already submitted and is not finished yet")
}
if err := t.ctx.libusb.submit(t.xfer); err != nil {
return err
}
t.submitted = true
return nil
}
// waits for libusb to signal the release of transfer data.
// After wait returns, the transfer contents are safe to access
// via t.buf. The number returned by wait indicates how many bytes
// of the buffer were read or written by libusb, and it can be
// smaller than the length of t.buf.
func (t *usbTransfer) wait(ctx context.Context) (n int, err error) {
t.mu.Lock()
defer t.mu.Unlock()
if !t.submitted {
return 0, nil
}
select {
case <-ctx.Done():
t.ctx.libusb.cancel(t.xfer)
// after the transfer is cancelled, it will run a callback
// that triggers the activation of t.done.
<-t.done
case <-t.done:
}
t.submitted = false
n, status := t.ctx.libusb.data(t.xfer)
if status != TransferCompleted {
return n, status
}
return n, err
}
// cancel aborts a submitted transfer. The transfer is cancelled
// asynchronously and the user still needs to wait() to return.
func (t *usbTransfer) cancel() error {
t.mu.Lock()
defer t.mu.Unlock()
if !t.submitted {
return nil
}
err := t.ctx.libusb.cancel(t.xfer)
if err == ErrorNotFound {
// transfer already completed
return nil
}
return err
}
// free releases the memory allocated for the transfer.
// free should be called only if the transfer is not used by libusb,
// i.e. it should not be called after submit() and before wait() returns.
func (t *usbTransfer) free() error {
t.mu.Lock()
defer t.mu.Unlock()
if t.submitted {
return errors.New("free() cannot be called on a submitted transfer until wait() returns")
}
if t.xfer == nil {
return nil
}
t.ctx.libusb.free(t.xfer)
t.xfer = nil
t.buf = nil
t.done = nil
return nil
}
// data returns the slice containing transfer buffer.
func (t *usbTransfer) data() []byte {
return t.buf
}
// newUSBTransfer allocates a new transfer structure and a new buffer for
// communication with a given device/endpoint.
func newUSBTransfer(ctx *Context, dev *libusbDevHandle, ei *EndpointDesc, bufLen int) (*usbTransfer, error) {
var isoPackets, isoPktSize int
if ei.TransferType == TransferTypeIsochronous {
isoPktSize = ei.MaxPacketSize
if bufLen < isoPktSize {
isoPktSize = bufLen
}
isoPackets = bufLen / isoPktSize
debug.Printf("New isochronous transfer - buffer length %d, using %d packets of %d bytes each", bufLen, isoPackets, isoPktSize)
}
done := make(chan struct{}, 1)
xfer, err := ctx.libusb.alloc(dev, ei, isoPackets, bufLen, done)
if err != nil {
return nil, err
}
if ei.TransferType == TransferTypeIsochronous {
ctx.libusb.setIsoPacketLengths(xfer, uint32(isoPktSize))
}
t := &usbTransfer{
xfer: xfer,
buf: ctx.libusb.buffer(xfer),
done: done,
ctx: ctx,
}
runtime.SetFinalizer(t, func(t *usbTransfer) {
t.cancel()
t.wait(context.Background())
t.free()
})
return t, nil
}

314
vendor/github.com/google/gousb/transfer_stream.go generated vendored Normal file
View file

@ -0,0 +1,314 @@
// Copyright 2017 the gousb Authors. 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 gousb
import (
"context"
"io"
)
type transferIntf interface {
submit() error
cancel() error
wait(context.Context) (int, error)
free() error
data() []byte
}
type stream struct {
// a fifo of USB transfers.
transfers chan transferIntf
// err is the first encountered error, returned to the user.
err error
// finished is true if transfers has been already closed.
finished bool
}
func (s *stream) gotError(err error) {
if s.err == nil {
s.err = err
}
}
func (s *stream) noMore() {
if !s.finished {
close(s.transfers)
s.finished = true
}
}
func (s *stream) submitAll() {
count := len(s.transfers)
var all []transferIntf
for i := 0; i < count; i++ {
all = append(all, <-s.transfers)
}
for _, t := range all {
if err := t.submit(); err != nil {
t.free()
s.gotError(err)
s.noMore()
return
}
s.transfers <- t
}
return
}
func (s *stream) flushRemaining() {
s.noMore()
for t := range s.transfers {
t.cancel()
t.wait(context.Background())
t.free()
}
}
func (s *stream) done() {
if s.err == nil {
close(s.transfers)
}
}
// ReadStream is a buffer that tries to prefetch data from the IN endpoint,
// reducing the latency between subsequent Read()s.
// ReadStream keeps prefetching data until Close() is called or until
// an error is encountered. After Close(), the buffer might still have
// data left from transfers that were initiated before Close. Read()ing
// from the ReadStream will keep returning available data. When no more
// data is left, io.EOF is returned.
type ReadStream struct {
s *stream
// current holds the last transfer to return.
current transferIntf
// total/used are the number of all/used bytes in the current transfer.
total, used int
}
// Read reads data from the transfer stream.
// The data will come from at most a single transfer, so the returned number
// might be smaller than the length of p.
// After a non-nil error is returned, all subsequent attempts to read will
// return io.ErrClosedPipe.
// Read cannot be called concurrently with other Read, ReadContext
// or Close.
func (r *ReadStream) Read(p []byte) (int, error) {
return r.ReadContext(context.Background(), p)
}
// ReadContext reads data from the transfer stream.
// The data will come from at most a single transfer, so the returned number
// might be smaller than the length of p.
// After a non-nil error is returned, all subsequent attempts to read will
// return io.ErrClosedPipe.
// ReadContext cannot be called concurrently with other Read, ReadContext
// or Close.
// The context passed controls the cancellation of this particular read
// operation within the stream. The semantics is identical to
// Endpoint.ReadContext.
func (r *ReadStream) ReadContext(ctx context.Context, p []byte) (int, error) {
if r.s.transfers == nil {
return 0, io.ErrClosedPipe
}
if r.current == nil {
t, ok := <-r.s.transfers
if !ok {
// no more transfers in flight
r.s.transfers = nil
return 0, r.s.err
}
n, err := t.wait(ctx)
if err != nil {
// wait error aborts immediately, all remaining data is invalid.
t.free()
r.s.flushRemaining()
r.s.transfers = nil
return n, err
}
r.current = t
r.total = n
r.used = 0
}
use := r.total - r.used
if use > len(p) {
use = len(p)
}
copy(p, r.current.data()[r.used:r.used+use])
r.used += use
if r.used == r.total {
if r.s.err == nil {
if err := r.current.submit(); err == nil {
// guaranteed to not block, len(transfers) == number of allocated transfers
r.s.transfers <- r.current
} else {
r.s.gotError(err)
r.s.noMore()
}
}
if r.s.err != nil {
r.current.free()
}
r.current = nil
}
return use, nil
}
// Close signals that the transfer should stop. After Close is called,
// subsequent Read()s will return data from all transfers that were already
// in progress before returning an io.EOF error, unless another error
// was encountered earlier.
// Close cannot be called concurrently with Read.
func (r *ReadStream) Close() error {
if r.s.transfers == nil {
return nil
}
r.s.gotError(io.EOF)
r.s.noMore()
return nil
}
// WriteStream is a buffer that will send data asynchronously, reducing
// the latency between subsequent Write()s.
type WriteStream struct {
s *stream
total int
}
// Write sends the data to the endpoint. Write returning a nil error doesn't
// mean that data was written to the device, only that it was written to the
// buffer. Only a call to Close() that returns nil error guarantees that
// all transfers have succeeded.
// If the slice passed to Write does not align exactly with the transfer
// buffer size (as declared in a call to NewStream), the last USB transfer
// of this Write will be sent with less data than the full buffer.
// After a non-nil error is returned, all subsequent attempts to write will
// return io.ErrClosedPipe.
// If Write encounters an error when preparing the transfer, the stream
// will still try to complete any pending transfers. The total number
// of bytes successfully written can be retrieved through a Written()
// call after Close() has returned.
// Write cannot be called concurrently with another Write, Written or Close.
func (w *WriteStream) Write(p []byte) (int, error) {
return w.WriteContext(context.Background(), p)
}
// WriteContext sends the data to the endpoint. Write returning a nil error doesn't
// mean that data was written to the device, only that it was written to the
// buffer. Only a call to Close() that returns nil error guarantees that
// all transfers have succeeded.
// If the slice passed to WriteContext does not align exactly with the transfer
// buffer size (as declared in a call to NewStream), the last USB transfer
// of this Write will be sent with less data than the full buffer.
// After a non-nil error is returned, all subsequent attempts to write will
// return io.ErrClosedPipe.
// If WriteContext encounters an error when preparing the transfer, the stream
// will still try to complete any pending transfers. The total number
// of bytes successfully written can be retrieved through a Written()
// call after Close() has returned.
// WriteContext cannot be called concurrently with another Write, WriteContext,
// Written, Close or CloseContext.
func (w *WriteStream) WriteContext(ctx context.Context, p []byte) (int, error) {
if w.s.transfers == nil || w.s.err != nil {
return 0, io.ErrClosedPipe
}
written := 0
all := len(p)
for written < all {
t := <-w.s.transfers
n, err := t.wait(ctx) // unsubmitted transfers will return 0 bytes and no error
w.total += n
if err != nil {
t.free()
w.s.gotError(err)
// This branch is used only after all the transfers were set in flight.
// That means all transfers left in the queue are in flight.
// They must be ignored, since this wait() failed.
w.s.flushRemaining()
return written, err
}
use := all - written
if max := len(t.data()); use > max {
use = max
}
copy(t.data(), p[written:written+use])
if err := t.submit(); err != nil {
t.free()
w.s.gotError(err)
// Even though this submit failed, all the transfers in flight are still valid.
// Don't flush remaining transfers.
// We won't submit any more transfers.
w.s.noMore()
return written, err
}
written += use
w.s.transfers <- t // guaranteed non blocking
}
return written, nil
}
// Close signals end of data to write. Close blocks until all transfers
// that were sent are finished. The error returned by Close is the first
// error encountered during writing the entire stream (if any).
// Close returning nil indicates all transfers completed successfully.
// After Close, the total number of bytes successfully written can be
// retrieved using Written().
// Close may not be called concurrently with Write, Close or Written.
func (w *WriteStream) Close() error {
return w.CloseContext(context.Background())
}
// Close signals end of data to write. Close blocks until all transfers
// that were sent are finished. The error returned by Close is the first
// error encountered during writing the entire stream (if any).
// Close returning nil indicates all transfers completed successfully.
// After Close, the total number of bytes successfully written can be
// retrieved using Written().
// Close may not be called concurrently with Write, Close or Written.
// CloseContext
func (w *WriteStream) CloseContext(ctx context.Context) error {
if w.s.transfers == nil {
return io.ErrClosedPipe
}
w.s.noMore()
for t := range w.s.transfers {
n, err := t.wait(ctx)
w.total += n
t.free()
if err != nil {
w.s.gotError(err)
w.s.flushRemaining()
}
t.free()
}
w.s.transfers = nil
return w.s.err
}
// Written returns the number of bytes successfully written by the stream.
// Written may be called only after Close() or CloseContext()
// has been called and returned.
func (w *WriteStream) Written() int {
return w.total
}
func newStream(tt []transferIntf) *stream {
s := &stream{
transfers: make(chan transferIntf, len(tt)),
}
for _, t := range tt {
s.transfers <- t
}
return s
}

26
vendor/github.com/google/gousb/usb.c generated vendored Normal file
View file

@ -0,0 +1,26 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2018 the gousb Authors. 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.
#include <libusb.h>
void gousb_set_debug(libusb_context *ctx, int lvl) {
// TODO(sebek): remove libusb_debug entirely in 2.1 or 3.0,
// require libusb >= 1.0.22. libusb 1.0.22 sets API version 0x01000106.
#if LIBUSB_API_VERSION >= 0x01000106
libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, lvl);
#else
libusb_set_debug(ctx, lvl);
#endif
}

231
vendor/github.com/google/gousb/usb.go generated vendored Normal file
View file

@ -0,0 +1,231 @@
// Copyright 2013 Google Inc. All rights reserved.
// Copyright 2016 the gousb Authors. 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 gousb provides an low-level interface to attached USB devices.
A Short Tutorial
A Context manages all resources necessary for communicating with USB
devices.
Through the Context users can iterate over available USB devices.
The USB standard defines a mechanism of discovering USB device functionality
through descriptors. After the device is attached and
initialized by the host stack, it's possible to retrieve its descriptor
(the device descriptor). It contains elements such as product and vendor IDs,
bus number and device number (address) on the bus.
In gousb, the Device struct represents a USB device. The Device structs Desc
field contains all known information about the device.
Among other information in the device descriptor is a list of configuration
descriptors, accessible through Device.Desc.Configs.
The USB standard allows one physical USB device to switch between different
sets of behaviors, or working modes, by selecting one of the offered configs
(each device has at least one).
This allows the same device to sometimes present itself as e.g. a 3G modem,
and sometimes as a flash drive with the drivers for that 3G modem.
Configs are mutually exclusive, each device
can have only one active config at a time. Switching the active config performs
a light-weight device reset. Each config in the device descriptor has
a unique identification number.
In gousb a device config needs to be selected through Device.Config(num).
It returns a Config struct that represents the device in this particular configuration.
The configuration descriptor is accessible through Config.Desc.
A config descriptor determines the list of available USB interfaces on the device.
Each interface is a virtual device within the physical USB device and its active
config. There can be many interfaces active concurrently. Interfaces are
enumerated sequentially starting from zero.
Additionally, each interface comes with a number of alternate settings for
the interface, which are somewhat similar to device configs, but on the
interface level. Each interface can have only a single alternate setting
active at any time. Alternate settings are enumerated sequentially starting from
zero.
In gousb an interface and its alternate setting can be selected through
Config.Interface(num, altNum). The Interface struct is the representation
of the claimed interface with a particular alternate setting.
The descriptor of the interface is available through Interface.Setting.
An interface with a particular alternate setting defines up to 30 data
endpoints, each identified by a unique address. The endpoint address is a combination
of endpoint number (1..15) and endpoint directionality (IN/OUT).
IN endpoints have addresses 0x81..0x8f, while OUT endpoints 0x01..0x0f.
An endpoint can be considered similar to a UDP/IP port,
except the data transfers are unidirectional.
Endpoints are represented by the Endpoint struct, and all defined endpoints
can be obtained through the Endpoints field of the Interface.Setting.
Each endpoint descriptor (EndpointDesc) defined in the interface's endpoint
map includes information about the type of the endpoint:
- endpoint address
- endpoint number
- direction: IN (device-to-host) or OUT (host-to-device)
- transfer type: USB standard defines a few distinct data transfer types:
--- bulk - high throughput, but no guaranteed bandwidth and no latency guarantees,
--- isochronous - medium throughput, guaranteed bandwidth, some latency guarantees,
--- interrupt - low throughput, high latency guarantees.
The endpoint descriptor determines the type of the transfer that will be used.
- maximum packet size: maximum number of bytes that can be sent or received by the device in a single USB transaction.
and a few other less frequently used pieces of endpoint information.
An IN Endpoint can be opened for reading through Interface.InEndpoint(epNum),
while an OUT Endpoint can be opened for writing through Interface.OutEndpoint(epNum).
An InEndpoint implements the io.Reader interface, an OutEndpoint implements
the io.Writer interface. Both Reads and Writes will accept larger slices
of data than the endpoint's maximum packet size, the transfer will be split
into smaller USB transactions as needed. But using Read/Write size equal
to an integer multiple of maximum packet size helps with improving the transfer
performance.
Apart from 15 possible data endpoints, each USB device also has a control endpoint.
The control endpoint is present regardless of the current device config, claimed
interfaces and their alternate settings. It makes a lot of sense, as the control endpoint is actually used, among others,
to issue commands to switch the active config or select an alternate setting for an interface.
Control commands are also often used to control the behavior of the device. There is no single
standard for control commands though, and many devices implement their custom control command schema.
Control commands can be issued through Device.Control().
See Also
For more information about USB protocol and handling USB devices,
see the excellent "USB in a nutshell" guide: http://www.beyondlogic.org/usbnutshell/
*/
package gousb
// Context manages all resources related to USB device handling.
type Context struct {
ctx *libusbContext
done chan struct{}
libusb libusbIntf
}
// Debug changes the debug level. Level 0 means no debug, higher levels
// will print out more debugging information.
// TODO(sebek): in the next major release, replace int levels with
// Go-typed constants.
func (c *Context) Debug(level int) {
c.libusb.setDebug(c.ctx, level)
}
func newContextWithImpl(impl libusbIntf) *Context {
c, err := impl.init()
if err != nil {
panic(err)
}
ctx := &Context{
ctx: c,
done: make(chan struct{}),
libusb: impl,
}
go impl.handleEvents(ctx.ctx, ctx.done)
return ctx
}
// NewContext returns a new Context instance.
func NewContext() *Context {
return newContextWithImpl(libusbImpl{})
}
// OpenDevices calls opener with each enumerated device.
// If the opener returns true, the device is opened and a Device is returned if the operation succeeds.
// Every Device returned (whether an error is also returned or not) must be closed.
// If there are any errors enumerating the devices,
// the final one is returned along with any successfully opened devices.
func (c *Context) OpenDevices(opener func(desc *DeviceDesc) bool) ([]*Device, error) {
list, err := c.libusb.getDevices(c.ctx)
if err != nil {
return nil, err
}
var reterr error
var ret []*Device
for _, dev := range list {
desc, err := c.libusb.getDeviceDesc(dev)
if err != nil {
c.libusb.dereference(dev)
reterr = err
continue
}
if opener(desc) {
handle, err := c.libusb.open(dev)
if err != nil {
c.libusb.dereference(dev)
reterr = err
continue
}
ret = append(ret, &Device{handle: handle, ctx: c, Desc: desc})
} else {
c.libusb.dereference(dev)
}
}
return ret, reterr
}
// 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.
// If there were any errors during device list traversal, it is possible
// it will return a non-nil device and non-nil error. A Device.Close() must
// be called to release the device if the returned device wasn't nil.
func (c *Context) OpenDeviceWithVIDPID(vid, pid ID) (*Device, error) {
var found bool
devs, err := c.OpenDevices(func(desc *DeviceDesc) bool {
if found {
return false
}
if desc.Vendor == ID(vid) && desc.Product == ID(pid) {
found = true
return true
}
return false
})
if len(devs) == 0 {
return nil, err
}
return devs[0], nil
}
// Close releases the Context and all associated resources.
func (c *Context) Close() error {
var ret error
c.done <- struct{}{}
if c.ctx != nil {
ret = c.libusb.exit(c.ctx)
}
c.ctx = nil
return ret
}