aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/kylelemons/gousb/usb/usb.go
blob: b4bb2581b56e02456216c6cfbe88ef3ca63e94e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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 usb provides a wrapper around libusb-1.0.
//
// Deprecated: this package was deprecated in favor of github.com/google/gousb.
// Please use the new package when starting new projects.
package usb

type Context struct {
	ctx  *libusbContext
	done chan struct{}
}

func (c *Context) Debug(level int) {
	libusb.setDebug(c.ctx, level)
}

func NewContext() *Context {
	c, err := libusb.init()
	if err != nil {
		panic(err)
	}
	ctx := &Context{
		ctx:  c,
		done: make(chan struct{}),
	}
	go libusb.handleEvents(ctx.ctx, ctx.done)
	return ctx
}

// ListDevices calls each with each enumerated device.
// If the function 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) ListDevices(each func(desc *Descriptor) bool) ([]*Device, error) {
	list, err := libusb.getDevices(c.ctx)
	if err != nil {
		return nil, err
	}

	var reterr error
	var ret []*Device
	for _, dev := range list {
		desc, err := libusb.getDeviceDesc(dev)
		if err != nil {
			libusb.dereference(dev)
			reterr = err
			continue
		}

		if each(desc) {
			handle, err := libusb.open(dev)
			if err != nil {
				reterr = err
				continue
			}
			ret = append(ret, newDevice(handle, desc))
		} else {
			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 int) (*Device, error) {
	var found bool
	devs, err := c.ListDevices(func(desc *Descriptor) 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
}

func (c *Context) Close() error {
	c.done <- struct{}{}
	if c.ctx != nil {
		libusb.exit(c.ctx)
	}
	c.ctx = nil
	return nil
}