accounts/usbwallet: support webusb for Trezor wallets
This commit is contained in:
		
				
					committed by
					
						
						Péter Szilágyi
					
				
			
			
				
	
			
			
			
						parent
						
							7a22da98b9
						
					
				
				
					commit
					4799b5abd4
				
			
							
								
								
									
										54
									
								
								vendor/github.com/karalabe/hid/generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								vendor/github.com/karalabe/hid/generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
// hid - Gopher Interface Devices (USB HID)
 | 
			
		||||
// Copyright (c) 2019 Péter Szilágyi, Guillaume Ballet. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package hid
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"C"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type GenericEndpointDirection uint8
 | 
			
		||||
 | 
			
		||||
// List of endpoint direction types
 | 
			
		||||
const (
 | 
			
		||||
	GenericEndpointDirectionOut = 0x00
 | 
			
		||||
	GenericEndpointDirectionIn  = 0x80
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// List of endpoint attributes
 | 
			
		||||
const (
 | 
			
		||||
	GenericEndpointAttributeInterrupt = 3
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GenericEndpoint represents a USB endpoint
 | 
			
		||||
type GenericEndpoint struct {
 | 
			
		||||
	Address    uint8
 | 
			
		||||
	Direction  GenericEndpointDirection
 | 
			
		||||
	Attributes uint8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GenericDeviceInfo struct {
 | 
			
		||||
	Path      string // Platform-specific device path
 | 
			
		||||
	VendorID  uint16 // Device Vendor ID
 | 
			
		||||
	ProductID uint16 // Device Product ID
 | 
			
		||||
 | 
			
		||||
	device *GenericDevice
 | 
			
		||||
 | 
			
		||||
	Interface int
 | 
			
		||||
 | 
			
		||||
	Endpoints []GenericEndpoint
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (gdi *GenericDeviceInfo) Type() DeviceType {
 | 
			
		||||
	return DeviceTypeGeneric
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Platform-specific device path
 | 
			
		||||
func (gdi *GenericDeviceInfo) GetPath() string {
 | 
			
		||||
	return gdi.Path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IDs returns the vendor and product IDs for the device
 | 
			
		||||
func (gdi *GenericDeviceInfo) IDs() (uint16, uint16, int, uint16) {
 | 
			
		||||
	return gdi.VendorID, gdi.ProductID, gdi.Interface, 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								vendor/github.com/karalabe/hid/hid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/github.com/karalabe/hid/hid.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -17,8 +17,8 @@ var ErrDeviceClosed = errors.New("hid: device closed")
 | 
			
		||||
// operating system is not supported by the library.
 | 
			
		||||
var ErrUnsupportedPlatform = errors.New("hid: unsupported platform")
 | 
			
		||||
 | 
			
		||||
// DeviceInfo is a hidapi info structure.
 | 
			
		||||
type DeviceInfo struct {
 | 
			
		||||
// HidDeviceInfo is a hidapi info structure.
 | 
			
		||||
type HidDeviceInfo struct {
 | 
			
		||||
	Path         string // Platform-specific device path
 | 
			
		||||
	VendorID     uint16 // Device Vendor ID
 | 
			
		||||
	ProductID    uint16 // Device Product ID
 | 
			
		||||
@@ -35,3 +35,18 @@ type DeviceInfo struct {
 | 
			
		||||
	// only if the device contains more than one interface.
 | 
			
		||||
	Interface int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPath returns the system-dependent path to the device
 | 
			
		||||
func (hdi *HidDeviceInfo) GetPath() string {
 | 
			
		||||
	return hdi.Path
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IDs returns the vendor and product id of the device
 | 
			
		||||
func (hdi *HidDeviceInfo) IDs() (uint16, uint16, int, uint16) {
 | 
			
		||||
	return hdi.VendorID, hdi.ProductID, hdi.Interface, hdi.UsagePage
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Type returns the type of the device (HID or generic)
 | 
			
		||||
func (hdi *HidDeviceInfo) Type() DeviceType {
 | 
			
		||||
	return DeviceTypeHID
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/github.com/karalabe/hid/hid_disabled.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/karalabe/hid/hid_disabled.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
// This file is released under the 3-clause BSD license. Note however that Linux
 | 
			
		||||
// support depends on libusb, released under GNU LGPL 2.1 or later.
 | 
			
		||||
 | 
			
		||||
// +build !linux,!darwin,!windows ios !cgo
 | 
			
		||||
// +build !freebsd,!linux,!darwin,!windows ios !cgo
 | 
			
		||||
 | 
			
		||||
package hid
 | 
			
		||||
 | 
			
		||||
@@ -22,30 +22,55 @@ func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Device is a live HID USB connected device handle. On platforms that this file
 | 
			
		||||
// HidDevice is a live HID USB connected device handle. On platforms that this file
 | 
			
		||||
// implements the type lacks the actual HID device and all methods are noop.
 | 
			
		||||
type Device struct {
 | 
			
		||||
	DeviceInfo // Embed the infos for easier access
 | 
			
		||||
type HidDevice struct {
 | 
			
		||||
	HidDeviceInfo // Embed the infos for easier access
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open connects to an HID device by its path name. On platforms that this file
 | 
			
		||||
// implements the method just returns an error.
 | 
			
		||||
func (info DeviceInfo) Open() (*Device, error) {
 | 
			
		||||
func (info HidDeviceInfo) Open() (*Device, error) {
 | 
			
		||||
	return nil, ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close releases the HID USB device handle. On platforms that this file implements
 | 
			
		||||
// the method is just a noop.
 | 
			
		||||
func (dev *Device) Close() error { return nil }
 | 
			
		||||
func (dev *HidDevice) Close() error { return ErrUnsupportedPlatform }
 | 
			
		||||
 | 
			
		||||
// Write sends an output report to a HID device. On platforms that this file
 | 
			
		||||
// implements the method just returns an error.
 | 
			
		||||
func (dev *Device) Write(b []byte) (int, error) {
 | 
			
		||||
func (dev *HidDevice) Write(b []byte) (int, error) {
 | 
			
		||||
	return 0, ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read retrieves an input report from a HID device. On platforms that this file
 | 
			
		||||
// implements the method just returns an error.
 | 
			
		||||
func (dev *Device) Read(b []byte) (int, error) {
 | 
			
		||||
func (dev *HidDevice) Read(b []byte) (int, error) {
 | 
			
		||||
	return 0, ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open tries to open the USB device represented by the current DeviceInfo
 | 
			
		||||
func (gdi *GenericDeviceInfo) Open() (Device, error) {
 | 
			
		||||
	return nil, ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenericDevice represents a generic USB device
 | 
			
		||||
type GenericDevice struct {
 | 
			
		||||
	*GenericDeviceInfo // Embed the infos for easier access
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write implements io.ReaderWriter
 | 
			
		||||
func (gd *GenericDevice) Write(b []byte) (int, error) {
 | 
			
		||||
	return 0, ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read implements io.ReaderWriter
 | 
			
		||||
func (gd *GenericDevice) Read(b []byte) (int, error) {
 | 
			
		||||
	return 0, ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close a previously opened generic USB device
 | 
			
		||||
func (gd *GenericDevice) Close() error {
 | 
			
		||||
	return ErrUnsupportedPlatform
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										263
									
								
								vendor/github.com/karalabe/hid/hid_enabled.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										263
									
								
								vendor/github.com/karalabe/hid/hid_enabled.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@
 | 
			
		||||
// This file is released under the 3-clause BSD license. Note however that Linux
 | 
			
		||||
// support depends on libusb, released under LGNU GPL 2.1 or later.
 | 
			
		||||
 | 
			
		||||
// +build linux,cgo darwin,!ios,cgo windows,cgo
 | 
			
		||||
// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo
 | 
			
		||||
 | 
			
		||||
package hid
 | 
			
		||||
 | 
			
		||||
@@ -13,13 +13,15 @@ package hid
 | 
			
		||||
 | 
			
		||||
#cgo linux CFLAGS: -I./libusb/libusb -DDEFAULT_VISIBILITY="" -DOS_LINUX -D_GNU_SOURCE -DPOLL_NFDS_TYPE=int
 | 
			
		||||
#cgo linux,!android LDFLAGS: -lrt
 | 
			
		||||
#cgo darwin CFLAGS: -DOS_DARWIN
 | 
			
		||||
#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit
 | 
			
		||||
#cgo darwin CFLAGS: -DOS_DARWIN -I./libusb/libusb
 | 
			
		||||
#cgo darwin LDFLAGS: -framework CoreFoundation -framework IOKit -lusb-1.0.0
 | 
			
		||||
#cgo windows CFLAGS: -DOS_WINDOWS
 | 
			
		||||
#cgo windows LDFLAGS: -lsetupapi
 | 
			
		||||
#cgo freebsd CFLAGS: -DOS_FREEBSD
 | 
			
		||||
#cgo freebsd LDFLAGS: -lusb
 | 
			
		||||
 | 
			
		||||
#ifdef OS_LINUX
 | 
			
		||||
	#include <sys/poll.h>
 | 
			
		||||
	#include <poll.h>
 | 
			
		||||
	#include "os/threads_posix.c"
 | 
			
		||||
	#include "os/poll_posix.c"
 | 
			
		||||
 | 
			
		||||
@@ -35,15 +37,50 @@ package hid
 | 
			
		||||
 | 
			
		||||
	#include "hidapi/libusb/hid.c"
 | 
			
		||||
#elif OS_DARWIN
 | 
			
		||||
	#include <libusb.h>
 | 
			
		||||
	#include "hidapi/mac/hid.c"
 | 
			
		||||
#elif OS_WINDOWS
 | 
			
		||||
	#include "hidapi/windows/hid.c"
 | 
			
		||||
#elif OS_FREEBSD
 | 
			
		||||
    #include <stdlib.h>
 | 
			
		||||
	#include <libusb.h>
 | 
			
		||||
	#include "hidapi/libusb/hid.c"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(OS_LINUX) || defined(OS_WINDOWS)
 | 
			
		||||
	void copy_device_list_to_slice(struct libusb_device **data, struct libusb_device **list, int count)
 | 
			
		||||
	{
 | 
			
		||||
		int i;
 | 
			
		||||
		struct libusb_device *current = *list;
 | 
			
		||||
		for (i=0; i<count; i++)
 | 
			
		||||
		{
 | 
			
		||||
			 data[i] = current;
 | 
			
		||||
			 current = list_entry(current->list.next, struct libusb_device, list);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#elif defined(OS_DARWIN) || defined(OS_FREEBSD)
 | 
			
		||||
	void copy_device_list_to_slice(struct libusb_device **data, struct libusb_device **list, int count)
 | 
			
		||||
	{
 | 
			
		||||
		int i;
 | 
			
		||||
		// No memcopy because the struct size isn't available for a sizeof()
 | 
			
		||||
		for (i=0; i<count; i++)
 | 
			
		||||
		{
 | 
			
		||||
			data[i] = list[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const char *usb_strerror(int err)
 | 
			
		||||
{
 | 
			
		||||
	return libusb_strerror(err);
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
@@ -65,26 +102,132 @@ func Supported() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// genericEnumerate performs generic USB device enumeration
 | 
			
		||||
func genericEnumerate(vendorID uint16, productID uint16) ([]DeviceInfo, error) {
 | 
			
		||||
	var infos []DeviceInfo
 | 
			
		||||
	var ctx *C.struct_libusb_context
 | 
			
		||||
	errCode := int(C.libusb_init((**C.struct_libusb_context)(&ctx)))
 | 
			
		||||
	if errCode < 0 {
 | 
			
		||||
		return nil, fmt.Errorf("Error while initializing libusb: %d", errCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var deviceListPtr **C.struct_libusb_device
 | 
			
		||||
	count := C.libusb_get_device_list(ctx, (***C.struct_libusb_device)(&deviceListPtr))
 | 
			
		||||
	if count < 0 {
 | 
			
		||||
		return nil, fmt.Errorf("Error code listing devices: %d", count)
 | 
			
		||||
	}
 | 
			
		||||
	defer C.libusb_free_device_list(deviceListPtr, C.int(count))
 | 
			
		||||
 | 
			
		||||
	deviceList := make([]*C.struct_libusb_device, count)
 | 
			
		||||
	dlhdr := (*reflect.SliceHeader)(unsafe.Pointer(&deviceList))
 | 
			
		||||
	C.copy_device_list_to_slice((**C.struct_libusb_device)(unsafe.Pointer(dlhdr.Data)), deviceListPtr, C.int(count))
 | 
			
		||||
 | 
			
		||||
	for devnum, dev := range deviceList {
 | 
			
		||||
		var desc C.struct_libusb_device_descriptor
 | 
			
		||||
		errCode := int(C.libusb_get_device_descriptor(dev, &desc))
 | 
			
		||||
		if errCode < 0 {
 | 
			
		||||
			return nil, fmt.Errorf("Error getting device descriptor for generic device %d: %d", devnum, errCode)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Start by checking the vendor id and the product id if necessary
 | 
			
		||||
		if uint16(desc.idVendor) != vendorID || !(productID == 0 || uint16(desc.idProduct) == productID) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Skip HID devices, they will be handled later
 | 
			
		||||
		switch desc.bDeviceClass {
 | 
			
		||||
		case 0:
 | 
			
		||||
			/* Device class is specified at interface level */
 | 
			
		||||
			for cfgnum := 0; cfgnum < int(desc.bNumConfigurations); cfgnum++ {
 | 
			
		||||
				var cfgdesc *C.struct_libusb_config_descriptor
 | 
			
		||||
				errCode = int(C.libusb_get_config_descriptor(dev, C.uint8_t(cfgnum), &cfgdesc))
 | 
			
		||||
				if errCode != 0 {
 | 
			
		||||
					return nil, fmt.Errorf("Error getting device configuration #%d for generic device %d: %d", cfgnum, devnum, errCode)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var ifs []C.struct_libusb_interface
 | 
			
		||||
				ifshdr := (*reflect.SliceHeader)(unsafe.Pointer(&ifs))
 | 
			
		||||
				ifshdr.Cap = int(cfgdesc.bNumInterfaces)
 | 
			
		||||
				ifshdr.Len = int(cfgdesc.bNumInterfaces)
 | 
			
		||||
				ifshdr.Data = uintptr(unsafe.Pointer(cfgdesc._interface))
 | 
			
		||||
 | 
			
		||||
				for ifnum, ifc := range ifs {
 | 
			
		||||
					var ifdescs []C.struct_libusb_interface_descriptor
 | 
			
		||||
					ifdshdr := (*reflect.SliceHeader)(unsafe.Pointer(&ifdescs))
 | 
			
		||||
					ifdshdr.Cap = int(ifc.num_altsetting)
 | 
			
		||||
					ifdshdr.Len = int(ifc.num_altsetting)
 | 
			
		||||
					ifdshdr.Data = uintptr(unsafe.Pointer(ifc.altsetting))
 | 
			
		||||
 | 
			
		||||
					for _, alt := range ifdescs {
 | 
			
		||||
						if alt.bInterfaceClass != 3 {
 | 
			
		||||
							// Device isn't a HID interface, add them to the device list.
 | 
			
		||||
 | 
			
		||||
							var endps []C.struct_libusb_endpoint_descriptor
 | 
			
		||||
							endpshdr := (*reflect.SliceHeader)(unsafe.Pointer(&endps))
 | 
			
		||||
							endpshdr.Cap = int(alt.bNumEndpoints)
 | 
			
		||||
							endpshdr.Len = int(alt.bNumEndpoints)
 | 
			
		||||
							endpshdr.Data = uintptr(unsafe.Pointer(alt.endpoint))
 | 
			
		||||
 | 
			
		||||
							endpoints := make([]GenericEndpoint, alt.bNumEndpoints)
 | 
			
		||||
 | 
			
		||||
							for ne, endpoint := range endps {
 | 
			
		||||
								endpoints[ne] = GenericEndpoint{
 | 
			
		||||
									Direction:  GenericEndpointDirection(endpoint.bEndpointAddress) & GenericEndpointDirectionIn,
 | 
			
		||||
									Address:    uint8(endpoint.bEndpointAddress),
 | 
			
		||||
									Attributes: uint8(endpoint.bmAttributes),
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
							info := &GenericDeviceInfo{
 | 
			
		||||
								Path:      fmt.Sprintf("%x:%x:%d", vendorID, uint16(desc.idProduct), uint8(C.libusb_get_port_number(dev))),
 | 
			
		||||
								VendorID:  uint16(desc.idVendor),
 | 
			
		||||
								ProductID: uint16(desc.idProduct),
 | 
			
		||||
								device: &GenericDevice{
 | 
			
		||||
									device: dev,
 | 
			
		||||
								},
 | 
			
		||||
								Endpoints: endpoints,
 | 
			
		||||
								Interface: ifnum,
 | 
			
		||||
							}
 | 
			
		||||
							info.device.GenericDeviceInfo = info
 | 
			
		||||
							infos = append(infos, info)
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case 3:
 | 
			
		||||
			// Device class is HID, skip it
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return infos, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Enumerate returns a list of all the HID devices attached to the system which
 | 
			
		||||
// match the vendor and product id:
 | 
			
		||||
//  - If the vendor id is set to 0 then any vendor matches.
 | 
			
		||||
//  - If the product id is set to 0 then any product matches.
 | 
			
		||||
//  - If the vendor and product id are both 0, all HID devices are returned.
 | 
			
		||||
func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
 | 
			
		||||
func Enumerate(vendorID uint16, productID uint16) ([]DeviceInfo, error) {
 | 
			
		||||
	enumerateLock.Lock()
 | 
			
		||||
	defer enumerateLock.Unlock()
 | 
			
		||||
 | 
			
		||||
	infos, err := genericEnumerate(vendorID, productID)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Gather all device infos and ensure they are freed before returning
 | 
			
		||||
	head := C.hid_enumerate(C.ushort(vendorID), C.ushort(productID))
 | 
			
		||||
	if head == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	defer C.hid_free_enumeration(head)
 | 
			
		||||
 | 
			
		||||
	// Iterate the list and retrieve the device details
 | 
			
		||||
	var infos []DeviceInfo
 | 
			
		||||
	for ; head != nil; head = head.next {
 | 
			
		||||
		info := DeviceInfo{
 | 
			
		||||
		info := &HidDeviceInfo{
 | 
			
		||||
			Path:      C.GoString(head.path),
 | 
			
		||||
			VendorID:  uint16(head.vendor_id),
 | 
			
		||||
			ProductID: uint16(head.product_id),
 | 
			
		||||
@@ -104,11 +247,11 @@ func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
 | 
			
		||||
		}
 | 
			
		||||
		infos = append(infos, info)
 | 
			
		||||
	}
 | 
			
		||||
	return infos
 | 
			
		||||
	return infos, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open connects to an HID device by its path name.
 | 
			
		||||
func (info DeviceInfo) Open() (*Device, error) {
 | 
			
		||||
func (info *HidDeviceInfo) Open() (Device, error) {
 | 
			
		||||
	enumerateLock.Lock()
 | 
			
		||||
	defer enumerateLock.Unlock()
 | 
			
		||||
 | 
			
		||||
@@ -119,14 +262,14 @@ func (info DeviceInfo) Open() (*Device, error) {
 | 
			
		||||
	if device == nil {
 | 
			
		||||
		return nil, errors.New("hidapi: failed to open device")
 | 
			
		||||
	}
 | 
			
		||||
	return &Device{
 | 
			
		||||
	return &HidDevice{
 | 
			
		||||
		DeviceInfo: info,
 | 
			
		||||
		device:     device,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Device is a live HID USB connected device handle.
 | 
			
		||||
type Device struct {
 | 
			
		||||
// HidDevice is a live HID USB connected device handle.
 | 
			
		||||
type HidDevice struct {
 | 
			
		||||
	DeviceInfo // Embed the infos for easier access
 | 
			
		||||
 | 
			
		||||
	device *C.hid_device // Low level HID device to communicate through
 | 
			
		||||
@@ -134,7 +277,7 @@ type Device struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close releases the HID USB device handle.
 | 
			
		||||
func (dev *Device) Close() error {
 | 
			
		||||
func (dev *HidDevice) Close() error {
 | 
			
		||||
	dev.lock.Lock()
 | 
			
		||||
	defer dev.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
@@ -149,7 +292,7 @@ func (dev *Device) Close() error {
 | 
			
		||||
//
 | 
			
		||||
// Write will send the data on the first OUT endpoint, if one exists. If it does
 | 
			
		||||
// not, it will send the data through the Control Endpoint (Endpoint 0).
 | 
			
		||||
func (dev *Device) Write(b []byte) (int, error) {
 | 
			
		||||
func (dev *HidDevice) Write(b []byte) (int, error) {
 | 
			
		||||
	// Abort if nothing to write
 | 
			
		||||
	if len(b) == 0 {
 | 
			
		||||
		return 0, nil
 | 
			
		||||
@@ -192,7 +335,7 @@ func (dev *Device) Write(b []byte) (int, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read retrieves an input report from a HID device.
 | 
			
		||||
func (dev *Device) Read(b []byte) (int, error) {
 | 
			
		||||
func (dev *HidDevice) Read(b []byte) (int, error) {
 | 
			
		||||
	// Aborth if nothing to read
 | 
			
		||||
	if len(b) == 0 {
 | 
			
		||||
		return 0, nil
 | 
			
		||||
@@ -226,3 +369,91 @@ func (dev *Device) Read(b []byte) (int, error) {
 | 
			
		||||
	}
 | 
			
		||||
	return read, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Type identify the device as a HID device
 | 
			
		||||
func (dev *HidDevice) Type() DeviceType {
 | 
			
		||||
	return dev.DeviceInfo.Type()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open tries to open the USB device represented by the current DeviceInfo
 | 
			
		||||
func (gdi *GenericDeviceInfo) Open() (Device, error) {
 | 
			
		||||
	var handle *C.struct_libusb_device_handle
 | 
			
		||||
	errCode := int(C.libusb_open(gdi.device.device, (**C.struct_libusb_device_handle)(&handle)))
 | 
			
		||||
	if errCode < 0 {
 | 
			
		||||
		return nil, fmt.Errorf("Error opening generic USB device %v, code %d", gdi.device.handle, errCode)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gdi.device.handle = handle
 | 
			
		||||
	// QUESTION: ai-je deja initialie le GDI ?
 | 
			
		||||
	// 	GenericDeviceInfo: gdi,
 | 
			
		||||
	// 	handle:            handle,
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	for _, endpoint := range gdi.Endpoints {
 | 
			
		||||
		switch {
 | 
			
		||||
		case endpoint.Direction == GenericEndpointDirectionOut && endpoint.Attributes == GenericEndpointAttributeInterrupt:
 | 
			
		||||
			gdi.device.WEndpoint = endpoint.Address
 | 
			
		||||
		case endpoint.Direction == GenericEndpointDirectionIn && endpoint.Attributes == GenericEndpointAttributeInterrupt:
 | 
			
		||||
			gdi.device.REndpoint = endpoint.Address
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if gdi.device.REndpoint == 0 || gdi.device.WEndpoint == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("Missing endpoint in device %#x:%#x:%d", gdi.VendorID, gdi.ProductID, gdi.Interface)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gdi.device, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenericDevice represents a generic USB device
 | 
			
		||||
type GenericDevice struct {
 | 
			
		||||
	*GenericDeviceInfo // Embed the infos for easier access
 | 
			
		||||
 | 
			
		||||
	REndpoint uint8
 | 
			
		||||
	WEndpoint uint8
 | 
			
		||||
 | 
			
		||||
	device *C.struct_libusb_device
 | 
			
		||||
	handle *C.struct_libusb_device_handle
 | 
			
		||||
	lock   sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write implements io.ReaderWriter
 | 
			
		||||
func (gd *GenericDevice) Write(b []byte) (int, error) {
 | 
			
		||||
	gd.lock.Lock()
 | 
			
		||||
	defer gd.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	out, err := interruptTransfer(gd.handle, gd.WEndpoint, b)
 | 
			
		||||
	return len(out), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read implements io.ReaderWriter
 | 
			
		||||
func (gd *GenericDevice) Read(b []byte) (int, error) {
 | 
			
		||||
	gd.lock.Lock()
 | 
			
		||||
	defer gd.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	out, err := interruptTransfer(gd.handle, gd.REndpoint, b)
 | 
			
		||||
	return len(out), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close a previously opened generic USB device
 | 
			
		||||
func (gd *GenericDevice) Close() error {
 | 
			
		||||
	gd.lock.Lock()
 | 
			
		||||
	defer gd.lock.Unlock()
 | 
			
		||||
 | 
			
		||||
	if gd.handle != nil {
 | 
			
		||||
		C.libusb_close(gd.handle)
 | 
			
		||||
		gd.handle = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interruptTransfer is a helpler function for libusb's interrupt transfer function
 | 
			
		||||
func interruptTransfer(handle *C.struct_libusb_device_handle, endpoint uint8, data []byte) ([]byte, error) {
 | 
			
		||||
	var transferred C.int
 | 
			
		||||
	errCode := int(C.libusb_interrupt_transfer(handle, (C.uchar)(endpoint), (*C.uchar)(&data[0]), (C.int)(len(data)), &transferred, (C.uint)(0)))
 | 
			
		||||
	if errCode != 0 {
 | 
			
		||||
		return nil, fmt.Errorf("Interrupt transfer error: %s", C.GoString(C.usb_strerror(C.int(errCode))))
 | 
			
		||||
	}
 | 
			
		||||
	return data[:int(transferred)], nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								vendor/github.com/karalabe/hid/usb.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/github.com/karalabe/hid/usb.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
// hid - Gopher Interface Devices (USB HID)
 | 
			
		||||
// Copyright (c) 2019 Péter Szilágyi, Guillaume Ballet. All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// This file is released under the 3-clause BSD license. Note however that Linux
 | 
			
		||||
// support depends on libusb, released under GNU LGPL 2.1 or later.
 | 
			
		||||
 | 
			
		||||
// Package usb provide interfaces for generic USB devices.
 | 
			
		||||
package hid
 | 
			
		||||
 | 
			
		||||
// DeviceType represents the type of a USB device (generic or HID)
 | 
			
		||||
type DeviceType int
 | 
			
		||||
 | 
			
		||||
// List of supported device types
 | 
			
		||||
const (
 | 
			
		||||
	DeviceTypeGeneric DeviceType = 0
 | 
			
		||||
	DeviceTypeHID     DeviceType = 1
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Enumerate returns a list of all the HID devices attached to the system which
 | 
			
		||||
// match the vendor and product id:
 | 
			
		||||
//  - If the vendor id is set to 0 then any vendor matches.
 | 
			
		||||
//  - If the product id is set to 0 then any product matches.
 | 
			
		||||
//  - If the vendor and product id are both 0, all HID devices are returned.
 | 
			
		||||
// func Enumerate(vendorID uint16, productID uint16) []DeviceInfo {
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// DeviceInfo is a generic libusb info interface
 | 
			
		||||
type DeviceInfo interface {
 | 
			
		||||
	// Type returns the type of the device (generic or HID)
 | 
			
		||||
	Type() DeviceType
 | 
			
		||||
 | 
			
		||||
	// Platform-specific device path
 | 
			
		||||
	GetPath() string
 | 
			
		||||
 | 
			
		||||
	// IDs returns the vendor and product IDs for the device,
 | 
			
		||||
	// as well as the endpoint id and the usage page.
 | 
			
		||||
	IDs() (uint16, uint16, int, uint16)
 | 
			
		||||
 | 
			
		||||
	// Open tries to open the USB device represented by the current DeviceInfo
 | 
			
		||||
	Open() (Device, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Device is a generic libusb device interface
 | 
			
		||||
type Device interface {
 | 
			
		||||
	Close() error
 | 
			
		||||
 | 
			
		||||
	Write(b []byte) (int, error)
 | 
			
		||||
 | 
			
		||||
	Read(b []byte) (int, error)
 | 
			
		||||
 | 
			
		||||
	// Type returns the type of the device (generic or HID)
 | 
			
		||||
	Type() DeviceType
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/karalabe/hid/wchar.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/karalabe/hid/wchar.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@
 | 
			
		||||
// https://github.com/orofarne/gowchar/blob/master/LICENSE
 | 
			
		||||
 | 
			
		||||
// +build !ios
 | 
			
		||||
// +build linux darwin windows
 | 
			
		||||
// +build freebsd linux darwin windows
 | 
			
		||||
 | 
			
		||||
package hid
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user