diff options
Diffstat (limited to 'vendor')
-rw-r--r-- | vendor/github.com/karalabe/hid/generic.go | 54 | ||||
-rw-r--r-- | vendor/github.com/karalabe/hid/hid.go | 19 | ||||
-rw-r--r-- | vendor/github.com/karalabe/hid/hid_disabled.go | 41 | ||||
-rw-r--r-- | vendor/github.com/karalabe/hid/hid_enabled.go | 263 | ||||
-rw-r--r-- | vendor/github.com/karalabe/hid/usb.go | 53 | ||||
-rw-r--r-- | vendor/github.com/karalabe/hid/wchar.go | 2 | ||||
-rw-r--r-- | vendor/vendor.json | 6 |
7 files changed, 408 insertions, 30 deletions
diff --git a/vendor/github.com/karalabe/hid/generic.go b/vendor/github.com/karalabe/hid/generic.go new file mode 100644 index 000000000..8de16fcbf --- /dev/null +++ b/vendor/github.com/karalabe/hid/generic.go @@ -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 +} diff --git a/vendor/github.com/karalabe/hid/hid.go b/vendor/github.com/karalabe/hid/hid.go index 60a40b8c2..f929006d8 100644 --- a/vendor/github.com/karalabe/hid/hid.go +++ b/vendor/github.com/karalabe/hid/hid.go @@ -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 +} diff --git a/vendor/github.com/karalabe/hid/hid_disabled.go b/vendor/github.com/karalabe/hid/hid_disabled.go index 0f266ba58..ce9827953 100644 --- a/vendor/github.com/karalabe/hid/hid_disabled.go +++ b/vendor/github.com/karalabe/hid/hid_disabled.go @@ -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 +} diff --git a/vendor/github.com/karalabe/hid/hid_enabled.go b/vendor/github.com/karalabe/hid/hid_enabled.go index e95e5792d..ee27ff98d 100644 --- a/vendor/github.com/karalabe/hid/hid_enabled.go +++ b/vendor/github.com/karalabe/hid/hid_enabled.go @@ -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 +} diff --git a/vendor/github.com/karalabe/hid/usb.go b/vendor/github.com/karalabe/hid/usb.go new file mode 100644 index 000000000..5e8768214 --- /dev/null +++ b/vendor/github.com/karalabe/hid/usb.go @@ -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 +} diff --git a/vendor/github.com/karalabe/hid/wchar.go b/vendor/github.com/karalabe/hid/wchar.go index d103beff5..640550ded 100644 --- a/vendor/github.com/karalabe/hid/wchar.go +++ b/vendor/github.com/karalabe/hid/wchar.go @@ -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 diff --git a/vendor/vendor.json b/vendor/vendor.json index a33a1d4e2..2780671cd 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -267,10 +267,10 @@ "revisionTime": "2017-04-30T22:20:11Z" }, { - "checksumSHA1": "6XsjAARQFvlW6dS15al0ibTFPOQ=", + "checksumSHA1": "p6UjFsx/1ACWAhsdEOWrXAHptGY=", "path": "github.com/karalabe/hid", - "revision": "d815e0c1a2e2082a287a2806bc90bc8fc7b276a9", - "revisionTime": "2018-11-28T19:21:57Z", + "revision": "e40407cce1c217644c09da5415bbfb07d330ea5e", + "revisionTime": "2019-05-28T15:16:06Z", "tree": true }, { |