Skip to content

Commit 80a3721

Browse files
deadprogramcmaglie
authored andcommitted
darwin: use Go type wrappers to avoid declaring Go methods on C types.
This is needed starting with Go 1.21 due to stricter enforcement of rules about adding methods to existing types, now including C types. See golang/go#60725 for further details. Signed-off-by: deadprogram <[email protected]>
1 parent 74e194e commit 80a3721

File tree

1 file changed

+76
-44
lines changed

1 file changed

+76
-44
lines changed

enumerator/usb_darwin.go

+76-44
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ import (
1818
"unsafe"
1919
)
2020

21+
type io_iterator_t struct {
22+
ioiterator C.io_iterator_t
23+
}
24+
25+
type io_object_t struct {
26+
ioobject C.io_object_t
27+
}
28+
29+
type io_registry_entry_t struct {
30+
ioregistryentry C.io_registry_entry_t
31+
}
32+
33+
type cfStringRef struct {
34+
cfs C.CFStringRef
35+
}
36+
37+
type cfTypeRef struct {
38+
cft C.CFTypeRef
39+
}
40+
2141
func nativeGetDetailedPortsList() ([]*PortDetails, error) {
2242
var ports []*PortDetails
2343

@@ -28,7 +48,7 @@ func nativeGetDetailedPortsList() ([]*PortDetails, error) {
2848
for _, service := range services {
2949
defer service.Release()
3050

31-
port, err := extractPortInfo(C.io_registry_entry_t(service))
51+
port, err := extractPortInfo(&io_registry_entry_t{ioregistryentry: service.ioobject})
3252
if err != nil {
3353
return nil, &PortEnumerationError{causedBy: err}
3454
}
@@ -37,7 +57,7 @@ func nativeGetDetailedPortsList() ([]*PortDetails, error) {
3757
return ports, nil
3858
}
3959

40-
func extractPortInfo(service C.io_registry_entry_t) (*PortDetails, error) {
60+
func extractPortInfo(service *io_registry_entry_t) (*PortDetails, error) {
4161
port := &PortDetails{}
4262
// If called too early the port may still not be ready or fully enumerated
4363
// so we retry 5 times before returning error.
@@ -58,12 +78,18 @@ func extractPortInfo(service C.io_registry_entry_t) (*PortDetails, error) {
5878
"IOUSBDevice": true,
5979
"IOUSBHostDevice": true,
6080
}
61-
usbDevice := service
62-
var searchErr error
63-
for !validUSBDeviceClass[usbDevice.GetClass()] {
81+
82+
var (
83+
usbDevice = io_registry_entry_t{service.ioregistryentry}
84+
usbDeviceObj = io_object_t{usbDevice.ioregistryentry}
85+
searchErr error
86+
)
87+
88+
for !validUSBDeviceClass[usbDeviceObj.GetClass()] {
6489
if usbDevice, searchErr = usbDevice.GetParent("IOService"); searchErr != nil {
6590
break
6691
}
92+
usbDeviceObj = io_object_t{usbDevice.ioregistryentry}
6793
}
6894
if searchErr == nil {
6995
// It's an IOUSBDevice
@@ -82,19 +108,19 @@ func extractPortInfo(service C.io_registry_entry_t) (*PortDetails, error) {
82108
return port, nil
83109
}
84110

85-
func getAllServices(serviceType string) ([]C.io_object_t, error) {
111+
func getAllServices(serviceType string) ([]io_object_t, error) {
86112
i, err := getMatchingServices(serviceMatching(serviceType))
87113
if err != nil {
88114
return nil, err
89115
}
90116
defer i.Release()
91117

92-
var services []C.io_object_t
118+
var services []io_object_t
93119
tries := 0
94120
for tries < 5 {
95121
// Extract all elements from iterator
96122
if service, ok := i.Next(); ok {
97-
services = append(services, service)
123+
services = append(services, *service)
98124
continue
99125
}
100126
// If iterator is still valid return the result
@@ -105,7 +131,7 @@ func getAllServices(serviceType string) ([]C.io_object_t, error) {
105131
for _, s := range services {
106132
s.Release()
107133
}
108-
services = []C.io_object_t{}
134+
services = []io_object_t{}
109135
i.Reset()
110136
tries++
111137
}
@@ -121,84 +147,86 @@ func serviceMatching(serviceType string) C.CFMutableDictionaryRef {
121147
}
122148

123149
// getMatchingServices look up registered IOService objects that match a matching dictionary.
124-
func getMatchingServices(matcher C.CFMutableDictionaryRef) (C.io_iterator_t, error) {
150+
func getMatchingServices(matcher C.CFMutableDictionaryRef) (io_iterator_t, error) {
125151
var i C.io_iterator_t
126152
err := C.IOServiceGetMatchingServices(C.kIOMasterPortDefault, C.CFDictionaryRef(matcher), &i)
127153
if err != C.KERN_SUCCESS {
128-
return 0, fmt.Errorf("IOServiceGetMatchingServices failed (code %d)", err)
154+
return io_iterator_t{}, fmt.Errorf("IOServiceGetMatchingServices failed (code %d)", err)
129155
}
130-
return i, nil
156+
return io_iterator_t{i}, nil
131157
}
132158

133-
// CFStringRef
159+
// cfStringRef
134160

135-
func cfStringCreateWithString(s string) C.CFStringRef {
161+
func CFStringCreateWithString(s string) cfStringRef {
136162
c := C.CString(s)
137163
defer C.free(unsafe.Pointer(c))
138-
return C.CFStringCreateWithCString(
164+
val := C.CFStringCreateWithCString(
139165
C.kCFAllocatorDefault, c, C.kCFStringEncodingMacRoman)
166+
return cfStringRef{val}
140167
}
141168

142-
func (ref C.CFStringRef) Release() {
143-
C.CFRelease(C.CFTypeRef(ref))
169+
func (ref cfStringRef) Release() {
170+
C.CFRelease(C.CFTypeRef(ref.cfs))
144171
}
145172

146173
// CFTypeRef
147174

148-
func (ref C.CFTypeRef) Release() {
149-
C.CFRelease(ref)
175+
func (ref cfTypeRef) Release() {
176+
C.CFRelease(C.CFTypeRef(ref.cft))
150177
}
151178

152179
// io_registry_entry_t
153180

154-
func (me *C.io_registry_entry_t) GetParent(plane string) (C.io_registry_entry_t, error) {
181+
func (me *io_registry_entry_t) GetParent(plane string) (io_registry_entry_t, error) {
155182
cPlane := C.CString(plane)
156183
defer C.free(unsafe.Pointer(cPlane))
157184
var parent C.io_registry_entry_t
158-
err := C.IORegistryEntryGetParentEntry(*me, cPlane, &parent)
185+
err := C.IORegistryEntryGetParentEntry(me.ioregistryentry, cPlane, &parent)
159186
if err != 0 {
160-
return 0, errors.New("No parent device available")
187+
return io_registry_entry_t{}, errors.New("No parent device available")
161188
}
162-
return parent, nil
189+
return io_registry_entry_t{parent}, nil
163190
}
164191

165-
func (me *C.io_registry_entry_t) CreateCFProperty(key string) (C.CFTypeRef, error) {
166-
k := cfStringCreateWithString(key)
192+
func (me *io_registry_entry_t) CreateCFProperty(key string) (cfTypeRef, error) {
193+
k := CFStringCreateWithString(key)
167194
defer k.Release()
168-
property := C.IORegistryEntryCreateCFProperty(*me, k, C.kCFAllocatorDefault, 0)
195+
property := C.IORegistryEntryCreateCFProperty(me.ioregistryentry, k.cfs, C.kCFAllocatorDefault, 0)
169196
if property == 0 {
170-
return 0, errors.New("Property not found: " + key)
197+
return cfTypeRef{}, errors.New("Property not found: " + key)
171198
}
172-
return property, nil
199+
return cfTypeRef{property}, nil
173200
}
174201

175-
func (me *C.io_registry_entry_t) GetStringProperty(key string) (string, error) {
202+
func (me *io_registry_entry_t) GetStringProperty(key string) (string, error) {
176203
property, err := me.CreateCFProperty(key)
177204
if err != nil {
205+
fmt.Println(err)
178206
return "", err
179207
}
180208
defer property.Release()
181209

182-
if ptr := C.CFStringGetCStringPtr(C.CFStringRef(property), 0); ptr != nil {
210+
if ptr := C.CFStringGetCStringPtr(C.CFStringRef(property.cft), 0); ptr != nil {
183211
return C.GoString(ptr), nil
184212
}
185213
// in certain circumstances CFStringGetCStringPtr may return NULL
186214
// and we must retrieve the string by copy
187215
buff := make([]C.char, 1024)
188-
if C.CFStringGetCString(C.CFStringRef(property), &buff[0], 1024, 0) != C.true {
216+
if C.CFStringGetCString(C.CFStringRef(property.cft), &buff[0], 1024, 0) != C.true {
189217
return "", fmt.Errorf("Property '%s' can't be converted", key)
190218
}
191219
return C.GoString(&buff[0]), nil
192220
}
193221

194-
func (me *C.io_registry_entry_t) GetIntProperty(key string, intType C.CFNumberType) (int, error) {
222+
func (me *io_registry_entry_t) GetIntProperty(key string, intType C.CFNumberType) (int, error) {
195223
property, err := me.CreateCFProperty(key)
196224
if err != nil {
197225
return 0, err
198226
}
199227
defer property.Release()
200228
var res int
201-
if C.CFNumberGetValue((C.CFNumberRef)(property), intType, unsafe.Pointer(&res)) != C.true {
229+
if C.CFNumberGetValue((C.CFNumberRef)(property.cft), intType, unsafe.Pointer(&res)) != C.true {
202230
return res, fmt.Errorf("Property '%s' can't be converted or has been truncated", key)
203231
}
204232
return res, nil
@@ -211,27 +239,31 @@ func (me *C.io_registry_entry_t) GetIntProperty(key string, intType C.CFNumberTy
211239
// structure they are iterating over. This function checks the iterator
212240
// is still valid and should be called when Next returns zero.
213241
// An invalid iterator can be Reset and the iteration restarted.
214-
func (me *C.io_iterator_t) IsValid() bool {
215-
return C.IOIteratorIsValid(*me) == C.true
242+
func (me *io_iterator_t) IsValid() bool {
243+
return C.IOIteratorIsValid(me.ioiterator) == C.true
244+
}
245+
246+
func (me *io_iterator_t) Reset() {
247+
C.IOIteratorReset(me.ioiterator)
216248
}
217249

218-
func (me *C.io_iterator_t) Reset() {
219-
C.IOIteratorReset(*me)
250+
func (me *io_iterator_t) Next() (*io_object_t, bool) {
251+
res := C.IOIteratorNext(me.ioiterator)
252+
return &io_object_t{res}, res != 0
220253
}
221254

222-
func (me *C.io_iterator_t) Next() (C.io_object_t, bool) {
223-
res := C.IOIteratorNext(*me)
224-
return res, res != 0
255+
func (me *io_iterator_t) Release() {
256+
C.IOObjectRelease(me.ioiterator)
225257
}
226258

227259
// io_object_t
228260

229-
func (me *C.io_object_t) Release() {
230-
C.IOObjectRelease(*me)
261+
func (me *io_object_t) Release() {
262+
C.IOObjectRelease(me.ioobject)
231263
}
232264

233-
func (me *C.io_object_t) GetClass() string {
265+
func (me *io_object_t) GetClass() string {
234266
class := make([]C.char, 1024)
235-
C.IOObjectGetClass(*me, &class[0])
267+
C.IOObjectGetClass(me.ioobject, &class[0])
236268
return C.GoString(&class[0])
237269
}

0 commit comments

Comments
 (0)