diff options
author | Péter Szilágyi <peterke@gmail.com> | 2019-06-01 22:19:47 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2019-06-04 23:04:55 +0800 |
commit | 5d68400cad8cda3b265d2bc9d45223b303349023 (patch) | |
tree | 49a7b41a221cfb71739bb1587c69e66176e34b91 /vendor/github.com/karalabe/usb/hid_enabled.go | |
parent | b4cc7b660cfaee01da625ed5f09ce2b9d34933ba (diff) | |
download | go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.tar go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.tar.gz go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.tar.bz2 go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.tar.lz go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.tar.xz go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.tar.zst go-tangerine-5d68400cad8cda3b265d2bc9d45223b303349023.zip |
accounts/usbwallet, vendor: switch from HID to generic USB lib
Diffstat (limited to 'vendor/github.com/karalabe/usb/hid_enabled.go')
-rw-r--r-- | vendor/github.com/karalabe/usb/hid_enabled.go | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/vendor/github.com/karalabe/usb/hid_enabled.go b/vendor/github.com/karalabe/usb/hid_enabled.go new file mode 100644 index 000000000..c2b372098 --- /dev/null +++ b/vendor/github.com/karalabe/usb/hid_enabled.go @@ -0,0 +1,187 @@ +// usb - Self contained USB and HID library for Go +// Copyright 2017 The library Authors +// +// This library is free software: you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) any +// later version. +// +// The library is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License along +// with the library. If not, see <http://www.gnu.org/licenses/>. + +// +build freebsd,cgo linux,cgo darwin,!ios,cgo windows,cgo + +package usb + +/* +#include <stdlib.h> +#include "./hidapi/hidapi/hidapi.h" +*/ +import "C" + +import ( + "errors" + "runtime" + "sync" + "unsafe" +) + +// enumerateHid 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 enumerateHid(vendorID uint16, productID uint16) ([]DeviceInfo, error) { + // 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, 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{ + Path: C.GoString(head.path), + VendorID: uint16(head.vendor_id), + ProductID: uint16(head.product_id), + Release: uint16(head.release_number), + UsagePage: uint16(head.usage_page), + Usage: uint16(head.usage), + Interface: int(head.interface_number), + } + if head.serial_number != nil { + info.Serial, _ = wcharTToString(head.serial_number) + } + if head.product_string != nil { + info.Product, _ = wcharTToString(head.product_string) + } + if head.manufacturer_string != nil { + info.Manufacturer, _ = wcharTToString(head.manufacturer_string) + } + infos = append(infos, info) + } + return infos, nil +} + +// openHid connects to an HID device by its path name. +func openHid(info DeviceInfo) (*hidDevice, error) { + path := C.CString(info.Path) + defer C.free(unsafe.Pointer(path)) + + device := C.hid_open_path(path) + if device == nil { + return nil, errors.New("hidapi: failed to open device") + } + return &hidDevice{ + DeviceInfo: info, + device: device, + }, nil +} + +// 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 + lock sync.Mutex +} + +// Close releases the HID USB device handle. +func (dev *hidDevice) Close() error { + dev.lock.Lock() + defer dev.lock.Unlock() + + if dev.device != nil { + C.hid_close(dev.device) + dev.device = nil + } + return nil +} + +// Write sends an output report to a HID device. +// +// 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 *hidDevice) Write(b []byte) (int, error) { + // Abort if nothing to write + if len(b) == 0 { + return 0, nil + } + // Abort if device closed in between + dev.lock.Lock() + device := dev.device + dev.lock.Unlock() + + if device == nil { + return 0, ErrDeviceClosed + } + // Prepend a HID report ID on Windows, other OSes don't need it + var report []byte + if runtime.GOOS == "windows" { + report = append([]byte{0x00}, b...) + } else { + report = b + } + // Execute the write operation + written := int(C.hid_write(device, (*C.uchar)(&report[0]), C.size_t(len(report)))) + if written == -1 { + // If the write failed, verify if closed or other error + dev.lock.Lock() + device = dev.device + dev.lock.Unlock() + + if device == nil { + return 0, ErrDeviceClosed + } + // Device not closed, some other error occurred + message := C.hid_error(device) + if message == nil { + return 0, errors.New("hidapi: unknown failure") + } + failure, _ := wcharTToString(message) + return 0, errors.New("hidapi: " + failure) + } + return written, nil +} + +// Read retrieves an input report from a HID device. +func (dev *hidDevice) Read(b []byte) (int, error) { + // Aborth if nothing to read + if len(b) == 0 { + return 0, nil + } + // Abort if device closed in between + dev.lock.Lock() + device := dev.device + dev.lock.Unlock() + + if device == nil { + return 0, ErrDeviceClosed + } + // Execute the read operation + read := int(C.hid_read(device, (*C.uchar)(&b[0]), C.size_t(len(b)))) + if read == -1 { + // If the read failed, verify if closed or other error + dev.lock.Lock() + device = dev.device + dev.lock.Unlock() + + if device == nil { + return 0, ErrDeviceClosed + } + // Device not closed, some other error occurred + message := C.hid_error(device) + if message == nil { + return 0, errors.New("hidapi: unknown failure") + } + failure, _ := wcharTToString(message) + return 0, errors.New("hidapi: " + failure) + } + return read, nil +} |