@@ -18,6 +18,26 @@ import (
18
18
"unsafe"
19
19
)
20
20
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
+
21
41
func nativeGetDetailedPortsList () ([]* PortDetails , error ) {
22
42
var ports []* PortDetails
23
43
@@ -28,7 +48,7 @@ func nativeGetDetailedPortsList() ([]*PortDetails, error) {
28
48
for _ , service := range services {
29
49
defer service .Release ()
30
50
31
- port , err := extractPortInfo (C . io_registry_entry_t ( service ) )
51
+ port , err := extractPortInfo (& io_registry_entry_t { ioregistryentry : service . ioobject } )
32
52
if err != nil {
33
53
return nil , & PortEnumerationError {causedBy : err }
34
54
}
@@ -37,7 +57,7 @@ func nativeGetDetailedPortsList() ([]*PortDetails, error) {
37
57
return ports , nil
38
58
}
39
59
40
- func extractPortInfo (service C. io_registry_entry_t ) (* PortDetails , error ) {
60
+ func extractPortInfo (service * io_registry_entry_t ) (* PortDetails , error ) {
41
61
port := & PortDetails {}
42
62
// If called too early the port may still not be ready or fully enumerated
43
63
// so we retry 5 times before returning error.
@@ -58,12 +78,18 @@ func extractPortInfo(service C.io_registry_entry_t) (*PortDetails, error) {
58
78
"IOUSBDevice" : true ,
59
79
"IOUSBHostDevice" : true ,
60
80
}
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 ()] {
64
89
if usbDevice , searchErr = usbDevice .GetParent ("IOService" ); searchErr != nil {
65
90
break
66
91
}
92
+ usbDeviceObj = io_object_t {usbDevice .ioregistryentry }
67
93
}
68
94
if searchErr == nil {
69
95
// It's an IOUSBDevice
@@ -82,19 +108,19 @@ func extractPortInfo(service C.io_registry_entry_t) (*PortDetails, error) {
82
108
return port , nil
83
109
}
84
110
85
- func getAllServices (serviceType string ) ([]C. io_object_t , error ) {
111
+ func getAllServices (serviceType string ) ([]io_object_t , error ) {
86
112
i , err := getMatchingServices (serviceMatching (serviceType ))
87
113
if err != nil {
88
114
return nil , err
89
115
}
90
116
defer i .Release ()
91
117
92
- var services []C. io_object_t
118
+ var services []io_object_t
93
119
tries := 0
94
120
for tries < 5 {
95
121
// Extract all elements from iterator
96
122
if service , ok := i .Next (); ok {
97
- services = append (services , service )
123
+ services = append (services , * service )
98
124
continue
99
125
}
100
126
// If iterator is still valid return the result
@@ -105,7 +131,7 @@ func getAllServices(serviceType string) ([]C.io_object_t, error) {
105
131
for _ , s := range services {
106
132
s .Release ()
107
133
}
108
- services = []C. io_object_t {}
134
+ services = []io_object_t {}
109
135
i .Reset ()
110
136
tries ++
111
137
}
@@ -121,84 +147,86 @@ func serviceMatching(serviceType string) C.CFMutableDictionaryRef {
121
147
}
122
148
123
149
// 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 ) {
125
151
var i C.io_iterator_t
126
152
err := C .IOServiceGetMatchingServices (C .kIOMasterPortDefault , C .CFDictionaryRef (matcher ), & i )
127
153
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 )
129
155
}
130
- return i , nil
156
+ return io_iterator_t { i } , nil
131
157
}
132
158
133
- // CFStringRef
159
+ // cfStringRef
134
160
135
- func cfStringCreateWithString (s string ) C. CFStringRef {
161
+ func CFStringCreateWithString (s string ) cfStringRef {
136
162
c := C .CString (s )
137
163
defer C .free (unsafe .Pointer (c ))
138
- return C .CFStringCreateWithCString (
164
+ val := C .CFStringCreateWithCString (
139
165
C .kCFAllocatorDefault , c , C .kCFStringEncodingMacRoman )
166
+ return cfStringRef {val }
140
167
}
141
168
142
- func (ref C. CFStringRef ) Release () {
143
- C .CFRelease (C .CFTypeRef (ref ))
169
+ func (ref cfStringRef ) Release () {
170
+ C .CFRelease (C .CFTypeRef (ref . cfs ))
144
171
}
145
172
146
173
// CFTypeRef
147
174
148
- func (ref C. CFTypeRef ) Release () {
149
- C .CFRelease (ref )
175
+ func (ref cfTypeRef ) Release () {
176
+ C .CFRelease (C . CFTypeRef ( ref . cft ) )
150
177
}
151
178
152
179
// io_registry_entry_t
153
180
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 ) {
155
182
cPlane := C .CString (plane )
156
183
defer C .free (unsafe .Pointer (cPlane ))
157
184
var parent C.io_registry_entry_t
158
- err := C .IORegistryEntryGetParentEntry (* me , cPlane , & parent )
185
+ err := C .IORegistryEntryGetParentEntry (me . ioregistryentry , cPlane , & parent )
159
186
if err != 0 {
160
- return 0 , errors .New ("No parent device available" )
187
+ return io_registry_entry_t {} , errors .New ("No parent device available" )
161
188
}
162
- return parent , nil
189
+ return io_registry_entry_t { parent } , nil
163
190
}
164
191
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 )
167
194
defer k .Release ()
168
- property := C .IORegistryEntryCreateCFProperty (* me , k , C .kCFAllocatorDefault , 0 )
195
+ property := C .IORegistryEntryCreateCFProperty (me . ioregistryentry , k . cfs , C .kCFAllocatorDefault , 0 )
169
196
if property == 0 {
170
- return 0 , errors .New ("Property not found: " + key )
197
+ return cfTypeRef {} , errors .New ("Property not found: " + key )
171
198
}
172
- return property , nil
199
+ return cfTypeRef { property } , nil
173
200
}
174
201
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 ) {
176
203
property , err := me .CreateCFProperty (key )
177
204
if err != nil {
205
+ fmt .Println (err )
178
206
return "" , err
179
207
}
180
208
defer property .Release ()
181
209
182
- if ptr := C .CFStringGetCStringPtr (C .CFStringRef (property ), 0 ); ptr != nil {
210
+ if ptr := C .CFStringGetCStringPtr (C .CFStringRef (property . cft ), 0 ); ptr != nil {
183
211
return C .GoString (ptr ), nil
184
212
}
185
213
// in certain circumstances CFStringGetCStringPtr may return NULL
186
214
// and we must retrieve the string by copy
187
215
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 {
189
217
return "" , fmt .Errorf ("Property '%s' can't be converted" , key )
190
218
}
191
219
return C .GoString (& buff [0 ]), nil
192
220
}
193
221
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 ) {
195
223
property , err := me .CreateCFProperty (key )
196
224
if err != nil {
197
225
return 0 , err
198
226
}
199
227
defer property .Release ()
200
228
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 {
202
230
return res , fmt .Errorf ("Property '%s' can't be converted or has been truncated" , key )
203
231
}
204
232
return res , nil
@@ -211,27 +239,31 @@ func (me *C.io_registry_entry_t) GetIntProperty(key string, intType C.CFNumberTy
211
239
// structure they are iterating over. This function checks the iterator
212
240
// is still valid and should be called when Next returns zero.
213
241
// 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 )
216
248
}
217
249
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
220
253
}
221
254
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 )
225
257
}
226
258
227
259
// io_object_t
228
260
229
- func (me * C. io_object_t ) Release () {
230
- C .IOObjectRelease (* me )
261
+ func (me * io_object_t ) Release () {
262
+ C .IOObjectRelease (me . ioobject )
231
263
}
232
264
233
- func (me * C. io_object_t ) GetClass () string {
265
+ func (me * io_object_t ) GetClass () string {
234
266
class := make ([]C.char , 1024 )
235
- C .IOObjectGetClass (* me , & class [0 ])
267
+ C .IOObjectGetClass (me . ioobject , & class [0 ])
236
268
return C .GoString (& class [0 ])
237
269
}
0 commit comments