Merge pull request #129 from cmaglie/update-deps-and-golang-support
Update deps and minimum golang support to 1.17
This commit is contained in:
4
.github/workflows/test.yaml
vendored
4
.github/workflows/test.yaml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: "1.13"
|
||||
go-version: "1.17"
|
||||
- name: Build native
|
||||
run: GOARCH=amd64 go build -v ./...
|
||||
shell: bash
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: "1.13"
|
||||
go-version: "1.17"
|
||||
- name: Cross-build
|
||||
run: |
|
||||
set ${{ matrix.go-os-pairs }}
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
|
||||
// +build go1.10,darwin
|
||||
|
||||
package enumerator
|
||||
|
||||
// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
//
|
||||
// Copyright 2014-2021 Cristian Maglie. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
//
|
||||
|
||||
// +build !go1.10,darwin
|
||||
|
||||
// This file is here to keep compatibility with the older versions of go
|
||||
// and is no more maintained or bugfixed, please update your go version
|
||||
// to at least 1.10 to get the latest updates.
|
||||
|
||||
package enumerator
|
||||
|
||||
// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit
|
||||
// #include <IOKit/IOKitLib.h>
|
||||
// #include <CoreFoundation/CoreFoundation.h>
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func nativeGetDetailedPortsList() ([]*PortDetails, error) {
|
||||
var ports []*PortDetails
|
||||
|
||||
services, err := getAllServices("IOSerialBSDClient")
|
||||
if err != nil {
|
||||
return nil, &PortEnumerationError{causedBy: err}
|
||||
}
|
||||
for _, service := range services {
|
||||
defer service.Release()
|
||||
|
||||
port, err := extractPortInfo(C.io_registry_entry_t(service))
|
||||
if err != nil {
|
||||
return nil, &PortEnumerationError{causedBy: err}
|
||||
}
|
||||
ports = append(ports, port)
|
||||
}
|
||||
return ports, nil
|
||||
}
|
||||
|
||||
func extractPortInfo(service C.io_registry_entry_t) (*PortDetails, error) {
|
||||
name, err := service.GetStringProperty("IOCalloutDevice")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error extracting port info from device: %s", err.Error())
|
||||
}
|
||||
port := &PortDetails{}
|
||||
port.Name = name
|
||||
port.IsUSB = false
|
||||
|
||||
usbDevice := service
|
||||
for usbDevice.GetClass() != "IOUSBDevice" {
|
||||
if usbDevice, err = usbDevice.GetParent("IOService"); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
// It's an IOUSBDevice
|
||||
vid, _ := usbDevice.GetIntProperty("idVendor", C.kCFNumberSInt16Type)
|
||||
pid, _ := usbDevice.GetIntProperty("idProduct", C.kCFNumberSInt16Type)
|
||||
serialNumber, _ := usbDevice.GetStringProperty("USB Serial Number")
|
||||
//product, _ := usbDevice.GetStringProperty("USB Product Name")
|
||||
//manufacturer, _ := usbDevice.GetStringProperty("USB Vendor Name")
|
||||
//fmt.Println(product + " - " + manufacturer)
|
||||
|
||||
port.IsUSB = true
|
||||
port.VID = fmt.Sprintf("%04X", vid)
|
||||
port.PID = fmt.Sprintf("%04X", pid)
|
||||
port.SerialNumber = serialNumber
|
||||
}
|
||||
return port, nil
|
||||
}
|
||||
|
||||
func getAllServices(serviceType string) ([]C.io_object_t, error) {
|
||||
i, err := getMatchingServices(serviceMatching(serviceType))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer i.Release()
|
||||
|
||||
var services []C.io_object_t
|
||||
tries := 0
|
||||
for tries < 5 {
|
||||
// Extract all elements from iterator
|
||||
if service, ok := i.Next(); ok {
|
||||
services = append(services, service)
|
||||
continue
|
||||
}
|
||||
// If iterator is still valid return the result
|
||||
if i.IsValid() {
|
||||
return services, nil
|
||||
}
|
||||
// Otherwise empty the result and retry
|
||||
for _, s := range services {
|
||||
s.Release()
|
||||
}
|
||||
services = []C.io_object_t{}
|
||||
i.Reset()
|
||||
tries++
|
||||
}
|
||||
// Give up if the iteration continues to fail...
|
||||
return nil, fmt.Errorf("IOServiceGetMatchingServices failed, data changed while iterating")
|
||||
}
|
||||
|
||||
// serviceMatching create a matching dictionary that specifies an IOService class match.
|
||||
func serviceMatching(serviceType string) C.CFMutableDictionaryRef {
|
||||
t := C.CString(serviceType)
|
||||
defer C.free(unsafe.Pointer(t))
|
||||
return C.IOServiceMatching(t)
|
||||
}
|
||||
|
||||
// getMatchingServices look up registered IOService objects that match a matching dictionary.
|
||||
func getMatchingServices(matcher C.CFMutableDictionaryRef) (C.io_iterator_t, error) {
|
||||
var i C.io_iterator_t
|
||||
err := C.IOServiceGetMatchingServices(C.kIOMasterPortDefault, matcher, &i)
|
||||
if err != C.KERN_SUCCESS {
|
||||
return 0, fmt.Errorf("IOServiceGetMatchingServices failed (code %d)", err)
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// CFStringRef
|
||||
|
||||
func cfStringCreateWithString(s string) C.CFStringRef {
|
||||
c := C.CString(s)
|
||||
defer C.free(unsafe.Pointer(c))
|
||||
return C.CFStringCreateWithCString(
|
||||
C.kCFAllocatorDefault, c, C.kCFStringEncodingMacRoman)
|
||||
}
|
||||
|
||||
// io_registry_entry_t
|
||||
|
||||
func (me *C.io_registry_entry_t) GetParent(plane string) (C.io_registry_entry_t, error) {
|
||||
cPlane := C.CString(plane)
|
||||
defer C.free(unsafe.Pointer(cPlane))
|
||||
var parent C.io_registry_entry_t
|
||||
err := C.IORegistryEntryGetParentEntry(*me, cPlane, &parent)
|
||||
if err != 0 {
|
||||
return 0, errors.New("No parent device available")
|
||||
}
|
||||
return parent, nil
|
||||
}
|
||||
|
||||
func (me *C.io_registry_entry_t) GetClass() string {
|
||||
obj := (*C.io_object_t)(me)
|
||||
return obj.GetClass()
|
||||
}
|
||||
|
||||
func (me *C.io_registry_entry_t) GetStringProperty(key string) (string, error) {
|
||||
k := cfStringCreateWithString(key)
|
||||
defer C.CFRelease(C.CFTypeRef(k))
|
||||
property := C.IORegistryEntryCreateCFProperty(*me, k, C.kCFAllocatorDefault, 0)
|
||||
if property == nil {
|
||||
return "", errors.New("Property not found: " + key)
|
||||
}
|
||||
defer C.CFRelease(property)
|
||||
|
||||
if ptr := C.CFStringGetCStringPtr((C.CFStringRef)(unsafe.Pointer(property)), 0); ptr != nil {
|
||||
return C.GoString(ptr), nil
|
||||
}
|
||||
// in certain circumstances CFStringGetCStringPtr may return NULL
|
||||
// and we must retrieve the string by copy
|
||||
buff := make([]C.char, 1024)
|
||||
if C.CFStringGetCString((C.CFStringRef)(property), &buff[0], 1024, 0) != C.true {
|
||||
return "", fmt.Errorf("Property '%s' can't be converted", key)
|
||||
}
|
||||
return C.GoString(&buff[0]), nil
|
||||
}
|
||||
|
||||
func (me *C.io_registry_entry_t) GetIntProperty(key string, intType C.CFNumberType) (int, error) {
|
||||
k := cfStringCreateWithString(key)
|
||||
defer C.CFRelease(C.CFTypeRef(k))
|
||||
property := C.IORegistryEntryCreateCFProperty(*me, k, C.kCFAllocatorDefault, 0)
|
||||
if property == nil {
|
||||
return 0, errors.New("Property not found: " + key)
|
||||
}
|
||||
defer C.CFRelease(property)
|
||||
var res int
|
||||
if C.CFNumberGetValue((C.CFNumberRef)(property), intType, unsafe.Pointer(&res)) != C.true {
|
||||
return res, fmt.Errorf("Property '%s' can't be converted or has been truncated", key)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// io_iterator_t
|
||||
|
||||
// IsValid checks if an iterator is still valid.
|
||||
// Some iterators will be made invalid if changes are made to the
|
||||
// structure they are iterating over. This function checks the iterator
|
||||
// is still valid and should be called when Next returns zero.
|
||||
// An invalid iterator can be Reset and the iteration restarted.
|
||||
func (me *C.io_iterator_t) IsValid() bool {
|
||||
return C.IOIteratorIsValid(*me) == C.true
|
||||
}
|
||||
|
||||
func (me *C.io_iterator_t) Reset() {
|
||||
C.IOIteratorReset(*me)
|
||||
}
|
||||
|
||||
func (me *C.io_iterator_t) Next() (C.io_object_t, bool) {
|
||||
res := C.IOIteratorNext(*me)
|
||||
return res, res != 0
|
||||
}
|
||||
|
||||
func (me *C.io_iterator_t) Release() {
|
||||
C.IOObjectRelease(C.io_object_t(*me))
|
||||
}
|
||||
|
||||
// io_object_t
|
||||
|
||||
func (me *C.io_object_t) Release() {
|
||||
C.IOObjectRelease(*me)
|
||||
}
|
||||
|
||||
func (me *C.io_object_t) GetClass() string {
|
||||
class := make([]C.char, 1024)
|
||||
C.IOObjectGetClass(*me, &class[0])
|
||||
return C.GoString(&class[0])
|
||||
}
|
||||
10
go.mod
10
go.mod
@@ -1,9 +1,15 @@
|
||||
module go.bug.st/serial
|
||||
|
||||
go 1.13
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/creack/goselect v0.1.2
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
|
||||
8
go.sum
8
go.sum
@@ -5,11 +5,11 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
Reference in New Issue
Block a user