Git Product home page Git Product logo

gousb's Introduction

Introduction

Build Status GoDoc Coverage Status

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. 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.

Documentation

The documentation can be viewed via local godoc or via the excellent godoc.org:

Installation

Dependencies

You must first install libusb-1.0. 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:

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. 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.

gousb's People

Contributors

albenik avatar chemidy avatar cooldarkdryplace avatar crijonsi avatar danielpaulus avatar djadala avatar dvrkps avatar half2me avatar haugum avatar joseffilzmaier avatar jstemmer avatar krasin avatar kylelemons avatar mauriciogg avatar nicovell3 avatar nilslice avatar nkovacs avatar nodtem66 avatar pjvds avatar rojer avatar vincentserpoul avatar willmcenaney avatar zagrodzki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gousb's Issues

ClassVideo

Please add:

ClassVideo Class = C.LIBUSB_CLASS_VIDEO

to the USB standard classes,

and

ClassVideo: "video",

to the classDescription

in file constants.go

Provide means of getting device's serial number

In my practice, it is often necessary to distinguish between several devices with the same VID, PID.
The standard way of doing that is by serial number, however i don't see any way of getting it.
Context.OpenDeviceWithVIDPIDSerial would be ideal, but if DeviceDesc provided the SerialNumber field, then filtering in the OpenDevices callback would also be acceptable.
Even post-filtering of opened devices would be ok.
In any case, there needs to be a way to query device's serial number, that's the main thing.

gousb.Endpoint.Read(): libusb: invalid param [code -2]

I am developing a UVC driver and i have two camera modules to test with. One module (ELP-SUSB1080P01) gives an error when i try to read from an endpoint:

libusb: error [submit_iso_transfer] isochronous transfer failed (dir: In):
invalid argument
--- FAIL: TestDeviceCaptureSettings (1.12s)
uvc_test.go:208: Device.UseVideoSetting(): gousb.Endpoint.Read():
libusb: invalid param [code -2]

The other camera works fine. The camera with the error has an isochronous asynchronous IN endpoint, whereas the other has a bulk unsynchronised IN endpoint, maybe that is significant.

This is the function where it goes wrong at the end, in line
n, err := d.vsEndp.Read(buf)

// UseVideoSetting sets up the device to use the requested video capture
// settings and starts streaming. If the requested settings were taken from
// the list of supported settings, then the request should be honoured as is.
func (d *Device) UseVideoSetting(setting *VideoSetting) error {
	var (
		formatIndex uint8
		frameIndex  uint8
	)
	switch desc := setting.fmt.(type) {
	case *formatDescUncompressed:
		formatIndex = desc.formatIndex
	case *formatDescMJPEG:
		formatIndex = desc.formatIndex
	}
	switch desc := setting.frame.(type) {
	case *frameDescUncompressed:
		frameIndex = desc.frameIndex
	case *frameDescMJPEG:
		frameIndex = desc.frameIndex
	}

	params := probeParams{
		hint:          0x0001,
		formatIndex:   formatIndex,
		frameIndex:    frameIndex,
		frameInterval: uint32(setting.Rate * 10000000),
	}
	fmt.Printf("desired params %#v\n", params)
	data := params.toBytes()

	// set desired state
	_, err := d.dev.Control(
		gousb.ControlOut|gousb.ControlClass|gousb.ControlInterface,
		_SET_CUR, vs_PROBE_CONTROL<<8, uint16(d.vsIfaceNum), data)
	if err != nil {
		return fmt.Errorf("gousb.Device.Control(): %s", err)
	}
	// get supported state
	_, err = d.dev.Control(
		gousb.ControlIn|gousb.ControlClass|gousb.ControlInterface,
		_GET_CUR, vs_PROBE_CONTROL<<8, uint16(d.vsIfaceNum), data)
	if err != nil {
		return fmt.Errorf("gousb.Device.Control(): %s", err)
	}
	paramsNew := probeParams{}
	paramsNew.fromBytes(data)
	fmt.Printf("supported params: %#v\n", paramsNew)

	// commit
	_, err = d.dev.Control(
		gousb.ControlOut|gousb.ControlClass|gousb.ControlInterface,
		_SET_CUR, vs_COMMIT_CONTROL<<8, uint16(d.vsIfaceNum), data)
	if err != nil {
		return fmt.Errorf("gousb.Device.Control(): %s", err)
	}

	// TODO: start a goroutine that reads the stream

	// read from the input endpoint
	bufSize := paramsNew.maxPayloadTransferSize //d.vsEndpD.maxPacketSize
	buf := make([]byte, bufSize)
	fmt.Fprintf(os.Stderr, "start streaming to %dB buffer\n", bufSize)

	for i := 0; i < 128; i++ {
		n, err := d.vsEndp.Read(buf)
		if err != nil {
			return fmt.Errorf("gousb.Endpoint.Read(): %s", err)
		}
		fmt.Printf("read %d bytes %v\n", n, buf[:32])
	}
	return nil
}

Anyone spot any error or flaw in my approach?

Zero-length writes are not allowed

In the transfer function, a zero-length buffer is immediately returned without actually sending anything. However, there seem to be valid use cases for this, so the short-circuit breaks certain things.

I am attempting to port yubihsm-connector to gousb from go-libusb, but the lack of empty writes appears to be problematic.

As libusb even includes a flag LIBUSB_TRANSFER_ADD_ZERO_PACKET to automatically send empty writes itself (which is not exposed by gousb), I think there's no reason to disallow them from user code and skipping them from the Go layer is incorrect.

ClassMiscellaneous

Please add:

ClassMiscellaneous Class = 0xEF

to the USB standard classes,

and

ClassMiscellaneous: "miscellaneous",

to the classDescription

in file constants.go

This one is not in libusb yet, but i encountered it while dealing with a UVC device.

Can not build to windows from Ubuntu 16.04

Hi dev. I want to build apps using gousb, but I can't build it to windows environment. I've trie to build your lsusb example by using this command:
GOOS=windows GOARCH=386 go build -o lsusbex.exe github.com/google/gousb/lsusb/main.go
End with this message and not build:

# github.com/google/gousb
github.com/google/gousb/config.go:40:11: undefined: Milliamperes
github.com/google/gousb/endpoint.go:44:12: undefined: EndpointDirection
github.com/google/gousb/endpoint.go:48:15: undefined: TransferType
github.com/google/gousb/endpoint.go:54:14: undefined: IsoSyncType
github.com/google/gousb/endpoint.go:56:12: undefined: UsageType
github.com/google/gousb/interface.go:47:8: undefined: Class
github.com/google/gousb/interface.go:49:11: undefined: Class
github.com/google/gousb/interface.go:51:11: undefined: Protocol

I've tried to build to windows 32 and 64 bit, but got the same result.
How to build app that dependent on gousb package to windows environment from ubuntu?
Thank you.

Possible to get IEEE-1284 PNP String?

Hi there,

I'm wondering whether it's possible to get the IEEE-1284 PNP String with gousb?
This is the code that cups uses to get this string:

/*
 * 'get_device_id()' - Get the IEEE-1284 device ID for the printer.
 */

static int				/* O - 0 on success, -1 on error */
get_device_id(usb_printer_t *printer,	/* I - Printer */
              char          *buffer,	/* I - String buffer */
              size_t        bufsize)	/* I - Number of bytes in buffer */
{
  int	length;				/* Length of device ID */


  if (libusb_control_transfer(printer->handle,
			      LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_ENDPOINT_IN |
			      LIBUSB_RECIPIENT_INTERFACE,
			      0, printer->conf,
			      (printer->iface << 8) | printer->altset,
			      (unsigned char *)buffer, bufsize, 5000) < 0)
  {
    *buffer = '\0';
    return (-1);
  }

 /*
  * Extract the length of the device ID string from the first two
  * bytes.  The 1284 spec says the length is stored MSB first...
  */

  length = (int)((((unsigned)buffer[0] & 255) << 8) | ((unsigned)buffer[1] & 255));

 /*
  * Check to see if the length is larger than our buffer or less than 14 bytes
  * (the minimum valid device ID is "MFG:x;MDL:y;" with 2 bytes for the length).
  *
  * If the length is out-of-range, assume that the vendor incorrectly
  * implemented the 1284 spec and re-read the length as LSB first,..
  */

  if (length > bufsize || length < 14)
    length = (int)((((unsigned)buffer[1] & 255) << 8) | ((unsigned)buffer[0] & 255));

  if (length > bufsize)
    length = bufsize;

  if (length < 14)
  {
   /*
    * Invalid device ID, clear it!
    */

    *buffer = '\0';
    return (-1);
  }

  length -= 2;

 /*
  * Copy the device ID text to the beginning of the buffer and
  * nul-terminate.
  */

  memmove(buffer, buffer + 2, (size_t)length);
  buffer[length] = '\0';

  return (0);
}

Program freezes on gousb.NewContext

I can go get the gousb repo just fine and everything seems to be working, intellisense brings up suggestions and so on.

But when I actually run my program it freezes on "gousb.NewContext()" I tracked it down with breakpoints and found the problem is arising from from the line below

if err := fromErrNo(C.libusb_init(&ctx)); err != nil { return nil, err }

Specifically
C.libusb_init(&ctx)

Using the Debugger on VSCode when I "step into" that line above and it goes to a file called _cgo_gotypes.go and in the files it says:

Could not load source '_cgo_gotypes.go'.

and in the Debug Console it says:

go list failed on .: can't load package: package .: no Go files in C:\Users\TOJ\AppData\Local\Programs\Microsoft VS Code

I have absolutely no idea what's going on and would really appreciate if someone could shed some light.

here's my go env btw:

set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\TOJ\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\Work\Important\[REPO-NAME]
set GOPROXY=
set GORACE=
set GOROOT=c:\go
set GOTMPDIR=
set GOTOOLDIR=c:\go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\TOJ\AppData\Local\Temp\go-build424489806=/tmp/go-build -gno-record-gcc-switches

null string in serialNumber issue

gousb/device.go

Line 246 in e4c3f66

func (d *Device) SerialNumber() (string, error) {

When there is a null string in the device.SerialNumber() of the device, I want to get the null string that was stripped.

Serial number example obtained through this library

00008020000955DC1132002E\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000

Real SerialNumber

UniqueDeviceID: 00008020-000955DC1132002E

libusb.pc not found

Hi I wanted to experiment with this package, but when the main.go file of lsusb subdirectory outputs

# pkg-config --cflags libusb-1.0 Package libusb-1.0 was not found in the pkg-config search path. Perhaps you should add the directory containing 'libusb-1.0.pc' to the PKG_CONFIG_PATH environment variable No package 'libusb-1.0' found pkg-config: exit status 1

I extracted the libusb to a folder and added it to PKG_CONFIG_PATH environment variable. But then I looked and saw that there was no libusb.pc file.
I couldn't find where to find this file for download. I am on Windows 10.

Compiling for windows:amd64 failed

go env

set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\xxx\AppData\Local\go-build
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\data\Go
set GORACE=
set GOROOT=C:\Go
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0

go build
main.go:24:2: C source files not allowed when not using cgo or SWIG: transfer.c

Any ideas?

Writing 20M buffer to output endpoint return error

Hi,

I'm using gousb on hos tPC to send some dummy data to custom USB device. I'm basically sending files. I find out that 12M file can be written to output endpoint but 20M file return:

Write returned an error: libusb: i/o error [code -1]

Is there some limit in data buffer which can be sent or am I doing something wrong? I'm using same code as example in this repo. Thanks.

Doesn't work on ARM (rasbperry pi)

I'm trying to build a package that includes gousb on a Raspberry Pi 2, and I'm unable to get gousb working at all.
go get -v github.com/google/gousb returns:

github.com/google/gousb (download)
github.com/google/gousb
# github.com/google/gousb
../github.com/google/gousb/libusb.go:234:29: could not determine kind of name for C.libusb_get_port_number
../github.com/google/gousb/libusb.go:396:19: could not determine kind of name for C.libusb_set_auto_detach_kernel_driver

Any ideas?

What is the tcdrain() equivalent in gousb?

Hi all,

I'm creating a simple USB lib for a device inspired by this example in C. The code in Go is here.

The behavior I'm getting is that on a first run the software works fine, but on a second, third etc. It doesn't. There is no error message coming back but the command is simply not executed on the USB device.

In the C example it shows that tcdrain() is used. Should I add something else to close / free / flush / drain?

restore Timeout as a field on InEndpoint

In the Async API issue i read about accidentally hiding the InEndpoint Timeout and the suggestion to expose it again. Please do! I don't know how to exit cleanly when a goroutine is blocked on a Read().

Build error Windows

Hello, when building to windows executable file, returns error. When not using gousb library, works fine.
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ GOOS=windows GOARCH=amd64 go build -o index.exe

Error Type
github.com/google/gousb
collect2: error: ld returned 1 exit status

warning: libusb_set_debug is deprecated

I am getting the following error with go install -v:

<redacted>/vendor/github.com/google/gousb
cgo-gcc-prolog: In function โ€˜_cgo_8c50a4ca37d7_Cfunc_libusb_set_debugโ€™:
cgo-gcc-prolog:505:2: warning: โ€˜libusb_set_debugโ€™ is deprecated: Use libusb_set_option instead [-Wdeprecated-declarations]
In file included from vendor/github.com/google/gousb/libusb.go:31:0:
/usr/include/libusb-1.0/libusb.h:1300:18: note: declared here
 void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
                  ^~~~~~~~~~~~~~~~

go env

GOARCH="386"
GOBIN=""
GOCACHE="/home/erik/.cache/go-build"
GOEXE=""
GOHOSTARCH="386"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/erik/go"
GORACE=""
GOROOT="/usr/lib/go-1.10"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.10/pkg/tool/linux_386"
GCCGO="gccgo"
GO386="387"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-s -w"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m32 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build827923295=/tmp/go-build -gno-record-gcc-switches"

ls usb example fails

I get the following exeption on my Lenovo X1 when running the lsusb example

2019/04/15 09:29:36 list: config 1 interface at index 0 has number 12, USB standard states they should be identical exit status 1

Running the ubuntu lsusb command works just fine. Could it be gousb is a bit over agressive here?

libusb.free() race

libusb.free() frees the libusbTransfer pointer and only then removes it from xferDoneMap (under a lock).
If libusb.alloc() is called from another goroutine in between these two operations, it might allocate the same pointer that was just freed.
The new element might then be removed from xferDoneMap prematurely, resulting in a deadlock when xferCallback tries to notify a nil channel.

I believe changing the order in free() should fix this.

Feature Request

UBS plugged and unplugged events:

I am unable to locate plugged and unplugged events in this package. It would be nice to know if a usb device is plugged or unplugged so that implementors can better manage reconnection when an unplugged device is later plugged-in.

I looked through the code but could hardly find anything close to that, is it there and I am just missing it? If not, is this something that could be implemented?

Control endpoint doesn't support multiple packets

The Control() method implemented on device https://github.com/google/gousb/blob/master/device.go#L195 doesn't seem to accept a "wLength" argument (see https://www.beyondlogic.org/usbnutshell/usb6.shtml). As such, the device only receives the first packet being sent (8 bytes in my case as it's max allowed packet size). It looks like the underlying C method being called already accepts an additional argument after the data arg, presumably for this purpose.

Is there any reason passing in wLength hasn't been implemented in this lib? Or is there an existing mechanism for transferring multiple packets to a control endpoint?

Cannot set direction in control request

In the old gousb, EndpointDirection was a uint8, with the following values:

ENDPOINT_DIR_IN   EndpointDirection = C.LIBUSB_ENDPOINT_IN
ENDPOINT_DIR_OUT  EndpointDirection = C.LIBUSB_ENDPOINT_OUT

In the current version it is a boolean, and the C library constants are not exposed. There's endpointDirectionMask, but it's private.
This is a problem because I need the direction constants for control requests. With the old gousb, I had this code:

n, err := device.Control(uint8(usb.ENDPOINT_DIR_IN|usb.REQUEST_TYPE_VENDOR), 51, 0, 0, data)

I can't do this now.

cross compile from macOS to linux failed

I installed the gcc compiler from http://crossgcc.rts-software.org/doku.php?id=compiling_for_linux but I failed to compile the source code to get a exe file.
Any help would be great, thanks.

code

package main

import (
	"errors"
	"log"

	"github.com/google/gousb"
)

func main() {
	vid, pid, err := findUsbPrinter()
	if err != nil {
		panic(err)
	}
	log.Println("vid, pid:", vid, pid)
}

func findUsbPrinter() (gousb.ID, gousb.ID, error) {
	ctx := gousb.NewContext()
	defer ctx.Close()

	devs, _ := ctx.OpenDevices(func(device *gousb.DeviceDesc) bool {
		//fmt.Printf("Device %s:%s %s \r\n", device.Vendor, device.Product, usbid.Describe(device))
		for _, cfg := range device.Configs {
			for _, intf := range cfg.Interfaces {
				//fmt.Printf("\tinterface %s\r\n", intf.String())
				for _, setting := range intf.AltSettings {
					if setting.Class == gousb.ClassPrinter {
						return true
					}
				}
			}
		}
		return false
	})
	defer func() {
		for _, d := range devs {
			d.Close()
		}
	}()
	if len(devs) == 0 {
		return gousb.ID(0), gousb.ID(0), errors.New("Can not found printer")
	}
	return devs[0].Desc.Vendor, devs[0].Desc.Product, nil

}

command

GOOS=linux GOARCH=amd64 CGO_ENABLED=1 CC=/usr/local/gcc-4.8.1-for-linux64/bin/x86_64-pc-linux-gcc go build -v -ldflags="-w -s" -o test-linux main.go

message

# github.com/google/gousb
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_cancel_transfer':
/tmp/go-build/cgo-gcc-prolog:104: undefined reference to `libusb_cancel_transfer'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_claim_interface':
/tmp/go-build/cgo-gcc-prolog:124: undefined reference to `libusb_claim_interface'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_control_transfer':
/tmp/go-build/cgo-gcc-prolog:163: undefined reference to `libusb_control_transfer'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_detach_kernel_driver':
/tmp/go-build/cgo-gcc-prolog:183: undefined reference to `libusb_detach_kernel_driver'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_bus_number':
/tmp/go-build/cgo-gcc-prolog:239: undefined reference to `libusb_get_bus_number'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_config_descriptor':
/tmp/go-build/cgo-gcc-prolog:260: undefined reference to `libusb_get_config_descriptor'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_configuration':
/tmp/go-build/cgo-gcc-prolog:279: undefined reference to `libusb_get_configuration'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_device_address':
/tmp/go-build/cgo-gcc-prolog:297: undefined reference to `libusb_get_device_address'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_device_descriptor':
/tmp/go-build/cgo-gcc-prolog:316: undefined reference to `libusb_get_device_descriptor'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_device_list':
/tmp/go-build/cgo-gcc-prolog:334: undefined reference to `libusb_get_device_list'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_device_speed':
/tmp/go-build/cgo-gcc-prolog:352: undefined reference to `libusb_get_device_speed'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_port_number':
/tmp/go-build/cgo-gcc-prolog:370: undefined reference to `libusb_get_port_number'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_get_string_descriptor_ascii':
/tmp/go-build/cgo-gcc-prolog:393: undefined reference to `libusb_get_string_descriptor_ascii'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_handle_events_timeout_completed':
/tmp/go-build/cgo-gcc-prolog:413: undefined reference to `libusb_handle_events_timeout_completed'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_init':
/tmp/go-build/cgo-gcc-prolog:431: undefined reference to `libusb_init'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_open':
/tmp/go-build/cgo-gcc-prolog:450: undefined reference to `libusb_open'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_release_interface':
/tmp/go-build/cgo-gcc-prolog:470: undefined reference to `libusb_release_interface'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_reset_device':
/tmp/go-build/cgo-gcc-prolog:488: undefined reference to `libusb_reset_device'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_set_auto_detach_kernel_driver':
/tmp/go-build/cgo-gcc-prolog:508: undefined reference to `libusb_set_auto_detach_kernel_driver'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_set_configuration':
/tmp/go-build/cgo-gcc-prolog:528: undefined reference to `libusb_set_configuration'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_set_interface_alt_setting':
/tmp/go-build/cgo-gcc-prolog:548: undefined reference to `libusb_set_interface_alt_setting'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_close':
/tmp/go-build/cgo-gcc-prolog:138: undefined reference to `libusb_close'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_exit':
/tmp/go-build/cgo-gcc-prolog:197: undefined reference to `libusb_exit'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_free_config_descriptor':
/tmp/go-build/cgo-gcc-prolog:209: undefined reference to `libusb_free_config_descriptor'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_free_device_list':
/tmp/go-build/cgo-gcc-prolog:223: undefined reference to `libusb_free_device_list'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x004.o: In function `_cgo_3308906fefe0_Cfunc_libusb_unref_device':
/tmp/go-build/cgo-gcc-prolog:576: undefined reference to `libusb_unref_device'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x005.o: In function `gousb_alloc_transfer_and_buffer':
../github.com/google/gousb/transfer.c:81: undefined reference to `libusb_alloc_transfer'
../github.com/google/gousb/transfer.c:87: undefined reference to `libusb_free_transfer'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x005.o: In function `submit':
../github.com/google/gousb/transfer.c:27: undefined reference to `libusb_submit_transfer'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x005.o: In function `gousb_free_transfer_and_buffer':
../github.com/google/gousb/transfer.c:99: undefined reference to `libusb_free_transfer'
/var/folders/6b/5_kf1cw10pz63q53ncx616j40000gn/T/go-build970745123/b003/_x006.o: In function `gousb_set_debug':
../github.com/google/gousb/usb.c:22: undefined reference to `libusb_set_option'

A lot of interrupted errors on MacOSX: handle_events: error: libusb: interrupted [code -10]

Recently I have seen a lot of these errors:
handle_events: error: libusb: interrupted [code -10]
on Mac OS X and Linux
with the latest LibUsb

libusb: stable 1.0.23 (bottled), HEAD
Library for USB device access
https://libusb.info/
/usr/local/Cellar/libusb/1.0.23 (26 files, 474.2KB) *

This actually just seems to be a return code from libusb handle_events_with_timeout, that does not really indicate an error but
just that the eventhandler was interrupted. Maybe this should be a debug log?
Right now it seems like something is broken, while actually everything works as expected.

Failed to claim interface 0

Question: 2021/01/07 14:58:44 vid=25a7,pid=fa23,bus=1,addr=40.DefaultInterface(): failed to claim interface 0 on vid=25a7,pid=fa23,bus=1,addr=40,config=1: libusb: not found [code -5]
OS :5.4.85-1-ARCHLINUX #1 SMP PREEMPT Mon Dec 21 21:38:53 UTC 2020 x86_64 GNU/Linux
Others:it can read usb configuration and interface information, but cannot claim.So what can I do to deal with it.Thanks.XD..

Compiling for windows:amd64 failed

Got the error when tried compiling this code for Windows amd64 platform on mac os

$ GOOS=windows GOARCH=amd64 go build -o get_usb.exe get_usb.go
# github.com/google/gousb
../../go/src/github.com/google/gousb/config.go:40:11: undefined: Milliamperes
../../go/src/github.com/google/gousb/endpoint.go:44:12: undefined: EndpointDirection
../../go/src/github.com/google/gousb/endpoint.go:48:15: undefined: TransferType
../../go/src/github.com/google/gousb/endpoint.go:54:14: undefined: IsoSyncType
../../go/src/github.com/google/gousb/endpoint.go:56:12: undefined: UsageType
../../go/src/github.com/google/gousb/interface.go:47:8: undefined: Class
../../go/src/github.com/google/gousb/interface.go:49:11: undefined: Class
../../go/src/github.com/google/gousb/interface.go:51:11: undefined: Protocol

P.S.
and for linux too

Feature request - Support detach_kernel_driver function

I need a handler on the gousb library to call the linux function "libusb_detach_kernel_driver", just as jpoirier does in his library (https://github.com/jpoirier/gousb/blob/master/usb/kerneldriver_linux.go). This will prevent my program from giving me a libusb: device or resource busy [code -6] error when I call dev.Config(1). For now, I have to detach the device driver by hand to be able to run my program.

Should It try to perform a pull request with the addition of that code to this library? Or could someone implement it please?

Thanks in advance.

Device exists but returns "not_found" error

devices, err := ctx.OpenDevices(func (desc *gousb.DeviceDesc) bool {
		if desc.Vendor == gousb.ID(0x04e8) && desc.Product == gousb.ID(0x6860) {
			fmt.Println("found!")
			return true
		}
		return false
	})

This code prints a "found!" message. But len(devices) is zero and "not_found" error occurred. Is there a limit of supporting devices? Or Is there a bug? The device I want to communicate with is Samsung Galaxy J7 2016.

panic: libusb: not found [code -5]

Hot Plug Support

Any interest in the participants from kylelemons/gousb#9 (@zagrodzki , @nkovacs, et al) reviving the work on the hotplug event support in this version?

(My own golang/c skills are woefully inadequate to help in anything much besides testing and moral support, but I would be very interested in this feature for a project I'm flailing around with.)

URB_CONTROL in

Hello!

I'm trying to reverse-engineer a windows-only USB data transfer protocol of one of my devices.

I see a bunch of URB_CONTROL requests / replies on endpoint 0x00 (OUT) and 0x80 (IN). I'm confused though on how I can select the endpoint 0x80 with func (d *Device) Control(rType, request uint8, val, idx uint16, data []byte) (int, error).

May you please help me sorting this out?

Thanks :)

EDIT: the default interface has 1 alternative configuration with 2 endpoints available: 0x00(1,OUT) and 0x81(1,IN)

libusb: bad access [code -3] on Mac OS

OS Catalina 10.15.3, go1.14 darwin/amd64

HID device - Delcom Buttom (recognized as keyboard)

[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.008318] [00000307] libusb: debug [libusb_get_device_list]
[ 0.008371] [00001103] libusb: debug [libusb_get_next_timeout] no URBs, no timeout!
[ 0.008376] [00000307] libusb: debug [libusb_get_device_descriptor]
[ 0.008392] [00001103] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[ 0.008394] [00000307] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.008407] [00001103] libusb: debug [handle_events] poll fds modified, reallocating
[ 0.008414] [00000307] libusb: debug [libusb_open] open 20.1
[ 0.008425] [00001103] libusb: debug [handle_events] poll() 1 fds with timeout in 100ms
[ 0.008486] [00000307] libusb: debug [darwin_open] device open for access
[ 0.008493] [00000307] libusb: debug [libusb_get_device_descriptor]
[ 0.008495] [00000307] libusb: debug [libusb_get_config_descriptor] index 0
[ 0.008508] [00000307] libusb: debug [libusb_get_configuration]
[ 0.008510] [00000307] libusb: debug [libusb_get_configuration] active config 1
[ 0.008515] [00000307] libusb: debug [libusb_claim_interface] interface 0
[ 0.008922] [00000307] libusb: error [darwin_claim_interface] USBInterfaceOpen: another process has device opened for exclusive access
2020/03/13 13:56:07 failed to claim interface 0 on vid=0fc5,pid=b080,bus=20,addr=1,config=1: libusb: bad access [code -3] IFC

Is this intended behavior for Mac OS?

libusb.h: No such file or directory

When building

github.com\google\gousb\constants.go:18:21: fatal error: libusb.h: No such file or directory
github.com\google\gousb\libusb.go:28:20: fatal error: libusb.h: No such file or directory
github.com\google\gousb\libusb.go:28:20: fatal error: libusb.h: No such file or directory

pkg-config --cflags --libs libusb-1.0
-IC:\data\Go\include\libusb-1.0 -LC:\data\Go\lib\windows_amd64\libusb-1.0 -lusb-1.0 -Wl,-rpath -Wl,$ORIGIN

Claiming interface on current configuration

Hello!
I am trying to write a userspace driver in go for a composite usb device using your library.
I want to claim one interface using gousb while the second interface resides opened by the kernel's cdc-acm driver.

I am having troubles because gousb always resets my device when using the Config(int) call (due to libusb.setConfig()) - and the cdc-acm driver gets unloaded when doing so.

According to the caveats page of libusb a possible solution to avoid soft resetting the device is to use libusb_get_configuration().
Maybe i have overlooked something but i can not seem to find this possibility in gousb.
I have forked your library and included a check that provides me with this needed functionality. I will create a PR so that you can evaluate my solution.

Thanks!

cc1.exe: sorry, unimplemented: 64-bit mode not compiled in

Hi! Trying to install it on Windows 10 64-bit.
Got this error:
cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
No matter if I use 32-bit or 64-bit GCC:

Using built-in specs.
COLLECT_GCC=gcc.exe
Target: i686-w64-mingw32
Configured with: ../gcc-4.8.3/configure --prefix=/opt/windows_32 --with-sysroot=/opt/windows_32 --libdir=/opt/windows_32/lib --mandir=/opt/windows_32/man --infodir=/opt/windows_32/info --enable-shared --disable-bootstrap --disable-multilib --with-arch=pentium3 --enable-threads=posix --enable-languages=c,c++ --enable-checking=release --enable-libgomp --with-system-zlib --with-python-dir=/lib/python2.7/site-packages --disable-libunwind-exceptions --enable-__cxa_atexit --enable-libssp --with-gnu-ld --verbose --enable-java-home --with-java-home=/opt/windows_32/lib/jvm/jre --with-jvm-root-dir=/opt/windows_32/lib/jvm --with-jvm-jar-dir=/opt/windows_32/lib/jvm/jvm-exports --with-arch-directory=amd64 --with-antlr-jar='/home/adrien/projects/win-builds-1.5/slackware64-current/d/gcc/antlr-*.jar' --disable-java-awt --disable-gtktest --build=x86_64-slackware-linux --host=i686-w64-mingw32 --target=i686-w64-mingw32
Thread model: posix
gcc version 4.8.3 (GCC)

or

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/6.3.0/lto-wrapper.exe
Target: mingw32
Configured with: ../src/gcc-6.3.0/configure --build=x86_64-pc-linux-gnu --host=mingw32 --target=mingw32 --with-gmp=/mingw --with-mpfr --with-mpc=/mingw --with-isl=/mingw --prefix=/mingw --disable-win32-registry --with-arch=i586 --with-tune=generic --enable-languages=c,c++,objc,obj-c++,fortran,ada --with-pkgversion='MinGW.org GCC-6.3.0-1' --enable-static --enable-shared --enable-threads --with-dwarf2 --disable-sjlj-exceptions --enable-version-specific-runtime-libs --with-libiconv-prefix=/mingw --with-libintl-prefix=/mingw --enable-libstdcxx-debug --enable-libgomp --disable-libvtv --enable-nls
Thread model: win32
gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)

How to fix that?
I prefer to get 32-bit version of Gousb.

Feature Request: Cancellable API

Has there been thought put into an Async API? I'd like to be able to queue an RX transaction and either receive notification or the packet itself on a channel.

Setting an alternate setting of 0 when claiming interface locks up USB device.

This is likely an issue with the USB device I'm using (YARD Stick One), but when claiming an interface
(calling *Config.Interface) and providing 0 for alt, gousb is calling libusb_set_interface_alt_setting which locks up the device. Because 0 is the default there's no need to explicitly set the interface alt setting, and as such the lockup can be avoided by not making that call. The change to only call lib_usb_set_interface_alt_setting when alt != 0 seems harmless and would allow this to work, but I'm not all that familiar with libusb so I may be missing why it's not possible to avoid the call.

diff --git a/config.go b/config.go
index 70e2330..5eb0f76 100644
--- a/config.go
+++ b/config.go
@@ -124,9 +124,11 @@ func (c *Config) Interface(num, alt int) (*Interface, error) {
        return nil, fmt.Errorf("failed to claim interface %d on %s: %v", num, c, err)
    }

-	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)
+	if alt != 0 {
+		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

Export fakelibusb test code

I would like to use fakelibusb_test.go in my USB code for unit testing as it seems pretty cool for mocking actual USB code.
Can you maybe put it into a library so I can import it and use it for unit testing?

libusb: bad access [code -3]

I am getting libusb: bad access [code -3], please find source code below. It's not returning any open device, even when I am returning true. devices are always 0... Please advise to fix the issue

ctx := gousb.NewContext()
	defer ctx.Close()

	devices, err := ctx.OpenDevices(func (desc *gousb.DeviceDesc) bool {
		if strings.Contains(usbid.Describe(desc),"SM-USB-DIG (Texas Instruments, Inc.)") {
			return true
		}
		return false
	})

	// All Devices returned from OpenDevices must be closed.
	defer func() {
		for _, d := range devices {
			d.Close()
		}
	}()

	for _, dev := range devices {
		// Once the device has been selected from OpenDevices, it is opened
		// and can be interacted with.
		manufacturer, err := dev.Manufacturer()
		if err!=nil {
			fmt.Println("err: %s",err)
		}else {
			fmt.Println("Manufacturer: %s",manufacturer)
		}

		//fmt.Printf("%03d.%03d %s:%s %s\n", dev.Bus, desc.Address, desc.Vendor, desc.Product, usbid.Describe(desc))
		//fmt.Printf("  Protocol: %s\n", usbid.Classify(desc))

		_ = dev
	}

	// OpenDevices can occaionally fail, so be sure to check its return value.
	if err != nil {
		log.Fatalf("list: %s", err) 
	}```

ERROR: Unknown revision v2.1.0

Hi there!

When installing gousb using
"go get -v github.com/google/gousb" (as written in the Readme on GitHub) I just get the error "go: error loading module requirements"...
(See screenshot.)

Is there a workaround for this problem?
grafik

Windows

Got this working on my MAC pretty much straight away. Have spent hours trying to get it working on Windows. The instructions are not clear. Still have no idea what I should be doing to get libusb installed

When I cross compile for windows on my MAC I get lots of compile errors eg. undefined Milliamperes. Is the windows library different?

Better Control() interface with data

Hi,

I found several problems in passing data to Device.Control() as a slice of bytes:

  1. Control requests are generally used to pass low-level data types, but since Go doesn't support packed structures, they are implemented as packed C types. But CGo doesn't support packed C structures either. Which means that it is impossible to read the data from this slice in any standard Go way.
  2. This byte slice is passed to the libusb by reading the SliceHeader structure, which is Go's implementation-defined.
  3. When writing portable standard Go, it requires making at least two copies of the data: slice -> C struct -> optionally Go struct when C struct is not packed.

Here is an example of a C struct that cannot be correctly accessed from Go - this is the one with I started having problems with current interface:

struct hub_descriptor {
    uint8_t  DescLength;
    uint8_t  DescriptorType;
    uint8_t  NbrPorts;
    uint16_t HubCharacteristics;
    uint8_t  PwrOn2PwrGood;
    uint8_t  HubContrCurrent;
} __attribute__((packed));

Its HubCharacteristics field appears as _ in Go. It is thus ignored by encoding/binary.Read() function... For the record, C getter functions need to be written to read fields from a packed structure.

So I modified gousb to get rid of the 3 problems I listed previously. There are two implementation options I see:

  1. Changing data's type to interface{} and use unsafe.Pointer(reflect.ValueOf(data).Pointer()). The advantage of this option is that we are now able to pass both slices and pointers to structures and int types, i.e. the two main types used with Control(). Note that it also requires one more argument to provide the size of data, since we cannot now the size of such types using interface{}.
  2. Changing data's type to uintptr, and letting users getting it.

I am personally using option 1 for now. If you guys agree, I can push the modifications in a PR.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.