|
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