Merge pull request #14 from nodtem66/master

Add OpenDeviceWithVidPid - thanks nodtem66!
This commit is contained in:
Kyle Lemons
2016-03-27 09:26:11 -07:00
7 changed files with 180 additions and 5 deletions

View File

@@ -7,8 +7,7 @@ Supported platforms include:
- linux
- darwin
Windows support is unconfirmed, but should work via cgo and [libusb-win32](http://sourceforge.net/apps/trac/libusb-win32/wiki).
- windows
Contributing
============
@@ -19,8 +18,8 @@ You will need to send me the email address that you used to sign the agreement
so that I can verify that it is on file before I can accept pull requests.
Installation
============
Installation on Linux
=====================
Dependencies
------------
@@ -46,6 +45,42 @@ There is also a `usbid` package that will not be installed by default by this co
go get -v github.com/kylelemons/gousb/usb{,id}
Installation on Windows
=======================
Dependencies
------------
- Gcc (only tested on [Win-Builds](http://win-builds.org/), but any MSYS, CYGWIN, MINGW should be worked
- [libusb-1.0](http://sourceforge.net/projects/libusb/files/libusb-1.0/)
Build
-----
- After downloaded, extract them to some directory; such as D:\lib\libusb-1.0.xx\
- Remember two path which "libusb.h" file and "libusb-1.0.a" inside
*Note* For MinGW32, use **MinGW32/static/libusb-1.0.a** while MinGW64 use **MinGW64/static/libusb-1.0.a** for linker
- Open `$(GOPATH)/src/github.com/kylelemons/gousb/usb/usb.go`.
Then edit `#cgo` directive, such as
// #cgo CFLAGS: -ID:/lib/libusbx-1.0.xx/include
// #cgo LDFLAGS: D:/lib/libusbx-1.0.xx/MinGW64/static/libusb-1.0.a
to your `libusb-1.0` installed path before the line:
// #include <libusb-1.0/libusb.h>
This flag will tell the linker the exact path of static library.
Then install `gousb`:
- Go to `$(GOPATH)/src/github.com/kylelemons/gousb/`. Run:
$ go install ./...
`lsusb` can run under `$GOBIN/lsusb`
Documentation
=============
The documentation can be viewed via local godoc or via Gary Burd's excellent [godoc.org](http://godoc.org/):

Binary file not shown.

View File

@@ -203,3 +203,26 @@ found:
return end, nil
}
func (d *Device) GetStringDescriptor(desc_index int) (string, error) {
// allocate 200-byte array limited the length of string descriptor
goBuffer := 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(
d.handle,
C.uint8_t(desc_index),
(*C.uchar)(unsafe.Pointer(&goBuffer[0])),
200)
// if any errors occur
if errno < 0 {
return "", fmt.Errorf("usb: getstr: %s", usbError(errno))
}
// convert slice of byte to string with limited length from errno
stringDescriptor := string(goBuffer[:errno])
return stringDescriptor, nil
}

49
usb/device_test.go Normal file
View File

@@ -0,0 +1,49 @@
// Copyright 2013 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package usb_test
import (
. "github.com/kylelemons/gousb/usb"
"testing"
)
func TestGetStringDescriptorAscii(t *testing.T) {
c := NewContext()
defer c.Close()
c.Debug(0)
devices, err := c.ListDevices(func(desc *Descriptor) bool {
return true
})
if err != nil {
t.Fatalf("%s", err.Error())
}
for i, d := range devices {
str, err := d.GetStringDescriptor(1)
if err != nil {
t.Fatalf("%s", err.Error())
}
str2, err := d.GetStringDescriptor(2)
if err != nil {
t.Fatalf("%s", err.Error())
}
t.Logf("%d: %s %s\n", i, str, str2)
d.Close()
}
}

View File

@@ -15,7 +15,10 @@
// Package usb provides a wrapper around libusb-1.0.
package usb
// #cgo LDFLAGS: -lusb-1.0
// #cgo windows CFLAGS: -ID:/lib/libusb-1.0.19/include
// #cgo windows,amd64 LDFLAGS: D:/lib/libusb-1.0.19/MinGW64/static/libusb-1.0.a
// #cgo windows,386 LDFLAGS: D:/lib/libusb-1.0.19/MinGW32/static/libusb-1.0.a
// #cgo !windows LDFLAGS: -lusb-1.0
// #include <libusb-1.0/libusb.h>
import "C"
@@ -106,6 +109,31 @@ func (c *Context) ListDevices(each func(desc *Descriptor) bool) ([]*Device, erro
return ret, reterr
}
// OpenDeviceWithVidPid opens Device from specific VendorId and ProductId.
// If there are any errors, it'll returns at second value.
func (c *Context) OpenDeviceWithVidPid(vid, pid int) (*Device, error) {
handle := C.libusb_open_device_with_vid_pid(c.ctx, (C.uint16_t)(vid), (C.uint16_t)(pid))
if handle == nil {
return nil, ERROR_NOT_FOUND
}
dev := C.libusb_get_device(handle)
if dev == nil {
return nil, ERROR_NO_DEVICE
}
desc, err := newDescriptor(dev)
// return an error from nil-handle and nil-device
if err != nil {
return nil, err
}
device := newDevice(handle, desc)
return device, nil
}
func (c *Context) Close() error {
close(c.done)
if c.ctx != nil {

Binary file not shown.

View File

@@ -81,6 +81,46 @@ func TestEnum(t *testing.T) {
}
}
func TestOpenDeviceWithVidPid(t *testing.T) {
c := NewContext()
defer c.Close()
c.Debug(0)
// Accept for all device
devs, err := c.ListDevices(func(desc *Descriptor) bool {
return true
})
defer func() {
for _, d := range devs {
d.Close()
}
}()
if err != nil {
t.Fatalf("list: %s", err)
}
for i := range devs {
vid := devs[i].Vendor
pid := devs[i].Product
device, err := c.OpenDeviceWithVidPid((int)(vid), (int)(pid))
// if the context failed to open device
if err != nil {
t.Fail()
}
// if opened device was not valid
if device.Descriptor.Bus != devs[i].Bus ||
device.Descriptor.Address != devs[i].Address ||
device.Vendor != devs[i].Vendor ||
device.Product != devs[i].Product {
t.Fail()
}
}
}
func TestMultipleContexts(t *testing.T) {
var buf bytes.Buffer
log.SetOutput(&buf)