Report abuse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
/*
 *  VoodooWirelessDevice.h
 *  VoodooWireless
 *
 *  Created by Prashant Vaibhav on 12/06/09.
 *  Copyright 2009 Prashant Vaibhav. All rights reserved.
 *
 */

#ifndef _H_VOODOOWIRELESSDEVICE_H
#define _H_VOODOOWIRELESSDEVICE_H

#include <sys/types.h>
#include <sys/kpi_mbuf.h>

#include <IOKit/IOService.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOWorkLoop.h>

#include <IOKit/apple80211/IO80211Controller.h>
#include <IOKit/apple80211/IO80211Interface.h>
#include <IOKit/apple80211/IO80211WorkLoop.h>
#include <IOKit/network/IOOutputQueue.h>

#include "VoodooWirelessFamily.h"
#include "VoodooIEEE80211.h"
#include "VoodooWirelessDevice_Types.h"

using namespace org_voodoo_wireless;

class VoodooWirelessDevice : public IO80211Controller
{
public:
	/* NOTE: None of the public functions need to be implemented by subclasses. Proper implementations
	 *       is already provided by this superclass */
	
	/* Basic IOKit functions */
	virtual bool		start			( IOService* provider );
	virtual void		stop			( IOService* provider );
	IOReturn		registerWithPolicyMaker	( IOService* policyMaker );
	
	/* Network driver and apple80211 functions */
	SInt32			apple80211Request	( UInt32 request_type, int request_number,
							  IO80211Interface* interface, void* data );
	IOReturn		enable			( IONetworkInterface* aNetif );
	IOReturn		disable			( IONetworkInterface* aNetif );
	IOOutputQueue*		createOutputQueue	( );
	
	UInt32			outputPacket		( mbuf_t m, void* param );

	IOReturn		getMaxPacketSize	( UInt32 *maxSize ) const;
	const OSString*		newVendorString		( ) const;
	const OSString*		newModelString		( ) const;
	const OSString*		newRevisionString	( ) const;
	IOReturn		getHardwareAddress	( IOEthernetAddress* addr );
	virtual IOReturn	setPromiscuousMode	( IOEnetPromiscuousMode mode );
	virtual IOReturn	setMulticastMode	( IOEnetMulticastMode mode );
	virtual IOReturn	setMulticastList	( IOEthernetAddress* addr, UInt32 len );
	virtual SInt32		monitorModeSetEnabled	( IO80211Interface * interface, bool enabled, UInt32 dlt );
	
protected:
	struct ExpansionData {};		// reserved, for internal use only
	ExpansionData*		reserved;	// reserved, for internal use only
	
	/* Functions to init / shutdown the HW */
	virtual IOReturn	allocateResources	( );	// Allocate hw rings, memory etc. needed for power up
	virtual void		freeResources		( );	// Undo all allocations done in allocateResources()
	virtual IOReturn	turnPowerOn		( );	// Make the card ready for action
	virtual IOReturn	turnPowerOff		( );	// Turn the card off
	
	/* Functions for establishing connections, scanning etc. */
	virtual IOReturn	startScan		( const ScanParameters* params,
							  const IEEE::ChannelList* channels );
	
	virtual void		abortScan		( );
	virtual IOReturn	associate		( const AssociationParameters* params );
	virtual IOReturn	disasssociate		( );
	
	/* Various configuration functions */
	virtual void		getHardwareInfo		( HardwareInfo* info );
	virtual IOReturn	getConfiguration	( HardwareConfigType type, void* param );
	virtual IOReturn	setConfiguration	( HardwareConfigType type, void* param );
	
	/* The following function should be called by subclasses to report events. */
	void			report			( DeviceResponseMessage msg, void* arg );
	
	/* This is to be called by subclasses when it receives any frames from HW.
	 * "data" should be raw 802.11 frame.
	 * During scanning, beacon or probe response frames should be passed via this function
	 */
	void			inputFrame		( RxFrameHeader hdr, mbuf_t data );
	
	/* This function must be implemented by the subclass to output a raw 802.11 frame.
	 * Note that the mbuf_t could either be a single mbuf or a chain of 2 or more mbufs.
	 * The passed mbuf_t becomes property of the driver which should free it when it is no longer needed.
	 */
	virtual IOReturn	outputFrame		( TxFrameHeader hdr, mbuf_t data );
	
private:
	HardwareInfo		_hwInfo;
	uint32_t		_flags;
	IOSimpleLock*		_simpleLock;
		
	/* The following are reserved slots for future expansion */
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 0);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 1);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 2);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 3);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 4);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 5);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 6);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 7);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 8);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 9);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 10);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 11);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 12);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 13);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 14);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 15);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 16);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 17);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 18);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 19);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 20);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 21);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 22);
	OSMetaClassDeclareReservedUnused(VoodooWirelessDevice, 23);
};

#endif//_H_VOODOOWIRELESSDEVICE_H

/*
 *  VoodooWirelessDevice_Types.h
 *  VoodooWireless
 *
 *  Created by Prashant Vaibhav on 16/06/09.
 *  Copyright 2009 Prashant Vaibhav. All rights reserved.
 *
 */

#ifndef _H_VOODOOWIRELESSDEVICE_TYPES_H
#define _H_VOODOOWIRELESSDEVICE_TYPES_H

#include <libkern/c++/OSSymbol.h>
#include <libkern/c++/OSString.h>
#include "VoodooWirelessFamily.h"
#include "VoodooIEEE80211.h"

namespace org_voodoo_wireless {
	
	struct ScanParameters {
		enum ScanType {	scanTypeActive, scanTypePassive, scanTypeBackground };
		ScanType		scanType;	// Type of scan (active/passive..)
		IEEE::PHYModes		scanPhyMode;	// 11a,b,g or n on which to scan
		IEEE::MACAddress	bssid;		// BSSID to which scan is directed
		OSSymbol*		ssid;		// SSID (network name) to which scan is directed
		uint32_t		dwellTime;	// Time to stay on each channel (ms)
		uint32_t		restTime;	// Time to wait between channels (ms)
	};
	
	struct ScanResult {
		IEEE::Channel		channel;	// channel on which this AP is operating
		IEEE::Capability	capability;	// AP capability flags
		IEEE::MACAddress	bssid;		// BSSID of access point
		OSSymbol*		ssid;		// Network name
		int			noiseLevel;	// background noise
		int			signalLevel;	// signal strength
		IEEE::RateSet		supportedRates;	// rates that the AP supports
		uint32_t		beaconInterval;	// in ms
		uint32_t		age;		// how old is this result (in ms)
		IEList*			extraIEs;	// extra information elements sent in the probe response
	};
	
	struct AssociationParameters {
		OSSymbol*		ssid;		// not needed usually, but providing anyway
		IEEE::MACAddress	bssid;
		IEEE::Channel		channel;
		IEEE::Capability	capability;
		IEEE::RateSet		supportedRates;	// That the AP supports
		uint32_t		beaconInterval;
		enum APMode { apModeAny, apModeAdHoc, apModeInfrastructure };
		APMode			connectionMode;
		enum AuthType {
			/* LSB signifies lower auth mode (to be OR'd with upper auth mode if needed) */
			authTypeNone	= 0,		// Open authentication
			authTypeShared	= 1,		// WEP key shared authentication
			/* Upper auth modes (even number only as LSB is taken) */
			authTypeWPA	= 2,
			authTypeWPAPSK	= 4,
			authTypeWPA2	= 6,
			authTypeWPA2PSK	= 8,
			authtypeLEAP	= 10,
			authType8021X	= 12,
			authTypeWPS	= 14
		};
		AuthType		authType;
		IEEE::WEPKey		wepKey;		// if key is zero length, then no WEP
		IEList*			extraIEs;	// info elements used with RSN (WPA etc.)
		bool			closedNetwork;	// indicates assoc request is for directed scanned network
	};
	
	struct RxFrameHeader {
		/* information about an incoming frame */
		IEEE::Channel		channel;
		IEEE::DataRate		rate;
		int			signalLevel;	// signal strength
		bool			decrypted;	// whether HW has already decrypted this frame
	};
	
	struct TxFrameHeader {
		IEEE::DataRate		rate;		// desired Tx rate (can be ignored by HW)
		bool			encrypted;	// whether this frame is already encrypted
	};
	
	struct HardwareCapabilities {
		/* Which features does the hardware support */
		bool	WEP		:1;	// the cipher. if 0, will fall back to software cipher
		bool	TKIP		:1;	// the cipher. if 0, will fall back to software cipher
		bool	TKIP_MIC	:1;	// hardware TKIP MIC support. if 0, fall back to full software TKIP
		bool	AES_CCMP	:1;	// the cipher. if 0, will fall back to software cipher
		bool	WPA1		:1;	// connecting to WPA1. if 0, WPA1 will not be available at all
		bool	WPA2		:1;	// connecting to WPA2. if 0, WPA2 will not be available at all
		
		bool	AdHocMode	:1;
		bool	HostAPMode	:1;
		bool	MonitorMode	:1;
		
		bool	PowerManagement	:1;	// active 802.11 power management, not IOKit power management
		bool	TxPowerManagement:1;	// transmit power can be set
		bool	WakeOneWireless	:1;
		
		bool	ShortSlot	:1;
		bool	ShortPreamble	:1;
		bool	FrameBursting	:1;
		bool	WMEQoS		:1;
		bool	ShortGuardInterval20MHz	:1;
		bool	ShortGuardInterval40MHz	:1;
		
		bool	hardwareRoaming	:1;	// hardware can migrate to different APs on its own
	};
	
	enum PowerSavingModes {
		powerSaveAlwaysOn	= 1,
		powerSaveNormal		= 2,		// middle-level power saving
		powerSaveMaximum	= 4		// maximum power savings
	};
	
	enum HardwareConfigType {
		/* Which kind of config to get/set, when get/setConfig is called. Any of this can be ignored */
		configTxPower,			// param = int txPower
		configRTSThreshold,		// param = uint32_t threshInBytes
		configFragmentationThreshold,	// param = uint32_t threshInBytes
		configShortRetryLimit,		// param = uint32_t numRetries
		configLongRetryLimit,		// param = uint32_t numRetries
		configCurrentTxRate,		// param = IEEE::DataRate
		configRateSet,			// param = IEEE::RateSet [working rates, not HW supported rates]
		configInterferenceMitigation,	// param = bool turnOn [HW dependent, usually bluetooth interference]
		config11GProtection		// param = bool turnOn [used in mixed 11bg networks]
	};
	
	struct HardwareInfo {
		/* Note: strings should not have been allocated already, they will be allocated
			 by the driver itself. Ownership is then passed to the superclass who must
			 release the strings. In other words, this struct should be zero filled
			 before being passed to subclass. */
		OSString*		manufacturer;
		OSString*		model;
		OSString*		hardwareRevision;
		OSString*		driverVersion;
		OSString*		firmwareVersion;
		IEEE::MACAddress	hardwareAddress;
		IEEE::PHYModes		supportedModes;		// OR'd bits if it's multi-mode PHY
		IEEE::ChannelList	supportedChannels;	// independent of locale
		IEEE::RateSet		supportedRates;		// that hardware supports, not what it's using now
		unsigned int		maxTxPower;		// in dBm, independent of locale
		enum SNRUnit { unit_dBm, unit_Percent, unit_mW, unit_Other_Linear, unit_Other_Logarithmic };
		SNRUnit			snrUnit;		// which units are noise/signal levels reported in
		PowerSavingModes	powerSavingModes;	// which modes does hardware support
		HardwareCapabilities	capabilities;
		uint32_t		maxPacketSize;		// largest packet size which this HW can transmit
		uint32_t		txQueueSize;		// how many packets can be sent to HW's tx queue
	};
	
	enum DeviceResponseMessage {
		msgNull	= iokit_vendor_specific_msg(1),	// XXX: not used
		
		msgPowerOff,			// HW power was turned off without being requested
		msgPowerOn,			// HW power was turned on without being requested
		msgRadioOff,			// PHY was turned off by user or power saving
		msgRadioOn,			// PHY was turned on by user or power saving
		
		msgScanAborted,			// scan was aborted (by HW, not as response to client request)
		msgScanCompleted,		// scanning all specified chanels is completed
		msgChannelScanned,		// scanning a specific channel is completed (arg=Channel*)
		
		msgAuthenticationFailed,	// authentication step failed
		msgAuthenticationDone,		// authentication step was done
		msgAssociationFailed,		// association with AP failed, arg=IEEE::ReasonCode*
		msgAssociationDone,		// association was finished successfully
		msgDeassociationFailed,		// deassoc request failed, arg=IEEE::ReasonCode*
		msgDeassociationDone,		// deassociated from AP, arg=IEEE::ReasonCode*
		msgDeauthenticated,		// deauthenticated from AP, arg=IEEE::ReasonCode*
		
		msgNoiseLevelReport,		// reporting noise level, arg=int* noiseLevel
		msgSignalStrengthReport,	// reporting signal strength, arg=int* signalStrength
		msgChannelSwitch,		// reporting AP channel switch, arg=Channel* newChan
		msgLinkQualityReport,		// reporting link quality, arg=int* qualityLevel
		msgBeaconMissed,		// reporting missed beacon, arg=uint32_t* howManyMissed
		msgConfigChanged,		// reporting a change in HW config (without being requested)
						// arg=HardwareConfigType* type, client may call getConfig after this
		
		msgMaxMessageNumber		// XXX: used to check if msg num was out of bound
	};
};

#endif


/*
 *  VoodooIEEE80211_Types.h
 *  VoodooWireless
 *
 *  Created by Prashant Vaibhav on 16/06/09.
 *  Copyright 2009 Prashant Vaibhav. All rights reserved.
 *
 */


#ifndef _H_VOODOOIEEE80211_TYPES_H
#define _H_VOODOOIEEE80211_TYPES_H

#include "VoodooWirelessFamily.h"

namespace org_voodoo_wireless {
namespace IEEE {
	struct MACAddress {
		/* Defining this again here because families should not have to use another
		 family's headers, and IOEthernetAddress is defined in IOEthernetFamily */
		uint8_t bytes[6];
	};
	
	struct WEPKey {
		uint8_t		index;		// 0 to 3
		OSString*	key;		// 40 or 104 bits (5 or 13 bytes)
	};
	
	enum PHYModes {
		dot11A	= 1,		// 5GHz OFDM
		dot11B	= 2,		// 2.4GHz CCK
		dot11G	= 4,		// 2.4GHz OFDM
		dot11N	= 8,		// 2.4GHz or 5GHz MIMO
	};
	
	const size_t MAX_CHANNELS = 64;
	const size_t MAX_RATES = 32;
	
	struct Channel {
		uint8_t			number;		// Channel number
		uint16_t		flags;		// Channel type flags
		enum Flags {
			supportsActiveScanning	= 0x1,
			band2GHz		= 0x2,
			band5GHz		= 0x4,
			width10MHz		= 0x8,
			width20MHz		= 0x10,
			width40MHz		= 0x20,
			requiresDFS		= 0x40,	// dynamic frequency selection for 11a
			supportsHostAPMode	= 0x80,
			supportsAdHocMode	= 0x100,
			extensionChannelIsAbove	= 0x200 // in 11n mode, if ext. ch is above this ch. (otherwise below)
		};
	};
	
	struct ChannelList {
		size_t			numItems;
		Channel			channel[MAX_CHANNELS];
	};
	
	enum DataRate {
		rateIsBasic	= 128,	// basic rates should be OR'd with this value (ie. bit 7 = 1)
		/* Rates are just uint32_t, in 0.5 Mbps units */
		rate1Mbps	= 2,	// 1 Mbps CCK
		rate2Mbps	= 4,	// 2 Mbps CCK
		rate5Mbps	= 10,	// 5.5 Mbps CCK
		rate6Mbps	= 12,	// 6 Mbps OFDM
		rate9Mbps	= 18,	// 9 Mbps OFDM
		rate11Mbps	= 22,	// 11 Mbps CCK
		rate12Mbps	= 24,	// 12 Mbps OFDM
		rate18Mbps	= 36,	// 18 Mbps OFDM
		rate24Mbps	= 48,	// 24 Mbps OFDM
		rate36Mbps	= 72,	// 36 Mbps OFDM
		rate48Mbps	= 96,	// 48 Mbps OFDM
		rate54Mbps	= 108,	// 54 Mbps OFDM
		/* 11n MIMO rates to be added later */
	};
	
	struct RateSet {
		size_t			numItems;
		DataRate		rate[MAX_RATES];
	};
	
	enum ReasonCode {
		// § 7.3.1.7 Table 7-22
		reasonUnspecified		= 1,
		reasonPreviousAuthExpired	= 2,
		reasonDeauthBecauseSTALeft	= 3,
		reasonDisassocDueToInactivity	= 4,
		reasonAPFull			= 5,
		reasonClass2FrameRxWithoutAuth	= 6,
		reasonClass3FrameRxWithoutAssoc	= 7,
		reasonDisassocBecauseSTALeft	= 8,
		reasonNotAuthorized		= 9,
		reasonPowerCapsUnacceptable	= 10,
		reasonSupportedChannelsUnacceptable = 11,
		reasonInvalidIE			= 13, /* 12 is reserved */
		reasonMICFailure		= 14,
		reason4WayHandshakeTimeout	= 15,
		reasonGroupKeyHandshakeTimeout	= 16,
		reasonIEMismatch		= 17,
		reasonInvalidGroupCipher	= 18,
		reasonInvalidPairwiseCipher	= 19,
		reasonInvalidAKMP		= 20,
		reasonUnsupportedRSNIE		= 21,
		reasonInvalidRSNIECaps		= 22,
		reason8021XAuthFailed		= 23,
		reasonCipherSuiteRejected	= 24,
		reasonQoS			= 32, /* 25-31 reserved */
		reasonQoSBandwidthUnavailable	= 33,
		reasonTooManyACKs		= 34,
		reasonTXOPsOutsideLimits	= 35,
		reasonPeerSTALeaving		= 36,
		reasonPeerSTAMechanismRejected	= 37,
		reasonPeerSTAMechanismNeedsSetup= 38,
		reasonPeerSTATimeout		= 39,
		reasonPeerSTACipherUnsupported	= 45, /* 40-44 reserved */
		reasonPrivateUnspecified	= 0xffff /* our own unspecified failure code */
	};
	
	struct IE {
		enum ID {
			/* § 7.3.2 Table 7-26 */
			ieSSID			= 0,	ieSupportedRates	= 1,
			ieFHParamSet		= 2,	ieDSParamSet		= 3,
			ieCFParamSet		= 4,	ieTIM			= 5,
			ieIBSSParamSet		= 6,	ieCountry		= 7,
			ieHoppingPatternParams	= 8,	ieHoppingPatternTable	= 9,
			ieRequest		= 10,	ieBSSLoad		= 11,
			ieEDCAParamSet		= 12,	ieTSPEC			= 13,
			ieTCLAS			= 14,	ieSchedule		= 15,
			ieChallengeText		= 16,	/* 17-31 reserved */
			iePowerConstraint	= 32,	iePowerCapability	= 33,
			ieTPCRequest		= 34,	ieTPCReport		= 35,
			ieSupportedChannels	= 36,	ieChannelSwitchAnnounce	= 37,
			ieMeasurementRequest	= 38,	ieMeasurementReport	= 39,
			ieQuiet			= 40,	ieIBSSDFS		= 41,
			ieERPInformation	= 42,	ieTSDelay		= 43,
			ieTCLASProcessing	= 44,	/* 45 reserved */
			ieQoSCapability		= 46,	/* 47 reserved */
			ieRSN			= 48,	/* 49 reserved */
			ieExtendedSupportedRates= 50,	/* 51-125 reserved */
			/* 126 reserved */		ieExtendedCapabilities	= 127,
			/* 128-220 reserved */		ieVendorSpecific	= 221,
			/* 222-255 reserved */
		};
		uint8_t		id;		// type codes specified in enum ID
		uint8_t		length;		// length in bytes of data that follows
		uint8_t		data[0];	// variable length up to 255 bytes
	} __packed;
	
	union Capability {
		struct {
			/* § 7.3.1.4 */
			bool	ESS		:1;
			bool	IBSS		:1;	// indicates Ad-hoc mode
			bool	CFPollable	:1;
			bool	CFPollRequest	:1;
			bool	Privacy		:1;	// indicates WEP on/off
			bool	ShortPreamble	:1;
			bool	PBCC		:1;
			bool	ChannelAgility	:1;
			bool	SpectrumMgmt	:1;
			bool	QoS		:1;
			bool	ShortSlotTime	:1;
			bool	APSD		:1;
			bool	Reserved	:1;
			bool	DSSSOFDM	:1;	// indicates 11g mode on/off
			bool	DelayedBlockAck	:1;
			bool	ImmediateBlockAck:1;
		} bits __packed;
		uint16_t	value;
	} __packed;
	
	
	/* Following is the structure of a MAC header present in ALL frames. The remaining
	 * contents of the frame depend on the type/subtype etc. § 7.2 onwards
	 */	
	struct WiFiFrameHeader
	{
		enum FrameType {
			ManagementFrame	= 0,
			ControlFrame	= 1,
			DataFrame	= 2,
			ReservedFrame	= 3
		};
		
		enum FrameSubtype {
			/* Subtype for Management frames: */
			AssocRequest	= 0,	AssocResponse	= 1,
			ReassocRequest	= 2,	ReassocResponse	= 3,
			ProbeRequest	= 4,	ProbeResponse	= 5,
			/* 6-7 are reserved */
			Beacon		= 8,	ATIM		= 9,
			Disassoc	= 10,	Authentication	= 11,
			DeAuthentication= 12,	Action		= 13,
			/* 14-15 are reserved */
			
			/* Subtypes for Control frames: */
			/* 0-7 are reserved */
			BlockAckReq	= 8,	BlockAck	= 9,
			PSPoll		= 10,	RTS		= 11,
			CTS		= 12,	ACK		= 13,
			CFEnd		= 14,	CFEndPoll	= 15,
			
			/* Subtypes for Data frames: */
			Data		= 0,	DataCFAck	= 1,
			DataCFPoll	= 2,	DataCFAckPoll	= 3,
			Null		= 4,	CFAck		= 5,
			CFPoll		= 6,	CFAckPoll	= 7,
			QoSData		= 8,	QoSDataCFAck	= 9,
			QoSDataCFPoll	= 10,	QoSDataCFAckPoll = 11,
			QoSNull		= 12,	/* 13 is reserved */
			QoSCFPoll	= 14,	QoSCFAckCFPoll	= 15
		};
		
		uint8_t		protocolVersion	:2;
		FrameType	type		:2;
		FrameSubtype	subtype		:4;
		bool		toDS		:1;
		bool		fromDS		:1;
		bool		moreFrag	:1;
		bool		retry		:1;
		bool		powerSaveMode	:1;	// Called PwrMgt in spec
		bool		moreData	:1;
		bool		protectedFrame	:1;
		bool		order		:1;
		
		uint16_t	durationID	:16;
		
		/* The following is also present in all MAC headers, but we won't
		 * put in here because its meaning depends on the particular frame type
		 IOEthernetAddress	addr1;
		 */
	} __packed;
	
	struct SequenceControl {
		uint8_t		fragmentNumber	:4;
		uint16_t	sequenceNumber	:12;
	} __packed;
	
	struct ManagementFrameHeader
	{
		WiFiFrameHeader		hdr;
		uint8_t			da[6];
		uint8_t			sa[6];
		uint8_t			bssid[6];
		SequenceControl		sequenceControl;
	} __packed;
	
	struct ProbeResponseFrameHeader {
		ManagementFrameHeader	mgmt;
		uint64_t		timestamp;
		uint16_t		beaconInterval;
		uint16_t		capability;
		/* Then follows a variable number of information elements */
		uint8_t			ieData[0];
	} __packed;
	
	struct TxDataFrameHeader {
		WiFiFrameHeader		hdr;
		uint8_t			bssid[6];
		uint8_t			sa[6]; // source MAC addr
		uint8_t			da[6]; // dest MAC addr
		uint16_t		seq;
		uint8_t			data[0]; // variable length
	} __packed;
	
	struct TxQoSDataFrameHeader {
		WiFiFrameHeader		hdr;
		uint8_t			bssid[6];
		uint8_t			sa[6]; // source MAC addr
		uint8_t			da[6]; // dest MAC addr
		uint16_t		seq;
		uint16_t		qos;
		uint8_t			data[0]; // variable length
	} __packed;
	
	struct EthernetFrameHeader {
		uint8_t			da[6];
		uint8_t			sa[6];
		uint8_t			frameType[2]; // always = 0x80 0x00
		uint8_t			data[0]; // variable length
	} __packed;
	
}
}

#endif