├── .gitignore
├── .gitmodules
├── README.md
├── AssemblyInfo.cs
├── InterfaceNotificationEventsArgs.cs
├── SudoInterface.cs
├── ManagedWifi.csproj
├── WlanClient.cs
├── IEParser.cs
├── WlanInterface.cs
└── Wlan.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | *.vs10x
2 | *.user
3 | bin
4 | obj
5 |
6 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "tools"]
2 | path = tools
3 | url = git@codebasehq.com:metageek/nutbrown/toolsdir.git
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ManagedWifi
2 | ===========
3 |
4 | Copyright 2009-2013 MetaGeek, LLC
5 |
6 | Licensed under the Apache License, Version 2.0 (the "License");
7 | you may not use this file except in compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | distributed under the License is distributed on an "AS IS" BASIS,
14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | See the License for the specific language governing permissions and
16 | limitations under the License.
17 |
--------------------------------------------------------------------------------
/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly: System.Reflection.AssemblyVersion("2012.1.31.1372")]
2 | [assembly: System.Reflection.AssemblyConfiguration("")]
3 | [assembly: System.Runtime.CompilerServices.CompilationRelaxations(8)]
4 | [assembly: System.Reflection.AssemblyTitle("Managed Wifi API")]
5 | [assembly: System.Reflection.AssemblyDescription(".NET managed wrapper for Windows Native Wifi API.")]
6 | [assembly: System.Runtime.CompilerServices.RuntimeCompatibility(WrapNonExceptionThrows = true)]
7 | [assembly: System.Reflection.AssemblyCompany("Monfort Software Engineering")]
8 | [assembly: System.Reflection.AssemblyProduct("Managed Wifi API")]
9 | [assembly: System.Reflection.AssemblyCopyright("Copyright © Monfort Software Engineering 2007")]
10 | [assembly: System.Reflection.AssemblyTrademark("")]
11 | [assembly: System.Runtime.InteropServices.ComVisible(false)]
12 | [assembly: System.Runtime.InteropServices.Guid("e7646a9f-2d07-455a-b9ae-51eaf7281d2f")]
13 | [assembly: System.Reflection.AssemblyFileVersion("1.1.1.1372")]
14 | [assembly: System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
15 |
--------------------------------------------------------------------------------
/InterfaceNotificationEventsArgs.cs:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright (c) 2007-2010 MetaGeek, LLC
4 | //
5 | // Licensed under the Apache License, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // http://www.apache.org/licenses/LICENSE-2.0
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 | //
17 | ////////////////////////////////////////////////////////////////
18 | namespace ManagedWifi
19 | {
20 | using System;
21 |
22 | public class InterfaceNotificationEventsArgs : EventArgs
23 | {
24 | #region Fields
25 |
26 | public Guid ItsGuid;
27 |
28 | #endregion Fields
29 |
30 | #region Constructors
31 |
32 | public InterfaceNotificationEventsArgs(Guid id)
33 | {
34 | ItsGuid = id;
35 | }
36 |
37 | #endregion Constructors
38 | }
39 | }
--------------------------------------------------------------------------------
/SudoInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.NetworkInformation;
3 |
4 | namespace ManagedWifi
5 | {
6 | class SudoInterface : NetworkInterface
7 | {
8 | #region Fields
9 |
10 | private readonly string _desc;
11 | private readonly string _id;
12 | private readonly string _name;
13 |
14 | #endregion Fields
15 |
16 | #region Properties
17 |
18 | public override string Description
19 | {
20 | get { return _desc; }
21 | }
22 |
23 | public override string Id
24 | {
25 | get { return _id; }
26 | }
27 |
28 | public override bool IsReceiveOnly
29 | {
30 | get { return false; }
31 | }
32 |
33 | public override string Name
34 | {
35 | get { return _name; }
36 | }
37 |
38 | public override NetworkInterfaceType NetworkInterfaceType
39 | {
40 | get { return NetworkInterfaceType.Wireless80211; }
41 | }
42 |
43 | public override OperationalStatus OperationalStatus
44 | {
45 | get { return OperationalStatus.Up; }
46 | }
47 |
48 | public override long Speed
49 | {
50 | get { return 0; }
51 | }
52 |
53 | public override bool SupportsMulticast
54 | {
55 | get { return false; }
56 | }
57 |
58 | #endregion Properties
59 |
60 | #region Constructors
61 |
62 | public SudoInterface(WlanInterface wlan)
63 | {
64 | _id = wlan.InterfaceGuid.ToString();
65 | _desc = wlan.InterfaceDescription;
66 | }
67 |
68 | public SudoInterface(string id, string description, string name)
69 | {
70 | _id = id;
71 | _name = name;
72 | _desc = description;
73 | }
74 |
75 | #endregion Constructors
76 |
77 | #region Public Methods
78 |
79 | public override IPInterfaceProperties GetIPProperties()
80 | {
81 | return null;
82 | }
83 |
84 | public override IPv4InterfaceStatistics GetIPv4Statistics()
85 | {
86 | throw new NotImplementedException();
87 | }
88 |
89 | public override PhysicalAddress GetPhysicalAddress()
90 | {
91 | return PhysicalAddress.None;
92 | }
93 |
94 | public override bool Supports(NetworkInterfaceComponent networkInterfaceComponent)
95 | {
96 | return true;
97 | }
98 |
99 | #endregion Public Methods
100 | }
101 | }
--------------------------------------------------------------------------------
/ManagedWifi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | bin\x86\Debug\
6 | DEBUG;TRACE
7 | true
8 | full
9 | x86
10 | true
11 | GlobalSuppressions.cs
12 | prompt
13 |
14 |
15 | bin\x86\Release\
16 | TRACE
17 | true
18 | true
19 | x86
20 | true
21 | GlobalSuppressions.cs
22 | prompt
23 |
24 |
25 | local
26 | 7.10.3077
27 | 2.0
28 | {B290695E-0DD1-4912-88DE-7AA6DC7AF0A5}
29 | Debug
30 | AnyCPU
31 | ManagedWifi
32 | JScript
33 | Grid
34 | IE50
35 | false
36 | Library
37 |
38 |
39 | 3.5
40 |
41 |
42 | false
43 | v3.5
44 |
45 |
46 | publish\
47 | true
48 | Disk
49 | false
50 | Foreground
51 | 7
52 | Days
53 | false
54 | false
55 | true
56 | 0
57 | 1.0.0.%2a
58 | false
59 | true
60 |
61 |
62 |
63 | ..\lib\MetaGeek.Diagnostics.dll
64 |
65 |
66 | System
67 |
68 |
69 | 3.5
70 |
71 |
72 |
73 |
74 | Code
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | False
86 | .NET Framework 3.5 SP1 Client Profile
87 | false
88 |
89 |
90 | False
91 | .NET Framework 2.0 %28x86%29
92 | true
93 |
94 |
95 | False
96 | .NET Framework 3.0 %28x86%29
97 | false
98 |
99 |
100 | False
101 | .NET Framework 3.5
102 | false
103 |
104 |
105 | False
106 | .NET Framework 3.5 SP1
107 | false
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/WlanClient.cs:
--------------------------------------------------------------------------------
1 | #region Header
2 |
3 | //
4 | // Copyright (c) 2007-2010 MetaGeek, LLC
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 | //
18 |
19 | #endregion Header
20 |
21 | using System;
22 | using System.Collections.Generic;
23 | using System.ComponentModel;
24 | using System.Runtime.InteropServices;
25 | using System.Text;
26 | using MetaGeek.Diagnostics;
27 | using MetaGeek.Diagnostics.Event;
28 |
29 | namespace ManagedWifi
30 | {
31 | public class WlanClient
32 | {
33 | #region Fields
34 |
35 | private readonly IntPtr _clientHandle;
36 | private readonly Dictionary _ifaces = new Dictionary();
37 | private uint _negotiatedVersion;
38 |
39 | #endregion Fields
40 |
41 | #region Properties
42 |
43 | public WlanInterface[] Interfaces
44 | {
45 | get
46 | {
47 | IntPtr ptr;
48 | WlanInterface[] interfaceArray2;
49 | Wlan.ThrowIfError(Wlan.WlanEnumInterfaces(_clientHandle, IntPtr.Zero, out ptr));
50 | try
51 | {
52 | Wlan.WlanInterfaceInfoListHeader structure = (Wlan.WlanInterfaceInfoListHeader)Marshal.PtrToStructure(ptr, typeof(Wlan.WlanInterfaceInfoListHeader));
53 | long num = ptr.ToInt64() + Marshal.SizeOf(structure);
54 | WlanInterface[] interfaceArray = new WlanInterface[structure.numberOfItems];
55 | List list = new List();
56 | for (int i = 0; i < structure.numberOfItems; i++)
57 | {
58 | Wlan.WlanInterfaceInfo info = (Wlan.WlanInterfaceInfo)Marshal.PtrToStructure(new IntPtr(num), typeof(Wlan.WlanInterfaceInfo));
59 | num += Marshal.SizeOf(info);
60 | list.Add(info.interfaceGuid);
61 | WlanInterface interface2 = _ifaces.ContainsKey(info.interfaceGuid) ? _ifaces[info.interfaceGuid] : new WlanInterface(this, info);
62 | interfaceArray[i] = interface2;
63 | _ifaces[info.interfaceGuid] = interface2;
64 | }
65 | Queue queue = new Queue();
66 | foreach (Guid guid in _ifaces.Keys)
67 | {
68 | if (!list.Contains(guid))
69 | {
70 | queue.Enqueue(guid);
71 | }
72 | }
73 | while (queue.Count != 0)
74 | {
75 | Guid key = queue.Dequeue();
76 | _ifaces.Remove(key);
77 | }
78 | interfaceArray2 = interfaceArray;
79 | }
80 | finally
81 | {
82 | Wlan.WlanFreeMemory(ptr);
83 | }
84 | return interfaceArray2;
85 | }
86 | }
87 |
88 | public IntPtr ItsClientHandle
89 | {
90 | get { return _clientHandle; }
91 | }
92 |
93 | private Logger ItsLogger
94 | {
95 | get;
96 | set;
97 | }
98 |
99 | private Wlan.WlanNotificationCallbackDelegate WlanNotificationCallback
100 | {
101 | get;
102 | set;
103 | }
104 |
105 | #endregion Properties
106 |
107 | #region Event Fields
108 |
109 | public RegisteredEventHandler InterfaceArrivedEvent = new RegisteredEventHandler();
110 | public RegisteredEventHandler InterfaceRemovedEvent = new RegisteredEventHandler();
111 |
112 | #endregion Event Fields
113 |
114 | #region Constructors
115 |
116 | public WlanClient()
117 | {
118 | ItsLogger = new Logger(this);
119 |
120 | try
121 | {
122 | Wlan.ThrowIfError(Wlan.WlanOpenHandle(1, IntPtr.Zero, out _negotiatedVersion, out _clientHandle));
123 | WlanNotificationCallback = new Wlan.WlanNotificationCallbackDelegate(OnWlanNotification);
124 |
125 | Wlan.WlanNotificationSource source;
126 | Wlan.ThrowIfError(Wlan.WlanRegisterNotification(_clientHandle, Wlan.WlanNotificationSource.All, false, WlanNotificationCallback, IntPtr.Zero, IntPtr.Zero, out source));
127 | }
128 | catch (Win32Exception ex)
129 | {
130 | Wlan.WlanCloseHandle(_clientHandle, IntPtr.Zero);
131 | ItsLogger.Warn(ex.Message);
132 | throw;
133 | }
134 | }
135 |
136 | ~WlanClient()
137 | {
138 | Wlan.WlanCloseHandle(_clientHandle, IntPtr.Zero);
139 | }
140 |
141 | #endregion Constructors
142 |
143 | #region Public Methods
144 |
145 | public string GetStringForReasonCode(Wlan.WlanReasonCode reasonCode)
146 | {
147 | StringBuilder stringBuffer = new StringBuilder(0x400);
148 | Wlan.ThrowIfError(Wlan.WlanReasonCodeToString(reasonCode, stringBuffer.Capacity, stringBuffer, IntPtr.Zero));
149 | return stringBuffer.ToString();
150 | }
151 |
152 | #endregion Public Methods
153 |
154 | #region Private Methods
155 |
156 | private void OnWlanNotification(ref Wlan.WlanNotificationData notifyData, IntPtr context)
157 | {
158 | WlanInterface interface2 = _ifaces.ContainsKey(notifyData.interfaceGuid) ? _ifaces[notifyData.interfaceGuid] : null;
159 | switch (notifyData.notificationSource)
160 | {
161 | case Wlan.WlanNotificationSource.Acm:
162 | switch (notifyData.notificationCode)
163 | {
164 | case 8:
165 | if (notifyData.dataSize >= Marshal.SizeOf(0))
166 | {
167 | Wlan.WlanReasonCode reasonCode = (Wlan.WlanReasonCode)Marshal.ReadInt32(notifyData.dataPtr);
168 | if (interface2 != null)
169 | {
170 | interface2.OnWlanReason(notifyData, reasonCode);
171 | }
172 | }
173 | goto Label_0194;
174 |
175 | case 9:
176 | case 10:
177 | case 11:
178 | case 20:
179 | case 0x15:
180 | {
181 | Wlan.WlanConnectionNotificationData? nullable = ParseWlanConnectionNotification(ref notifyData);
182 | if (nullable.HasValue && (interface2 != null))
183 | {
184 | interface2.OnWlanConnection(notifyData, nullable.Value);
185 | }
186 | goto Label_0194;
187 | }
188 | case 12:
189 | case 15:
190 | case 0x10:
191 | case 0x11:
192 | case 0x12:
193 | case 0x13:
194 | goto Label_0194;
195 |
196 | case 13:
197 | InterfaceArrivedEvent.Raise(this, new InterfaceNotificationEventsArgs(notifyData.interfaceGuid));
198 | goto Label_0194;
199 |
200 | case 14:
201 | InterfaceRemovedEvent.Raise(this, new InterfaceNotificationEventsArgs(notifyData.interfaceGuid));
202 | goto Label_0194;
203 | }
204 | break;
205 |
206 | case Wlan.WlanNotificationSource.Msm:
207 | switch (notifyData.notificationCode)
208 | {
209 | case 1:
210 | case 2:
211 | case 3:
212 | case 4:
213 | case 5:
214 | case 6:
215 | case 9:
216 | case 10:
217 | case 11:
218 | case 12:
219 | case 13:
220 | {
221 | Wlan.WlanConnectionNotificationData? nullable2 = ParseWlanConnectionNotification(ref notifyData);
222 | if (nullable2.HasValue && (interface2 != null))
223 | {
224 | interface2.OnWlanConnection(notifyData, nullable2.Value);
225 | }
226 | goto Label_0194;
227 | }
228 | case 7:
229 | case 8:
230 | goto Label_0194;
231 | }
232 | goto Label_0194;
233 | }
234 | Label_0194:
235 | if (interface2 != null)
236 | {
237 | interface2.OnWlanNotification(notifyData);
238 | }
239 | }
240 |
241 | private Wlan.WlanConnectionNotificationData? ParseWlanConnectionNotification(ref Wlan.WlanNotificationData notifyData)
242 | {
243 | int num = Marshal.SizeOf(typeof(Wlan.WlanConnectionNotificationData));
244 | if (notifyData.dataSize < num)
245 | {
246 | return null;
247 | }
248 | Wlan.WlanConnectionNotificationData data = (Wlan.WlanConnectionNotificationData)Marshal.PtrToStructure(notifyData.dataPtr, typeof(Wlan.WlanConnectionNotificationData));
249 | if (data.wlanReasonCode == Wlan.WlanReasonCode.Success)
250 | {
251 | IntPtr ptr = new IntPtr(notifyData.dataPtr.ToInt64() + Marshal.OffsetOf(typeof(Wlan.WlanConnectionNotificationData), "profileXml").ToInt64());
252 | data.profileXml = Marshal.PtrToStringUni(ptr);
253 | }
254 | return data;
255 | }
256 |
257 | #endregion Private Methods
258 | }
259 | }
--------------------------------------------------------------------------------
/IEParser.cs:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////
2 |
3 | #region Header
4 |
5 | //
6 | // Copyright (c) 2007-2010 MetaGeek, LLC
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | #endregion Header
22 |
23 | ////////////////////////////////////////////////////////////////
24 | using System;
25 | using System.Collections;
26 | using System.Collections.Generic;
27 | using System.Globalization;
28 | using System.IO;
29 |
30 | namespace ManagedWifi
31 | {
32 | public static class IeParser
33 | {
34 |
35 | public struct InformationElement
36 | {
37 | public ushort ItsNumber { get; set; }
38 | public ushort ItsLength { get; set; }
39 | public byte[] ItsData { get; set; }
40 | }
41 |
42 | #region Public Methods
43 |
44 | public static TypeNSettings Parse(byte[] ies)
45 | {
46 |
47 | var informationElements = BuildInformationElements(ies);
48 | var settings = new TypeNSettings();
49 | bool returnNull = true;
50 |
51 | foreach (var informationElement in informationElements)
52 | {
53 | switch (informationElement.ItsNumber)
54 | {
55 | case 45: //HT Capabilities
56 | ParseHTCapabilities(informationElement, settings);
57 | returnNull = false;
58 | break;
59 | case 61: //HT Information
60 | ParseHTOperation(informationElement, settings);
61 | returnNull = false;
62 | break;
63 | }
64 | }
65 |
66 | return returnNull ? null : settings;
67 | }
68 |
69 | public static TypeACSettings ParseAC(byte[] ies)
70 | {
71 |
72 | var informationElements = BuildInformationElements(ies);
73 | var settings = new TypeACSettings();
74 | bool returnNull = true;
75 |
76 | foreach (var informationElement in informationElements)
77 | {
78 | switch (informationElement.ItsNumber)
79 | {
80 | case 45: //HT Capabilities
81 | ParseHTCapabilities(informationElement, settings);
82 | returnNull = false;
83 | break;
84 | case 61: //HT Information
85 | ParseHTOperation(informationElement, settings);
86 | returnNull = false;
87 | break;
88 | case 191: //VHT Capabilities
89 | ParseVHTCapabilities(informationElement, settings);
90 | break;
91 | case 192: //VHT Operation
92 | ParseVHTOperation(informationElement, settings);
93 | break;
94 | }
95 | }
96 |
97 | return returnNull ? null : settings;
98 | }
99 |
100 |
101 |
102 | private static void ParseVHTOperation(InformationElement ie, TypeACSettings settings)
103 | {
104 | settings.Operations = new TypeACSettings.VHTOperations();
105 |
106 | var operations = new byte[4];
107 | Array.Copy(ie.ItsData, 0, operations, 0, 3);
108 |
109 | var basicMCSSet = new byte[8];
110 | Array.Copy(ie.ItsData, 3, basicMCSSet, 0, 2);
111 |
112 | settings.Operations.ChannelWidth =
113 | (TypeACSettings.VHTOperations.VHTChannelWidth) Enum.Parse(
114 | typeof(TypeACSettings.VHTOperations.VHTChannelWidth),
115 | operations[0].ToString(CultureInfo.InvariantCulture)
116 | );
117 | }
118 |
119 | private static void ParseVHTCapabilities(InformationElement ie, TypeACSettings settings)
120 | {
121 | settings.Capabilities = new TypeACSettings.VHTCapabilities();
122 |
123 | var capabilities = new byte[4];
124 | Array.Copy(ie.ItsData, 0, capabilities, 0, 4);
125 |
126 | var supportedMCS = new byte[8];
127 | Array.Copy(ie.ItsData, 4, supportedMCS, 0, 8);
128 |
129 | var supportedChannelWidth = ( capabilities[0] & 0x0C ) >> 2;
130 |
131 | switch (supportedChannelWidth)
132 | {
133 | case 1:
134 | settings.Capabilities.Supports160Mhz = true;
135 | break;
136 | case 2:
137 | settings.Capabilities.Supports80Plus80Mhz = true;
138 | settings.Capabilities.Supports160Mhz = true;
139 | break;
140 | }
141 |
142 | settings.Capabilities. ShortGi160MHz = (capabilities[0] & 0x40) == 0x40;
143 | settings.Capabilities.ShortGi80MHz = (capabilities[0] & 0x20) == 0x20;
144 |
145 | settings.Capabilities.MaxRecieveRate = BitConverter.ToUInt16(supportedMCS, 2);
146 | settings.Capabilities.MaxTransmitRate = BitConverter.ToUInt16(supportedMCS, 6);
147 | }
148 |
149 | private static void ParseHTOperation(InformationElement ie, TypeNSettings settings)
150 | {
151 | const int channel = 0;
152 | const int subset1 = 1;
153 |
154 | //Primary channel
155 | settings.PrimaryChannel = ie.ItsData[0];
156 |
157 | //Secondary channel location
158 | settings.SecondaryChannelLower = (ie.ItsData[channel] & 0x03) == 0x03;
159 |
160 | //Check if there is no secondary channel and set 40MHz to false
161 | if (settings.Is40Mhz)
162 | settings.Is40Mhz = (ie.ItsData[subset1] & 0x03) == 0x03 || (ie.ItsData[subset1] & 0x01) == 0x01;
163 | }
164 |
165 | private static void ParseHTCapabilities(InformationElement ie, TypeNSettings settings)
166 | {
167 | settings.Is40Mhz = ((ie.ItsData[0] & 0x02) == 0x02);
168 |
169 | settings.ShortGi20MHz = (ie.ItsData[0] & 0x20) == 0x20;
170 | settings.ShortGi40MHz = (ie.ItsData[0] & 0x40) == 0x40;
171 |
172 | //Get supported MCS indexes
173 | //1 bit per index
174 |
175 | byte[] bits = new byte[4];
176 | //Array.ConstrainedCopy(ies, index + 5, bits, 0, 4);
177 | Array.Copy(ie.ItsData, 4, bits, 0, 4);
178 |
179 | BitArray b = new BitArray(bits);
180 | //settings.Rates = new List();
181 |
182 | //The MCS indexes are in little endian,
183 | //so this loop will start at the lowest rates
184 | for (int i = 0; i < b.Length; i++)
185 | {
186 | //If the MCS index bit is 0, skip it
187 | if (b[i] == false) continue;
188 |
189 | //Add the rate
190 | settings.Rates.Add(McsSet.GetSpeed((uint) i, settings.ShortGi20MHz, settings.ShortGi40MHz,
191 | settings.Is40Mhz));
192 | }
193 | }
194 |
195 | private static IEnumerable BuildInformationElements(byte[] ies)
196 | {
197 | var informationElements = new List();
198 |
199 | var index = 0;
200 |
201 | while (index < ies.Length)
202 | {
203 | var ie = new InformationElement();
204 | ie.ItsNumber = ies[index];
205 | ie.ItsLength = ies[index + 1];
206 | ie.ItsData = new byte[ie.ItsLength];
207 | Array.Copy(ies, index + 2, ie.ItsData, 0, ie.ItsLength);
208 |
209 | informationElements.Add(ie);
210 | index += ie.ItsLength + 2;
211 | }
212 | return informationElements;
213 | }
214 |
215 |
216 | public class TypeNSettings
217 | {
218 | public bool Is40Mhz;
219 | public bool ShortGi20MHz;
220 | public bool ShortGi40MHz;
221 | public uint PrimaryChannel;
222 | public bool SecondaryChannelLower;
223 |
224 | //public uint MaxMcs;
225 | public List Rates;
226 |
227 | //public static TypeNSettings Empty = new TypeNSettings() { Rates = new List() };
228 | public TypeNSettings()
229 | {
230 | Rates = new List();
231 | }
232 |
233 | public TypeNSettings(TypeNSettings settings)
234 | {
235 | Is40Mhz = settings.Is40Mhz;
236 | ShortGi20MHz = settings.ShortGi20MHz;
237 | ShortGi40MHz = settings.ShortGi40MHz;
238 | PrimaryChannel = settings.PrimaryChannel;
239 | SecondaryChannelLower = settings.SecondaryChannelLower;
240 | //MaxMcs = settings.MaxMcs;
241 | Rates = settings.Rates;
242 | }
243 |
244 | public override bool Equals(object obj)
245 | {
246 | if (obj is TypeNSettings)
247 | {
248 | TypeNSettings set = (TypeNSettings)obj;
249 | bool yes = set.Is40Mhz == Is40Mhz;
250 | yes &= set.ShortGi20MHz == ShortGi20MHz;
251 | yes &= set.ShortGi40MHz == ShortGi40MHz;
252 | yes &= set.PrimaryChannel == PrimaryChannel;
253 | yes &= set.SecondaryChannelLower == SecondaryChannelLower;
254 | //Don't compare rates
255 |
256 | return yes;
257 | }
258 | return false;
259 | }
260 | }
261 |
262 | public class TypeACSettings : TypeNSettings
263 | {
264 | public class VHTCapabilities
265 | {
266 | public bool ShortGi80MHz;
267 | public bool ShortGi160MHz;
268 | public bool Supports160Mhz;
269 | public bool Supports80Plus80Mhz;
270 | public ushort MaxRecieveRate;
271 | public ushort MaxTransmitRate;
272 | }
273 |
274 | public class VHTOperations
275 | {
276 | public enum VHTChannelWidth : byte
277 | {
278 | TwentyOrForty = 0x00,
279 | Eighty = 0x01,
280 | OneSixty = 0x02,
281 | EightyPlusEighty = 0x03
282 | }
283 |
284 | public VHTChannelWidth ChannelWidth;
285 | }
286 |
287 | public VHTCapabilities Capabilities { get; set; }
288 | public VHTOperations Operations { get; set; }
289 | }
290 |
291 |
292 | #endregion Public Methods
293 |
294 | #region Private Methods
295 |
296 | private class McsSet
297 | {
298 | //20MHz long GI
299 | private static readonly Dictionary LGiTable20 = new Dictionary
300 | {
301 | {0, 6f},//6.5
302 | {1, 13f},
303 | {2, 19f}, //19.5
304 | {3, 26f},
305 | {4, 39f},
306 | {5, 52f},
307 | {6, 58f},
308 | {7, 65f}
309 | };
310 |
311 | //20MHz short GI
312 | private static readonly Dictionary SGiTable20 = new Dictionary
313 | {
314 | {0, 7f}, //7.2
315 | {1, 14f},//14.4
316 | {2, 22f},//21.7
317 | {3, 29f},//28.9
318 | {4, 43f},//43.3
319 | {5, 58f},//57.8
320 | {6, 65f},
321 | {7, 72f} //72.2
322 | };
323 |
324 | //40MHz long GI
325 | private static readonly Dictionary LGiTable40 = new Dictionary
326 | {
327 | {0, 13f}, //13.5
328 | {1, 27f},
329 | {2, 40f},//40.5
330 | {3, 54f},
331 | {4, 81f},
332 | {5, 108f},
333 | {6, 121f},
334 | {7, 135f}
335 | };
336 |
337 | //40MHz short GI
338 | private static readonly Dictionary SGiTable40 = new Dictionary
339 | {
340 | {0, 15f},
341 | {1, 30f},
342 | {2, 45f},
343 | {3, 60f},
344 | {4, 90f},
345 | {5, 120f},
346 | {6, 135f},
347 | {7, 150f}
348 | };
349 |
350 | public static float GetSpeed(uint index, bool shortGi20MHz, bool shortGi40MHz, bool fortyMHz)
351 | {
352 | float output;
353 |
354 | if (index > 32) return 0f;
355 | int streams = 0;
356 |
357 | if (index >= 0 && index < 8)
358 | {
359 | streams = 1;
360 | }
361 | else if (index >= 8 && index < 16)
362 | {
363 | streams = 2;
364 | index -= 8;
365 | }
366 | else if (index >= 16 && index < 24)
367 | {
368 | streams = 3;
369 | index -= 16;
370 | }
371 | else if (index >= 24 && index < 32)
372 | {
373 | streams = 4;
374 | index -= 24;
375 | }
376 |
377 | if (fortyMHz)
378 | {
379 | if (shortGi40MHz)
380 | {
381 | output = SGiTable40[index];
382 | output *= streams;
383 | }
384 | else
385 | {
386 | output = LGiTable40[index];
387 | output *= streams;
388 | }
389 | }
390 | else //20 MHz channel
391 | {
392 | if (shortGi20MHz)
393 | {
394 | output = SGiTable20[index];
395 | output *= streams;
396 | }
397 | else
398 | {
399 | output = LGiTable20[index];
400 | output *= streams;
401 | }
402 | }
403 |
404 | return output;
405 | }
406 | }
407 |
408 | #endregion Private Methods
409 | }
410 |
411 |
412 | }
--------------------------------------------------------------------------------
/WlanInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Net.NetworkInformation;
4 | using System.Runtime.InteropServices;
5 | using System.Threading;
6 |
7 | namespace ManagedWifi
8 | {
9 | public class WlanInterface
10 | {
11 | #region Fields
12 |
13 | private readonly WlanClient _client;
14 | private readonly Queue