hid: fix and test HID enumeration on multiple threads

This commit is contained in:
Péter Szilágyi
2017-08-21 13:23:58 +03:00
parent c8dff1c60e
commit 0e60174ae0
4 changed files with 42 additions and 0 deletions
+1
View File
@@ -22,3 +22,4 @@ matrix:
script:
- go install ./...
- go test -v ./...
+1
View File
@@ -29,3 +29,4 @@ install:
build_script:
- go install ./...
- go test -v ./...
+12
View File
@@ -48,6 +48,15 @@ import (
"unsafe"
)
// enumerateLock is a mutex serializing access to USB device enumeration needed
// by the macOS USB HID system calls, which require 2 consecutive method calls
// for enumeration, causing crashes if called concurrently.
//
// For more details, see:
// https://developer.apple.com/documentation/iokit/1438371-iohidmanagersetdevicematching
// > "subsequent calls will cause the hid manager to release previously enumerated devices"
var enumerateLock sync.Mutex
func init() {
// Initialize the HIDAPI library
C.hid_init()
@@ -66,6 +75,9 @@ func Supported() bool {
// - 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 {
enumerateLock.Lock()
defer enumerateLock.Unlock()
// Gather all device infos and ensure they are freed before returning
head := C.hid_enumerate(C.ushort(vendorID), C.ushort(productID))
if head == nil {
+28
View File
@@ -0,0 +1,28 @@
// hid - Gopher Interface Devices (USB HID)
// Copyright (c) 2017 Péter Szilágyi. 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 hid
import (
"sync"
"testing"
)
// Tests that device enumeration can be called concurrently from multiple threads.
func TestThreadedEnumerate(t *testing.T) {
var pend sync.WaitGroup
for i := 0; i < 8; i++ {
pend.Add(1)
go func(index int) {
defer pend.Done()
for j := 0; j < 512; j++ {
Enumerate(uint16(index), 0)
}
}(i)
}
pend.Wait()
}