1: /*
2:
3: File: WiFiController.cpp
4: Program: GTDriver
5: Author: Michael Roßberg
6: mick@binaervarianz.de
7: Description: GTDriver is a free driver for PrismGT based cards under OS X.
8:
9: This file is part of GTDriver.
10:
11: GTDriver is free software; you can redistribute it and/or modify
12: it under the terms of the GNU General Public License as published by
13: the Free Software Foundation; either version 2 of the License, or
14: (at your option) any later version.
15:
16: GTDriver is distributed in the hope that it will be useful,
17: but WITHOUT ANY WARRANTY; without even the implied warranty of
18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: GNU General Public License for more details.
20:
21: You should have received a copy of the GNU General Public License
22: along with GTDriver; if not, write to the Free Software
23: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24: */
25:
26: #include "WiFiController.h"
27:
28: #include <IOKit/pccard/IOPCCard.h>
29:
30: #define ONE_SECOND_TICKS 1000
31: #define LOAD_STATISTICS_INTERVAL (4 * ONE_SECOND_TICKS)
32:
33: #define super IOEthernetController
34: OSDefineMetaClassAndStructors(WiFiController, IOEthernetController)
35:
36: extern "C" {
37: #include <sys/sockio.h>
38: }
39:
40: //---------------------------------------------------------------------------
41: // Function: initDriver
42: //
43: // Create and initialize driver objects before the hardware is
44: // enabled.
45: //
46: // Returns true on sucess, and false if initialization failed.
47:
48: bool WiFiController::_initDriver(IOService * provider) {
49: //currentMediumType = MEDIUM_TYPE_INVALID;
50:
51: // This driver will allocate and use an IOGatedOutputQueue.
52: //
53: _transmitQueue = getOutputQueue();
54: if (_transmitQueue == NULL) return false;
55:
56: // Allocate two IOMbufLittleMemoryCursor instances. One for transmit and
57: // the other for receive.
58: //
59: //rxMbufCursor = IOMbufLittleMemoryCursor::withSpecification(MAX_BUF_SIZE,1);
60: //txMbufCursor = IOMbufLittleMemoryCursor::withSpecification(MAX_BUF_SIZE,
61: // TBDS_PER_TCB);
62: //if (!rxMbufCursor || !txMbufCursor)
63: // return false;
64:
65: // Get a handle to our superclass' workloop.
66: //
67: IOWorkLoop *myWorkLoop = (IOWorkLoop *) getWorkLoop();
68: if (!myWorkLoop) return false;
69:
70: // Create and register an interrupt event source. The provider will
71: // take care of the low-level interrupt registration stuff.
72: //
73: _interruptSrc = IOInterruptEventSource::interruptEventSource(
74: this,
75: (IOInterruptEventAction) &WiFiController::interruptOccurred,
76: provider);
77:
78: if (!_interruptSrc ||
79: (myWorkLoop->addEventSource(_interruptSrc) != kIOReturnSuccess))
80: return false;
81:
82: // This is important. If the interrupt line is shared with other devices,
83: // then the interrupt vector will be enabled only if all corresponding
84: // interrupt event sources are enabled. To avoid masking interrupts for
85: // other devices that are sharing the interrupt line, the event source
86: // is enabled immediately.
87:
88: _interruptSrc->enable();
89:
90: // Register a timer event source. This is used as a watchdog timer.
91: //
92: _timerSrc = IOTimerEventSource::timerEventSource(this,
93: (IOTimerEventSource::Action)&WiFiController::timeoutOccurred);
94: if (!_timerSrc ||
95: (myWorkLoop->addEventSource(_timerSrc) != kIOReturnSuccess))
96: return false;
97:
98: // Create a dictionary to hold IONetworkMedium objects.
99: //
100: _mediumDict = OSDictionary::withCapacity(MEDIUM_TYPE_INVALID + 1);
101: if (!_mediumDict)
102: return false;
103:
104: _addMediumType(kIOMediumIEEE80211None, 0, MEDIUM_TYPE_NONE);
105: _addMediumType(kIOMediumIEEE80211Auto, 0, MEDIUM_TYPE_AUTO);
106: /*_addMediumType(kIOMediumIEEE80211DS1, 1000000, MEDIUM_TYPE_1MBIT);
107: _addMediumType(kIOMediumIEEE80211DS2, 2000000, MEDIUM_TYPE_2MBIT);
108: _addMediumType(kIOMediumIEEE80211DS5, 5500000, MEDIUM_TYPE_5MBIT);
109: _addMediumType(kIOMediumIEEE80211DS11, 11000000, MEDIUM_TYPE_11MBIT);
110: _addMediumType(kIOMediumIEEE80211, 54000000, MEDIUM_TYPE_54MBIT, "OFDM54");
111: */
112: _currentMediumType = MEDIUM_TYPE_AUTO;
113:
114: setLinkStatus(kIONetworkLinkValid, _getMediumWithType(MEDIUM_TYPE_NONE));
115:
116: return true;
117: }
118: /*
119:
120: bool
121: WiFiController::attachRawInterface(IONetworkInterface ** interfaceP,
122: bool doRegister)
123: {
124: IONetworkInterface * netif;
125:
126: *interfaceP = 0;
127:
128: do {
129: // Allocate a concrete subclass of IONetworkInterface
130: // by calling createInterface().
131:
132: netif = createRawInterface();
133: if (!netif)
134: break;
135:
136: // Configure the interface instance by calling
137: // configureInterface(), then attach it as our client.
138:
139: if ( !configureInterface(netif) || !netif->attach(this) )
140: {
141: netif->release();
142: break;
143: }
144:
145: *interfaceP = netif;
146:
147: // Register the interface nub. Spawns a matching thread.
148:
149: if (doRegister)
150: netif->registerService();
151:
152: return true; // success
153: }
154: while (0);
155:
156: return false; // failure
157: }
158:
159: //---------------------------------------------------------------------------
160: // Allocate and return a new BIWiFiInterface instance.
161:
162: IONetworkInterface * WiFiController::createRawInterface()
163: {
164: BIWiFiInterface * netif = new BIWiFiInterface;
165:
166: if ( netif && ( netif->init( this ) == false ) )
167: {
168: netif->release();
169: netif = 0;
170: }
171: return netif;
172: }*/
173:
174: //---------------------------------------------------------------------------
175: // Function: start <IOService>
176: //
177: // Hardware was detected and initialized, start the driver.
178:
179: bool WiFiController::start(IOService * provider) {
180: bool ret = false;
181: bool started = false;
182:
183: memset(_ssid, 0, sizeof(_ssid));
184: _ssidLength = 0;
185: _linkSpeed = 0;
186: _currentState = stateIntializing;
187: _currentMode = modeClient;
188: _currentFrequency = 2412;
189: _packetQueue = IODataQueue::withCapacity(16384); // allocate 16KB for caching output in monitor mode
190:
191: do {
192: started = true;
193:
194: // Start our superclass first.
195: if (super::start(provider) == false)
196: break;
197:
198: if (startProvider(provider) == false) break;
199:
200: // Initialize the driver's event sources and other support objects.
201: if (_initDriver(provider) == false) break;
202:
203: // Get default driver settings (stored in property table).
204: //if (getDefaultSettings() == false) break;
205:
206: // Execute one-time initialization code.
207: if (startHardware() == false) break;
208:
209: if (publishMediumDictionary(_mediumDict) == false) {
210: WLLogErr("publishMediumDictionary failed\n");
211: break;
212: }
213:
214: ret = true;
215: }
216: while (false);
217:
218: _cardGone = false;
219:
220: // Close our provider, it will be re-opened on demand when
221: // our enable() method is called.
222: closeProvider();
223:
224: do {
225: if (ret == false) break;
226:
227: ret = false;
228:
229: // Allocate and attach an IOEthernetInterface instance to this driver
230: // object.
231:
232: if (attachInterface((IONetworkInterface **) &_netif, false) == false) break;
233: // Start matching for clients of IONetworkInterface.
234: /*
235: IOEthernetAddress addr;
236: addr.bytes[0] = 0x00;
237: addr.bytes[1] = 0x00;
238: addr.bytes[2] = 0x00;
239: addr.bytes[3] = 0x00;
240: addr.bytes[4] = 0x00;
241: addr.bytes[5] = 0x23;
242: setProperty("IOMACAddress2", (void *) &addr, kIOEthernetAddressSize);
243:
244: if (attachRawInterface((IONetworkInterface **) &_rawNetif, false) == false) break;
245: */
246:
247: _netif->registerService();
248: //_rawNetif->registerService();
249: registerService();
250:
251: ret = true;
252: }
253: while (false);
254:
255: // Issue a stop on failure.
256: if (started && !ret) super::stop(provider);
257:
258: return ret;
259: }
260:
261: //---------------------------------------------------------------------------
262: // Function: createWorkLoop <IONetworkController>
263: //
264: // Override IONetworkController::createWorkLoop() method to create and return
265: // a new work loop object.
266:
267: bool WiFiController::createWorkLoop() {
268: _workLoop = IOWorkLoop::workLoop();
269:
270: return (_workLoop != NULL);
271: }
272:
273: //---------------------------------------------------------------------------
274: // Function: getWorkLoop <IOService>
275: //
276: // Override IOService::getWorkLoop() method and return a reference to our
277: // work loop.
278:
279: IOWorkLoop * WiFiController::getWorkLoop() const {
280: return _workLoop;
281: }
282:
283: //---------------------------------------------------------------------------
284: // Function: configureInterface <IONetworkController>
285: //
286: // Configure a newly instantiated IONetworkInterface object.
287:
288: bool WiFiController::configureInterface(IONetworkInterface * netif) {
289: IONetworkData * data;
290:
291: if (super::configureInterface(netif) == false)
292: return false;
293:
294: // Get the generic network statistics structure.
295:
296: data = netif->getParameter(kIONetworkStatsKey);
297: if (!data || !(_netStats = (IONetworkStats *)data->getBuffer())) {
298: return false;
299: }
300:
301: // Get the Ethernet statistics structure.
302:
303: data = netif->getParameter(kIOEthernetStatsKey);
304: if (!data || !(_etherStats = (IOEthernetStats *)data->getBuffer())) {
305: return false;
306: }
307:
308: return true;
309: }
310:
311: //---------------------------------------------------------------------------
312: // Function: free <IOService>
313: //
314: // Deallocate all resources and destroy the instance.
315:
316: void WiFiController::free() {
317: #define RELEASE(x) do { if(x) { (x)->release(); (x) = 0; } } while(0)
318:
319: RELEASE(_netif);
320: //RELEASE(_rawNetif);
321: if (_interruptSrc && _workLoop) {
322: _workLoop->removeEventSource(_interruptSrc);
323: }
324:
325: freeHardware();
326:
327: RELEASE(_interruptSrc);
328: RELEASE(_timerSrc );
329: RELEASE(_mediumDict );
330: RELEASE(_workLoop );
331: RELEASE(_packetQueue );
332:
333: freeProvider();
334:
335: if (_powerOffThreadCall) {
336: thread_call_free(_powerOffThreadCall);
337: _powerOffThreadCall = 0;
338: }
339:
340: if (_powerOnThreadCall) {
341: thread_call_free(_powerOnThreadCall);
342: _powerOnThreadCall = 0;
343: }
344:
345: super::free(); // pass it to our superclass
346: }
347:
348: //---------------------------------------------------------------------------
349: // Function: enableAdapter
350: //
351: // Enables the adapter & driver to the given level of support.
352:
353: bool WiFiController::enableAdapter() {
354: // Open provider.
355: //
356: if (!openProvider()) {
357: WLLogErr("Could not open Provider");
358: return false;
359: }
360: if (!enableHardware()) {
361: WLLogErr("Could not enable Hardware");
362: return false;
363: }
364:
365: // Start our IOOutputQueue object.
366: //
367: _transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE);
368: _transmitQueue->start();
369:
370: _timerSrc->setTimeoutMS(LOAD_STATISTICS_INTERVAL);
371:
372: return true;
373: }
374:
375: //---------------------------------------------------------------------------
376: // Function: disableAdapter
377: //
378: // Disables the adapter & driver to the given level of support.
379:
380: bool WiFiController::disableAdapter() {
381: WLEnter();
382:
383: _timerSrc->cancelTimeout();
384: _transmitQueue->stop();
385:
386: // Report link status: valid and down.
387: //
388: setLinkStatus(kIONetworkLinkValid);
389:
390: // Flush all packets held in the queue and prevent it
391: // from accumulating any additional packets.
392: //
393: _transmitQueue->setCapacity(0);
394: _transmitQueue->flush();
395:
396: disableHardware();
397: // Close provider.
398: //
399: closeProvider();
400:
401: WLExit();
402: return true;
403: }
404:
405: //---------------------------------------------------------------------------
406: // Function: enable <IONetworkController>
407: //
408: // A request from our interface client to enable the adapter.
409:
410: IOReturn WiFiController::enable(IONetworkInterface * /*netif*/) {
411: if (_enabledForNetif) return kIOReturnSuccess;
412:
413: _enabledForNetif = enableAdapter();
414: WLLogInfo("Enabling Network: %d", _enabledForNetif);
415:
416: return (_enabledForNetif ? kIOReturnSuccess : kIOReturnIOError);
417: }
418:
419: //---------------------------------------------------------------------------
420: // Function: disable <IONetworkController>
421: //
422: // A request from our interface client to disable the adapter.
423:
424: IOReturn WiFiController::disable(IONetworkInterface * netif) {
425: WLEnter();
426:
427: _enabledForNetif = false;
428:
429: if (netif != _netif) {
430: WLLogErr("Wrong network interface!");
431: return kIOReturnInvalid;
432: }
433:
434: disableAdapter();
435:
436: WLExit();
437: return kIOReturnSuccess;
438: }
439:
440: IOReturn WiFiController::message(UInt32 type, IOService * provider, void * argument) {
441: if (type == kIOPCCardCSEventMessage) {
442: switch ((unsigned int)argument) {
443: case CS_EVENT_CARD_REMOVAL:
444: WLLogInfo("PC Card was removed.\n");
445:
446: _cardGone = true; //make sure nobody does something stupid
447: handleEjectionHardware();
448:
449: // Message our clients and tell them we're no longer available...
450: super::message(kIOMessageServiceIsTerminated, this, 0);
451: this->terminate(kIOServiceRequired); // we're gone, lets save memory.
452: _currentState = stateCardEjected;
453: break;
454: case CS_EVENT_CARD_INSERTION:
455: //TODO Handle this
456: break;
457: default:
458: WLLogWarn("PC Card generated untrapped message: %ud\n", (unsigned int)argument);
459: break;
460: }
461: }
462:
463: return super::message(type, provider, argument);
464: }
465:
466: //---------------------------------------------------------------------------
467: // Function: getPacketBufferConstraints <IONetworkController>
468: //
469: // Return our driver's packet alignment requirements.
470:
471: void WiFiController::getPacketBufferConstraints(IOPacketBufferConstraints * constraints) const {
472: constraints->alignStart = kIOPacketBufferAlign4; // even word aligned.
473: constraints->alignLength = kIOPacketBufferAlign4; // no restriction.
474: }
475:
476: //---------------------------------------------------------------------------
477: // Function: getHardwareAddress <IOEthernetController>
478: //
479: // Return the adapter's hardware/Ethernet address.
480:
481: IOReturn WiFiController::getHardwareAddress(IOEthernetAddress * addrs) {
482: bcopy(&_myAddress, addrs, sizeof(*addrs));
483: return kIOReturnSuccess;
484: }
485:
486: IOReturn WiFiController::setHardwareAddress(const void * addr, UInt32 addrBytes) {
487: IOReturn ret;
488: if (addrBytes != kIOEthernetAddressSize) return kIOReturnBadArgument;
489:
490: ret = setHardwareAddressHardware((UInt8*)addr);
491: if (ret == kIOReturnSuccess) {
492: bcopy(addr, &_myAddress, addrBytes);
493: }
494: return ret;
495: }
496:
497: #pragma mark -
498:
499: //---------------------------------------------------------------------------
500: // Function: createOutputQueue <IONetworkController>
501: //
502: // Allocate an IOGatedOutputQueue instance.
503:
504: IOOutputQueue * WiFiController::createOutputQueue(){
505: return IOGatedOutputQueue::withTarget(this, getWorkLoop());
506: }
507:
508: const OSString* WiFiController::newVendorString() const {
509: return OSString::withCString("binaervarianz");
510: }
511:
512: const OSString* WiFiController::newModelString() const {
513: return OSString::withCString("default controller");
514: }
515:
516: #pragma mark -
517:
518: //---------------------------------------------------------------------------
519: // Function: timeoutOccurred
520: //
521: // Periodic timer that monitors the receiver status, updates error
522: // and collision statistics, and update the current link status.
523:
524: void WiFiController::timeoutOccurred(OSObject * owner, IOTimerEventSource * /*timer*/) {
525: WiFiController *self = (WiFiController*) owner;
526: self->handleTimer();
527:
528: self->_timerSrc->setTimeoutMS(LOAD_STATISTICS_INTERVAL);
529: }
530:
531: void WiFiController::interruptOccurred(OSObject * owner, IOInterruptEventSource * src, int /*count*/) {
532: WiFiController *self = (WiFiController*) owner;
533:
534: self->handleInterrupt();
535: }
536:
537: #pragma mark -
538:
539: UInt32 WiFiController::outputPacket(mbuf_t m, void * param) {
540: IOReturn ret;
541:
542: if (!_enabledForNetif) { // drop the packet.
543: freePacket(m);
544: return kIOReturnOutputDropped;
545: }
546:
547: ret = outputPacketHardware(m);
548:
549: if (ret == kIOReturnOutputSuccess) _netStats->outputPackets++;
550: else if (ret == kIOReturnOutputDropped) {
551: _netStats->outputErrors++;
552: freePacket(m);
553: }
554:
555: return ret;
556: }
557:
558: #pragma mark -
559:
560: //---------------------------------------------------------------------------
561: // Function: _phyAddMediumType
562: //
563: // Purpose:
564: // Add a single medium object to the medium dictionary.
565: // Also add the medium object to an array for fast lookup.
566:
567: bool WiFiController::_addMediumType(UInt32 type, UInt32 speed, UInt32 code, char* name) {
568: IONetworkMedium * medium;
569: bool ret = false;
570:
571: medium = IONetworkMedium::medium(type, speed, 0, code, name);
572: if (medium) {
573: ret = IONetworkMedium::addMedium(_mediumDict, medium);
574: if (ret)
575: _mediumTable[code] = medium;
576: medium->release();
577: }
578: return ret;
579: }
580:
581: //---------------------------------------------------------------------------
582: // Function: _phyGetMediumWithCode
583: //
584: // Purpose:
585: // Returns the IONetworkMedium object associated with the given type.
586:
587: IONetworkMedium *WiFiController::_getMediumWithType(UInt32 type) {
588: if (type < MEDIUM_TYPE_INVALID)
589: return _mediumTable[type];
590: else
591: return 0;
592: }
593: //---------------------------------------------------------------------------
594: // Function: selectMedium <IONetworkController>
595: //
596: // Transition the controller/PHY to use a new medium. Note that
597: // this function can be called my the driver, or by our client.
598:
599: IOReturn WiFiController::selectMedium(const IONetworkMedium * medium) {
600: bool r;
601:
602: if ( OSDynamicCast(IONetworkMedium, medium) == 0 ) {
603: // Defaults to Auto.
604: medium = _getMediumWithType(MEDIUM_TYPE_AUTO);
605: if (medium == 0) return kIOReturnError;
606: }
607:
608: // Program PHY to select the desired medium.
609: //
610: r = setMediumHardware((mediumType_t) medium->getIndex());
611:
612: // Update the current medium property.
613: //
614: if (r && !setCurrentMedium(medium))
615: WLLogErr("setCurrentMedium error\n");
616:
617: return (r ? kIOReturnSuccess : kIOReturnIOError);
618: }
619:
620: //---------------------------------------------------------------------------
621: // Function: setMulticastMode <IOEthernetController>
622:
623: IOReturn WiFiController::setMulticastMode(bool active) {
624: return kIOReturnSuccess;
625: }
626:
627: //---------------------------------------------------------------------------
628: // Function: setMulticastList <IOEthernetController>
629:
630: IOReturn WiFiController::setMulticastList(IOEthernetAddress * addrs, UInt32 count) {
631: IOReturn ret = kIOReturnSuccess;
632:
633: return ret;
634: }
635:
636: #pragma mark -
637:
638: //abstracts; are to be defined in sub-classes
639: bool WiFiController::startProvider(IOService *provider) { return false; }
640: bool WiFiController::openProvider() { return false; }
641: bool WiFiController::closeProvider() { return false; }
642: bool WiFiController::freeProvider() { return false; }
643:
644: bool WiFiController::startHardware() { return false; }
645: bool WiFiController::initHardware() { return false; }
646: bool WiFiController::freeHardware() { return false; }
647: bool WiFiController::enableHardware() { return false; }
648: bool WiFiController::disableHardware() { return false; }
649: bool WiFiController::getReadyForSleep() { return false; }
650: bool WiFiController::handleEjectionHardware() { return false; }
651: bool WiFiController::setMediumHardware(mediumType_t medium) { return medium == MEDIUM_TYPE_AUTO; }
652:
653: bool WiFiController::handleInterrupt() { return false; }
654: bool WiFiController::handleTimer() { return false; }
655:
656: IOReturn WiFiController::outputPacketHardware(mbuf_t m) { return kIOReturnOutputDropped; }
657: IOReturn WiFiController::setHardwareAddressHardware(UInt8 *addr) { return kIOReturnUnsupported; }
658:
659: UInt32 WiFiController::getLinkSpeed() { return 0; }
660: UInt32 WiFiController::getFrequency() { return 0; };
661: bool WiFiController::setFrequency(UInt32 frequency) { return false; }
662: bool WiFiController::setMode(wirelessMode mode) { return false; }
663: bool WiFiController::setKey(UInt32 length, UInt8* key) { return false; }
664:
665: wirelessState WiFiController::getConnectionState() {
666: if (_currentState <= stateDisabled) return _currentState;
667: if (_enabledForNetif) return _currentState;
668: return stateDisabled;
669: }
670:
671: bool WiFiController::setSSID(UInt32 length, UInt8* ssid) {
672: length = length > 32 ? 32 : length;
673: memset(_ssid, 0, sizeof(_ssid));
674: memcpy(_ssid, ssid, length);
675: _ssidLength = length;
676:
677: WLLogDebug("Joining network with SSID <%s>, length: %d", _ssid, _ssidLength);
678: return false;
679: }
680:
681: bool WiFiController::getBSSNodesInRange(UInt32 *size, UInt8* data) {
682: *size = *size > _bssListCount * sizeof(bssItem) ? _bssListCount * sizeof(bssItem) : *size;
683: memcpy(data, _bssList, *size);
684: return true;
685: }
686: