|
1 | 1 | package main
|
2 | 2 |
|
3 |
| -import ( |
4 |
| - "os" |
5 |
| - "regexp" |
6 |
| - "strings" |
7 |
| - "sync" |
| 3 | +import () |
8 | 4 |
|
9 |
| - log "github.com/Sirupsen/logrus" |
10 |
| - "github.com/mattn/go-ole" |
11 |
| - "github.com/mattn/go-ole/oleutil" |
12 |
| -) |
13 |
| - |
14 |
| -var ( |
15 |
| - serialListWindowsWg sync.WaitGroup |
16 |
| -) |
17 |
| - |
18 |
| -func associateVidPidWithPort(ports []OsSerialPort) []OsSerialPort { |
19 |
| - ports, _ = getList() |
| 5 | +func ExtraFilterPorts(ports []OsSerialPort) []OsSerialPort { |
20 | 6 | return ports
|
21 | 7 | }
|
22 |
| - |
23 |
| -func getList() ([]OsSerialPort, os.SyscallError) { |
24 |
| - // use a queue to do this to avoid conflicts |
25 |
| - // we've been getting crashes when this getList is requested |
26 |
| - // too many times too fast. i think it's something to do with |
27 |
| - // the unsafe syscalls overwriting memory |
28 |
| - |
29 |
| - // this will only block if waitgroupctr > 0. so first time |
30 |
| - // in shouldn't block |
31 |
| - serialListWindowsWg.Wait() |
32 |
| - |
33 |
| - serialListWindowsWg.Add(1) |
34 |
| - arr, sysCallErr := getListViaWmiPnpEntity() |
35 |
| - serialListWindowsWg.Done() |
36 |
| - //arr = make([]OsSerialPort, 0) |
37 |
| - |
38 |
| - // see if array has any data, if not fallback to the traditional |
39 |
| - // com port list model |
40 |
| - /* |
41 |
| - if len(arr) == 0 { |
42 |
| - // assume it failed |
43 |
| - arr, sysCallErr = getListViaOpen() |
44 |
| - } |
45 |
| - */ |
46 |
| - |
47 |
| - // see if array has any data, if not fallback to looking at |
48 |
| - // the registry list |
49 |
| - /* |
50 |
| - arr = make([]OsSerialPort, 0) |
51 |
| - if len(arr) == 0 { |
52 |
| - // assume it failed |
53 |
| - arr, sysCallErr = getListViaRegistry() |
54 |
| - } |
55 |
| - */ |
56 |
| - |
57 |
| - return arr, sysCallErr |
58 |
| -} |
59 |
| - |
60 |
| -func getListSynchronously() { |
61 |
| - |
62 |
| -} |
63 |
| - |
64 |
| -func getListViaWmiPnpEntity() ([]OsSerialPort, os.SyscallError) { |
65 |
| - |
66 |
| - //log.Println("Doing getListViaWmiPnpEntity()") |
67 |
| - |
68 |
| - // this method panics a lot and i'm not sure why, just catch |
69 |
| - // the panic and return empty list |
70 |
| - defer func() { |
71 |
| - if e := recover(); e != nil { |
72 |
| - // e is the interface{} typed-value we passed to panic() |
73 |
| - log.Println("Got panic: ", e) // Prints "Whoops: boom!" |
74 |
| - } |
75 |
| - }() |
76 |
| - |
77 |
| - var err os.SyscallError |
78 |
| - |
79 |
| - //var friendlyName string |
80 |
| - |
81 |
| - // init COM, oh yeah |
82 |
| - ole.CoInitialize(0) |
83 |
| - defer ole.CoUninitialize() |
84 |
| - |
85 |
| - unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator") |
86 |
| - defer unknown.Release() |
87 |
| - |
88 |
| - wmi, _ := unknown.QueryInterface(ole.IID_IDispatch) |
89 |
| - defer wmi.Release() |
90 |
| - |
91 |
| - // service is a SWbemServices |
92 |
| - serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer") |
93 |
| - service := serviceRaw.ToIDispatch() |
94 |
| - defer service.Release() |
95 |
| - |
96 |
| - // result is a SWBemObjectSet |
97 |
| - //pname := syscall.StringToUTF16("SELECT * FROM Win32_PnPEntity where Name like '%" + "COM35" + "%'") |
98 |
| - pname := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0 and Name like '%(COM%'" |
99 |
| - //pname := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0" |
100 |
| - resultRaw, err2 := oleutil.CallMethod(service, "ExecQuery", pname) |
101 |
| - //log.Println("Got result from oleutil.CallMethod") |
102 |
| - if err2 != nil { |
103 |
| - // we got back an error or empty list |
104 |
| - log.Printf("Got an error back from oleutil.CallMethod. err:%v", err2) |
105 |
| - return nil, err |
106 |
| - } |
107 |
| - |
108 |
| - result := resultRaw.ToIDispatch() |
109 |
| - defer result.Release() |
110 |
| - |
111 |
| - countVar, _ := oleutil.GetProperty(result, "Count") |
112 |
| - count := int(countVar.Val) |
113 |
| - |
114 |
| - list := make([]OsSerialPort, count) |
115 |
| - |
116 |
| - for i := 0; i < count; i++ { |
117 |
| - |
118 |
| - // items we're looping thru look like below and |
119 |
| - // thus we can query for any of these names |
120 |
| - /* |
121 |
| - __GENUS : 2 |
122 |
| - __CLASS : Win32_PnPEntity |
123 |
| - __SUPERCLASS : CIM_LogicalDevice |
124 |
| - __DYNASTY : CIM_ManagedSystemElement |
125 |
| - __RELPATH : Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14&0&0002" |
126 |
| - __PROPERTY_COUNT : 24 |
127 |
| - __DERIVATION : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement} |
128 |
| - __SERVER : JOHN-ATIV |
129 |
| - __NAMESPACE : root\cimv2 |
130 |
| - __PATH : \\JOHN-ATIV\root\cimv2:Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14 |
131 |
| - &0&0002" |
132 |
| - Availability : |
133 |
| - Caption : TinyG v2 (Data Channel) (COM12) |
134 |
| - ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318} |
135 |
| - CompatibleID : {USB\Class_02&SubClass_02&Prot_01, USB\Class_02&SubClass_02, USB\Class_02} |
136 |
| - ConfigManagerErrorCode : 0 |
137 |
| - ConfigManagerUserConfig : False |
138 |
| - CreationClassName : Win32_PnPEntity |
139 |
| - Description : TinyG v2 (Data Channel) |
140 |
| - DeviceID : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002 |
141 |
| - ErrorCleared : |
142 |
| - ErrorDescription : |
143 |
| - HardwareID : {USB\VID_1D50&PID_606D&REV_0097&MI_02, USB\VID_1D50&PID_606D&MI_02} |
144 |
| - InstallDate : |
145 |
| - LastErrorCode : |
146 |
| - Manufacturer : Synthetos (www.synthetos.com) |
147 |
| - Name : TinyG v2 (Data Channel) (COM12) |
148 |
| - PNPDeviceID : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002 |
149 |
| - PowerManagementCapabilities : |
150 |
| - PowerManagementSupported : |
151 |
| - Service : usbser |
152 |
| - Status : OK |
153 |
| - StatusInfo : |
154 |
| - SystemCreationClassName : Win32_ComputerSystem |
155 |
| - SystemName : JOHN-ATIV |
156 |
| - PSComputerName : JOHN-ATIV |
157 |
| - */ |
158 |
| - |
159 |
| - // item is a SWbemObject, but really a Win32_Process |
160 |
| - itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) |
161 |
| - item := itemRaw.ToIDispatch() |
162 |
| - defer item.Release() |
163 |
| - |
164 |
| - asString, _ := oleutil.GetProperty(item, "Name") |
165 |
| - |
166 |
| - //log.Println(asString.ToString()) |
167 |
| - |
168 |
| - // get the com port |
169 |
| - //if false { |
170 |
| - s := strings.Split(asString.ToString(), "(COM")[1] |
171 |
| - s = "COM" + s |
172 |
| - s = strings.Split(s, ")")[0] |
173 |
| - list[i].Name = s |
174 |
| - //} |
175 |
| - |
176 |
| - // get the deviceid so we can figure out related ports |
177 |
| - // it will look similar to |
178 |
| - // USB\VID_1D50&PID_606D&MI_00\6&2F09EA14&0&0000 |
179 |
| - deviceIdStr, _ := oleutil.GetProperty(item, "DeviceID") |
180 |
| - devIdItems := strings.Split(deviceIdStr.ToString(), "&") |
181 |
| - //log.Printf("DeviceId elements:%v", devIdItems) |
182 |
| - if len(devIdItems) > 3 { |
183 |
| - list[i].SerialNumber = devIdItems[3] |
184 |
| - list[i].IdProduct = strings.Replace(devIdItems[1], "PID_", "", 1) |
185 |
| - list[i].IdVendor = strings.Replace(devIdItems[0], "USB\\VID_", "", 1) |
186 |
| - } else { |
187 |
| - list[i].SerialNumber = deviceIdStr.ToString() |
188 |
| - pidMatch := regexp.MustCompile("PID_(\\d+)").FindAllStringSubmatch(deviceIdStr.ToString(), -1) |
189 |
| - if len(pidMatch) > 0 { |
190 |
| - if len(pidMatch[0]) > 1 { |
191 |
| - list[i].IdProduct = pidMatch[0][1] |
192 |
| - } |
193 |
| - } |
194 |
| - vidMatch := regexp.MustCompile("VID_(\\d+)").FindAllStringSubmatch(deviceIdStr.ToString(), -1) |
195 |
| - if len(vidMatch) > 0 { |
196 |
| - if len(vidMatch[0]) > 1 { |
197 |
| - list[i].IdVendor = vidMatch[0][1] |
198 |
| - } |
199 |
| - } |
200 |
| - } |
201 |
| - |
202 |
| - list[i].IdVendor = "0x" + list[i].IdVendor |
203 |
| - list[i].IdProduct = "0x" + list[i].IdProduct |
204 |
| - |
205 |
| - manufStr, _ := oleutil.GetProperty(item, "Manufacturer") |
206 |
| - list[i].Manufacturer = manufStr.ToString() |
207 |
| - descStr, _ := oleutil.GetProperty(item, "Description") |
208 |
| - list[i].Product = descStr.ToString() |
209 |
| - //classStr, _ := oleutil.GetProperty(item, "CreationClassName") |
210 |
| - //list[i].DeviceClass = classStr.ToString() |
211 |
| - |
212 |
| - } |
213 |
| - |
214 |
| - return list, err |
215 |
| -} |
216 |
| - |
217 |
| -func convertByteArrayToUint16Array(b []byte, mylen uint32) []uint16 { |
218 |
| - |
219 |
| - log.Println("converting. len:", mylen) |
220 |
| - var i uint32 |
221 |
| - ret := make([]uint16, mylen/2) |
222 |
| - for i = 0; i < mylen; i += 2 { |
223 |
| - //ret[i/2] = binary.LittleEndian.Uint16(b[i : i+1]) |
224 |
| - ret[i/2] = uint16(b[i]) | uint16(b[i+1])<<8 |
225 |
| - } |
226 |
| - return ret |
227 |
| -} |
0 commit comments