1: /*
     2:         
     3:         File:			WiFiUserClient.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 "WiFiUserClient.h" 
    27: #include <IOKit/IOMessage.h> 
    28: 
    29: #define super IOUserClient 
    30: OSDefineMetaClassAndStructors(WiFiUserClient, IOUserClient);
    31: 
    32: IODataQueue* WiFiUserClient::_packetQueue = NULL;
    33: 
    34: bool WiFiUserClient::start(IOService* provider) {
    35:     WLEnter();
    36:     
    37:     if (!super::start(provider)) {
    38:         WLLogErr("super::start() failed");
    39:         return false;
    40:     }
    41: 
    42:     _provider = OSDynamicCast(WiFiController, provider);
    43:     if (!_provider) {
    44:         WLLogErr("_provider failed");
    45:         return false;
    46:     }
    47: 
    48:     _userCommandGate = IOCommandGate::commandGate(this);
    49:     if (!_userCommandGate) {
    50:         WLLogErr("Couldn't get CommandGate");
    51:         return false;
    52:     }
    53: 
    54:     IOWorkLoop* wl = _provider->getWorkLoop();
    55:     if (wl->addEventSource(_userCommandGate) != kIOReturnSuccess) {
    56:         WLLogErr("Couldn't add gate to workloop");
    57:         return false;
    58:     }
    59:     _packetQueue = _provider->getPacketQueue();
    60:     if (!_packetQueue) {
    61:         WLLogCrit("Could not obtain packetQueue");
    62:         return false;
    63:     }
    64:     return true;
    65: }
    66: 
    67: void WiFiUserClient::stop(IOService* provider) {
    68:     WLEnter();
    69: }
    70: 
    71: bool WiFiUserClient::initWithTask(task_t owningTask, void* securityToken, UInt32 type) {
    72:     WLEnter();
    73:     
    74:     if (!super::initWithTask(owningTask, securityToken, type))
    75:         return false;
    76: 
    77:     if (!owningTask)
    78: 	return false;
    79: 
    80:     _owningTask = owningTask;
    81:     _securityToken = securityToken;
    82:     _securityType = type;
    83:     _provider = NULL;
    84: 
    85:     return true;
    86: }
    87: 
    88: IOReturn WiFiUserClient::clientClose(void) {
    89:     WLEnter();
    90:     
    91:     close();
    92:     terminate();
    93: 
    94:     if (_owningTask)
    95:         _owningTask = NULL;
    96: 
    97:     _provider = NULL;
    98: 
    99:     return kIOReturnSuccess;
   100: }
   101: 
   102: IOReturn WiFiUserClient::clientDied(void) {
   103:     WLEnter();
   104: 
   105:     return super::clientDied();
   106: }
   107: 
   108: IOReturn WiFiUserClient::message(UInt32 type, IOService * provider, void * argument) {
   109:     if (type == kIOMessageServiceIsTerminated) {
   110:         WLLogInfo("Provider did terminate!");
   111:         close();
   112:         terminate();
   113:     }
   114:     return  super::message(type, provider, argument);
   115: }
   116: 
   117: IOExternalMethod* WiFiUserClient::
   118: getTargetAndMethodForIndex(IOService** target, UInt32 index) {
   119:     static const IOExternalMethod sMethods[kWiFiUserClientLastMethod] = {
   120:         {   // kWiFiUserClientOpen
   121:             NULL,
   122:             (IOMethod)&WiFiUserClient::open,
   123:             kIOUCScalarIScalarO,
   124:             0,
   125:             0
   126:         },
   127:         {   // kWiFiUserClientClose
   128:             NULL,
   129:             (IOMethod)&WiFiUserClient::close,
   130:             kIOUCScalarIScalarO,
   131:             0,
   132:             0
   133:         },
   134:         {
   135:             // kWiFiUserClientGetLinkSpeed
   136:             NULL,
   137:             (IOMethod)&WiFiUserClient::_getLinkSpeed,
   138:             kIOUCScalarIScalarO,
   139:             0,
   140:             0
   141:         },
   142:         {
   143:             // kWiFiUserClientGetConnectionState
   144:             NULL,
   145:             (IOMethod)&WiFiUserClient::_getConnectionState,
   146:             kIOUCScalarIScalarO,
   147:             0,
   148:             0
   149:         },
   150:         {
   151:             // kWiFiUserClientGetFrequency
   152:             NULL,
   153:             (IOMethod)&WiFiUserClient::_getFrequency,
   154:             kIOUCScalarIScalarO,
   155:             0,
   156:             0
   157:         },
   158:         {
   159:             // kWiFiUserClientSetFrequency
   160:             NULL,
   161:             (IOMethod)&WiFiUserClient::_setFrequency,
   162:             kIOUCScalarIScalarO,
   163:             1,
   164:             0
   165:         },
   166:         {
   167:             // kWiFiUserClientSetSSID
   168:             NULL,
   169:             (IOMethod)&WiFiUserClient::_setSSID,
   170:             kIOUCScalarIStructI,
   171:             0,
   172:             0xFFFFFFFF
   173:         },
   174:         {
   175:             // kWiFiUserClientSetWEPKey
   176:             NULL,
   177:             (IOMethod)&WiFiUserClient::_setWEPKey,
   178:             kIOUCScalarIStructI,
   179:             0,
   180:             0xFFFFFFFF
   181:         },
   182:         {
   183:             // kWiFiUserClientGetScan
   184:             NULL,
   185:             (IOMethod)&WiFiUserClient::_getScan,
   186:             kIOUCScalarIStructO,
   187:             0,
   188:             0xFFFFFFFF
   189:         },
   190:         {
   191:             // kWiFiUserClientSetMode
   192:             NULL,
   193:             (IOMethod)&WiFiUserClient::_setMode,
   194:             kIOUCScalarIScalarO,
   195:             1,
   196:             0
   197:         },
   198:     };
   199: 
   200:     if (index < (UInt32)kWiFiUserClientLastMethod) {
   201:         *target = this;
   202:         return (IOExternalMethod*)&sMethods[index];
   203:     }
   204: 
   205:     return NULL;
   206: }
   207: 
   208: /*********************************************************************
   209:  *
   210:  *********************************************************************/
   211: 
   212: IOReturn WiFiUserClient::open(void) {
   213:     WLEnter();
   214:     
   215:     if (isInactive())
   216:         return kIOReturnNotAttached;
   217: 
   218:     if (!_provider->open(this))
   219:         return kIOReturnExclusiveAccess;
   220: 
   221:     return kIOReturnSuccess;
   222: }
   223: 
   224: IOReturn WiFiUserClient::close(void) {
   225:     WLEnter();
   226: 
   227:     if (!_provider)
   228:         return kIOReturnNotAttached;
   229: 
   230:     if (_provider->isOpen(this)) {
   231:         _provider->close(this);
   232:     }
   233: 
   234:     return kIOReturnSuccess;
   235: }
   236: 
   237: #pragma mark - 
   238: 
   239: IOReturn WiFiUserClient::
   240: clientMemoryForType(UInt32 type, IOOptionBits* optionBits,
   241:                     IOMemoryDescriptor** memoryDescriptor) {
   242:     if (type == kWiFiUserClientMap) {
   243:         /* Set memoryDescriptor to DataQueue memory descriptor */
   244:         
   245:         if (!_packetQueue) {
   246:             WLLogCrit("NO PACKET QUEUE!");
   247:             return kIOReturnInternalError;
   248:         }
   249:         
   250:         *memoryDescriptor = _packetQueue->getMemoryDescriptor();
   251:         return (*memoryDescriptor != NULL) ? kIOReturnSuccess : kIOReturnInternalError;
   252:     }
   253:     else {
   254:         WLLogCrit("bad type");
   255:         return kIOReturnError;
   256:     }
   257: }
   258: 
   259: IOReturn WiFiUserClient::
   260: registerNotificationPort(mach_port_t notificationPort,
   261:                          UInt32 type, UInt32 refCon) {
   262:     if (type == kWiFiUserClientNotify) {
   263:         /* Set data queue's notification port */
   264:         if (!_packetQueue) {
   265:             WLLogCrit("NO PACKET QUEUE!");
   266:             return kIOReturnInternalError;
   267:         }
   268:         
   269:         _packetQueue->setNotificationPort(notificationPort);
   270:         return kIOReturnSuccess;
   271:     }
   272:     else {
   273:         WLLogCrit("bad type");
   274:         return kIOReturnError;
   275:     }
   276: }
   277: 
   278: #pragma mark - 
   279: 
   280: UInt32 WiFiUserClient::_getLinkSpeed() {
   281:     return _provider->getLinkSpeed();
   282: }
   283: 
   284: UInt32 WiFiUserClient::_getConnectionState() {
   285:     return _provider->getConnectionState();
   286: }
   287: 
   288: UInt32 WiFiUserClient::_getFrequency() {
   289:     return _provider->getFrequency() / 1000;
   290: }
   291: 
   292: IOReturn WiFiUserClient::_setSSID(const char *buffer, UInt32 size) {
   293:     return (_provider->setSSID(size, (UInt8*)buffer) ? kIOReturnSuccess : kIOReturnError);
   294: }
   295: 
   296: IOReturn WiFiUserClient::_setWEPKey(const char *buffer, UInt32 size) {
   297:     return (_provider->setKey(size, (UInt8*)buffer) ? kIOReturnSuccess : kIOReturnError);
   298: }
   299: 
   300: IOReturn WiFiUserClient::_getScan(const char *buffer, UInt32 size) {
   301:     UInt32 *s;
   302:     s = (UInt32*)buffer;
   303:     *s = size - 4;
   304:     return (_provider->getBSSNodesInRange(s, ((UInt8*)buffer) + 4) ? kIOReturnSuccess : kIOReturnError);
   305: }
   306: 
   307: IOReturn WiFiUserClient::_setFrequency(UInt32 frequency) {
   308:     return _provider->setFrequency(frequency * 1000);
   309: }
   310: 
   311: IOReturn WiFiUserClient::_setMode(UInt32 mode) {
   312:     return _provider->setMode((wirelessMode)mode);
   313: }
   314: 
   315: