diff --git a/README.md b/README.md index 472793a..2f0c201 100644 --- a/README.md +++ b/README.md @@ -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 + +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/): diff --git a/rawread/rawread b/rawread/rawread deleted file mode 100755 index 4639c44..0000000 Binary files a/rawread/rawread and /dev/null differ diff --git a/usb/device.go b/usb/device.go index 035cb3f..d016b25 100644 --- a/usb/device.go +++ b/usb/device.go @@ -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 +} diff --git a/usb/device_test.go b/usb/device_test.go new file mode 100644 index 0000000..6eebdcf --- /dev/null +++ b/usb/device_test.go @@ -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() + } +} diff --git a/usb/usb.go b/usb/usb.go index b106815..6029dbd 100644 --- a/usb/usb.go +++ b/usb/usb.go @@ -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 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 { diff --git a/usb/usb.test b/usb/usb.test deleted file mode 100755 index 2cd1d0f..0000000 Binary files a/usb/usb.test and /dev/null differ diff --git a/usb/usb_test.go b/usb/usb_test.go index 22aad4f..cc83b9f 100644 --- a/usb/usb_test.go +++ b/usb/usb_test.go @@ -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)