Annotation of XNU/iokit/Families/IONetworking/IONetworkData.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved. 
                     24:  *
                     25:  * IONetworkData.cpp
                     26:  */
                     27: 
                     28: #include <libkern/c++/OSDictionary.h>
                     29: #include <libkern/c++/OSNumber.h>
                     30: #include <IOKit/assert.h>
                     31: #include <IOKit/IOLib.h>
                     32: #include <IOKit/network/IONetworkData.h>
                     33: 
                     34: #define super OSData
                     35: OSDefineMetaClassAndStructors( IONetworkData, OSData )
                     36: 
                     37: #define TAP_IS_VALID    (_tapTarget && _tapAction)
                     38: 
                     39: // All access method are serialized by a single global lock,
                     40: // shared among all IONetworkData instances.
                     41: //
                     42: static  IOLock * gIONDLock = 0;
                     43: #define LOCK     IOTakeLock(gIONDLock)
                     44: #define UNLOCK   IOUnlock(gIONDLock)
                     45: 
                     46: static const OSSymbol * gIONDDataKey;
                     47: static const OSSymbol * gIONDAccessKey;
                     48: static const OSSymbol * gIONDCapacityKey;
                     49: 
                     50: //---------------------------------------------------------------------------
                     51: // IONetworkData class initializer.
                     52: 
                     53: void IONetworkData::initialize()
                     54: {
                     55:     // Allocates the global data lock.
                     56:     //
                     57:     gIONDLock = IOLockAlloc();
                     58:     assert(gIONDLock);
                     59:     IOLockInitWithState(gIONDLock, kIOLockStateUnlocked);
                     60: 
                     61:     gIONDDataKey     = OSSymbol::withCStringNoCopy("Data"); 
                     62:     gIONDAccessKey   = OSSymbol::withCStringNoCopy("Access Flags");
                     63:     gIONDCapacityKey = OSSymbol::withCStringNoCopy("Capacity");
                     64: 
                     65:     assert(gIONDDataKey && gIONDAccessKey && gIONDCapacityKey);
                     66: }
                     67: 
                     68: //---------------------------------------------------------------------------
                     69: // Initialize an IONetworkData instance. A target/action may be
                     70: // registered to receive a notification when the read(), write(),
                     71: // reset(), or serialize() methods are called.
                     72: //
                     73: // name:        A name assigned to this object.
                     74: //
                     75: // buffer:      Pointer to an external data buffer. If 0,
                     76: //              then an internal buffer shall be allocated.
                     77: //
                     78: // capacity:    Capacity of the data buffer.
                     79: //
                     80: // accessFlags: Access flags.
                     81: //              Can be later modified by calling setAccessFlags().
                     82: //
                     83: // target:      Notification target. The target will be notified
                     84: //              when IONetworkData receives a call to one of its
                     85: //              access methods. If 0, then notification is disabled.
                     86: //
                     87: // action:      Notification action. If 0, then notification is
                     88: //              disabled.
                     89: //
                     90: // arg:         An argument to passed to the notification action.
                     91: //
                     92: // Returns true if initialized successfully, false otherwise.
                     93: 
                     94: bool
                     95: IONetworkData::initWithName(const char * name,
                     96:                             UInt32       inCapacity,
                     97:                             void *       buffer = 0,
                     98:                             UInt32       accessFlags = kIONDBasicAccessTypes,
                     99:                             OSObject *   target = 0,
                    100:                             Action       action = 0,
                    101:                             void *       arg    = 0)
                    102: {
                    103:     if ( ((buffer == 0) ?
                    104:            super::initWithCapacity(inCapacity) :
                    105:            super::initWithBytesNoCopy(buffer, inCapacity)) == false )
                    106:     {
                    107:         return false;
                    108:     }
                    109: 
                    110:     _access    = accessFlags;
                    111:     _tapTarget = target;
                    112:     _tapAction = action;
                    113:     _tapArg    = arg;
                    114:     _capacity  = inCapacity;
                    115:     length     = inCapacity;  // (ivar in OSData) force length to maximum
                    116: 
                    117:     // Generate a key for this object based on its assigned name.
                    118:     //
                    119:     if ((_key = OSSymbol::withCString(name)) == 0)
                    120:         return false;
                    121: 
                    122:     // Clear the data buffer.
                    123:     //
                    124:     clearBytes();
                    125: 
                    126:     return true;
                    127: }
                    128: 
                    129: //---------------------------------------------------------------------------
                    130: // Factory method that will construct and initialize an IONetworkData 
                    131: // instance.
                    132: //
                    133: // Returns an IONetworkData instance on success, or 0 otherwise.
                    134: 
                    135: IONetworkData *
                    136: IONetworkData::withName(const char * name,
                    137:                         UInt32       inCapacity,
                    138:                         void *       buffer = 0,
                    139:                         UInt32       accessFlags = kIONDBasicAccessTypes,
                    140:                         OSObject *   target = 0,
                    141:                         Action       action = 0,
                    142:                         void *       arg    = 0)
                    143: {
                    144:     IONetworkData * aData = new IONetworkData;
                    145:     
                    146:     if (aData && !aData->initWithName(name, inCapacity, buffer, accessFlags,
                    147:                                       target, action, arg))
                    148:     {
                    149:         aData->release();
                    150:         aData = 0;
                    151:     }
                    152:     return aData;
                    153: }
                    154: 
                    155: //---------------------------------------------------------------------------
                    156: // Free the IONetworkData instance.
                    157: 
                    158: void IONetworkData::free()
                    159: {
                    160:     if (_key)
                    161:         _key->release();
                    162: 
                    163:     // Superclass will free the internal data buffer.
                    164: 
                    165:     super::free();
                    166: }
                    167: 
                    168: //---------------------------------------------------------------------------
                    169: // Change the access flags.
                    170: //
                    171: // accessFlags: A bitfield of access flag bits.
                    172: //              See IONDAccessFlags enum.
                    173: 
                    174: void IONetworkData::setAccessFlags(UInt32 accessFlags)
                    175: {
                    176:     LOCK;
                    177:     _access = (_access & kIONDImmutableAccessFlags) |
                    178:               (accessFlags & ~kIONDImmutableAccessFlags);
                    179:     UNLOCK;
                    180: }
                    181: 
                    182: //---------------------------------------------------------------------------
                    183: // Register a target/action to handle access notification.
                    184: // A notification is sent by an IONetworkData to the registered
                    185: // notification handler when an access method is called.
                    186: //
                    187: // target: The target object that implements the notification action.
                    188: //         If 0, then notification will be disabled.
                    189: //
                    190: // action: The notification action. If 0, then notification will be disabled.
                    191: //
                    192: // arg:    An optional argument passed to the notification handler.
                    193: 
                    194: void IONetworkData::setNotificationTarget(OSObject *  target,
                    195:                                           Action      action,
                    196:                                           void *      arg = 0)
                    197: {
                    198:     LOCK;
                    199:     _tapTarget = target;
                    200:     _tapAction = action;
                    201:     _tapArg    = arg;
                    202:     UNLOCK;
                    203: }
                    204: 
                    205: //---------------------------------------------------------------------------
                    206: // Return a pointer to the data buffer.
                    207: 
                    208: const void * IONetworkData::getBuffer() const
                    209: {
                    210:     return getBytesNoCopy();
                    211: }
                    212: 
                    213: //---------------------------------------------------------------------------
                    214: // Return the access flags.
                    215: 
                    216: UInt32 IONetworkData::getAccessFlags() const
                    217: {
                    218:     return _access;
                    219: }
                    220: 
                    221: //---------------------------------------------------------------------------
                    222: // Return the notification target.
                    223: 
                    224: OSObject * IONetworkData::getTarget() const
                    225: {
                    226:     return _tapTarget;
                    227: }
                    228: 
                    229: //---------------------------------------------------------------------------
                    230: // Return the notification action.
                    231: 
                    232: IONetworkData::Action IONetworkData::getAction() const
                    233: {
                    234:     return _tapAction;
                    235: }
                    236: 
                    237: //---------------------------------------------------------------------------
                    238: // Return the notification argument.
                    239: 
                    240: void * IONetworkData::getArgument() const
                    241: {
                    242:     return _tapArg;
                    243: }
                    244: 
                    245: //---------------------------------------------------------------------------
                    246: // Get an OSSymbol key associated with this IONetworkData instance.
                    247: // During initialization, IONetworkData will create an OSSymbol
                    248: // key based on its assigned name.
                    249: //
                    250: // Return an OSSymbol key generated from the assigned name.
                    251: 
                    252: const OSSymbol * IONetworkData::getKey() const
                    253: {
                    254:     return _key;
                    255: }
                    256: 
                    257: //---------------------------------------------------------------------------
                    258: // Override the getCapacity() method inherited from OSData.
                    259: // This method overrides the implementation in OSData in
                    260: // order to report the capacity for both internal or external
                    261: // data buffers.
                    262: //
                    263: // Return the capacity of the data buffer in bytes.
                    264: 
                    265: UInt IONetworkData::getCapacity() const
                    266: {
                    267:     return _capacity;
                    268: }
                    269: 
                    270: //---------------------------------------------------------------------------
                    271: // Update the data buffer from a source buffer provided by the
                    272: // caller.
                    273: //
                    274: // bytes:    Pointer to a source buffer provided by the caller.
                    275: //
                    276: // inLength: Length of the source buffer, or the amount of data
                    277: //           to copy to the data buffer. The length provided must
                    278: //           be smaller than or equal to the capacity of the object.
                    279: //
                    280: // Returns true if the length of the source buffer is within limits, and
                    281: // the source buffer was copied, false otherwise.
                    282: 
                    283: bool IONetworkData::setBytes(const void * bytes, UInt inLength)
                    284: {
                    285:     if (inLength > _capacity)
                    286:         return false;       // specified buffer is too large.
                    287: 
                    288:     if (inLength == 0)
                    289:         return true;
                    290: 
                    291:     bcopy(bytes, data, inLength);
                    292: 
                    293:     length = inLength;      // set the new data length.
                    294: 
                    295:     return true;
                    296: }
                    297: 
                    298: //---------------------------------------------------------------------------
                    299: // Set a new data buffer length to indicate the amount of
                    300: // valid data in the data buffer.
                    301: //
                    302: // inLength: Length of the data buffer in bytes. The length provided must
                    303: //           be smaller than or equal to the capacity of the data object.
                    304: //
                    305: // Returns true if the length provided was accepted.
                    306: 
                    307: bool IONetworkData::setLength(UInt inLength)
                    308: {
                    309:     if (inLength > _capacity)
                    310:         return false;       // Length cannot exceed capacity.
                    311: 
                    312:     length = inLength;
                    313: 
                    314:     return true;
                    315: }
                    316: 
                    317: //---------------------------------------------------------------------------
                    318: // Copy the data buffer (with length bytes) to a destination buffer
                    319: // provided by the caller.
                    320: //
                    321: // bytes:       Pointer to a destination buffer.
                    322: //
                    323: // inOutLength: The caller must initialize the integer value pointed
                    324: //              by inOutLength with the size of the destination buffer
                    325: //              before the call. This method will overwrite it with the
                    326: //              number of bytes copied.
                    327: //
                    328: // Returns true if the destination buffer is larger than or equal to the
                    329: // length of the data buffer, false otherwise.
                    330: 
                    331: bool IONetworkData::copyBytes(void * bytes, UInt * inOutLength) const
                    332: {
                    333:     if (length > *inOutLength)
                    334:         return false;       // specified buffer is too small.
                    335:     
                    336:     *inOutLength = length;  // return the number of bytes copied.
                    337: 
                    338:     if (length)
                    339:         bcopy(data, bytes, length);
                    340: 
                    341:     return true;
                    342: }
                    343: 
                    344: //---------------------------------------------------------------------------
                    345: // Clear the entire data buffer and fill it with zeroes.
                    346: //
                    347: // Return true if the buffer was cleared, false otherwise.
                    348: 
                    349: bool IONetworkData::clearBytes()
                    350: {
                    351:     if (_capacity)
                    352:         bzero(data, _capacity);
                    353: 
                    354:     return true;
                    355: }
                    356: 
                    357: //---------------------------------------------------------------------------
                    358: // Handle a user space request to reset the data buffer. If notication
                    359: // is enabled, then the notification handler is called after the data
                    360: // buffer has been cleared
                    361: //
                    362: // Returns kIOReturnNotWritable if reset access is not allowed,
                    363: // kIOReturnSuccess otherwise. If a notification handler is called,
                    364: // and it returns an error code, then that error is returned.
                    365: 
                    366: IOReturn IONetworkData::reset()
                    367: {
                    368:     IOReturn ret = kIOReturnUnsupported;
                    369: 
                    370:     LOCK;
                    371: 
                    372:     do {
                    373:         // Check access.
                    374:         //
                    375:         if ((_access & kIONDAccessTypeReset) == 0)
                    376:         {
                    377:             ret = kIOReturnNotWritable;
                    378:             break;
                    379:         }
                    380: 
                    381:         // Default action is to bzero the entire buffer.
                    382:         //
                    383:         if ((_access & kIONDAccessNoBufferAccess) == 0)
                    384:         {
                    385:             clearBytes();
                    386:             ret = kIOReturnSuccess;
                    387:         }
                    388: 
                    389:         // Notify our target.
                    390:         //
                    391:         if (TAP_IS_VALID)
                    392:         {
                    393:             ret = (_tapTarget->*_tapAction)(this,
                    394:                                             (UInt32) kIONDAccessTypeReset,
                    395:                                             _tapArg, 0, 0);
                    396:         }
                    397:     }
                    398:     while (0);
                    399: 
                    400:     UNLOCK;
                    401: 
                    402:     return ret;
                    403: }
                    404: 
                    405: //---------------------------------------------------------------------------
                    406: // Handle a user space request to read from the data buffer and copy it
                    407: // to the destination buffer provided. If notification is enabled,
                    408: // then the notification handler is called before the data buffer
                    409: // is copied to the destination buffer. The notification handler may
                    410: // use this opportunity to update the contents of the data buffer.
                    411: //
                    412: // inBuffer:  Pointer to the destination buffer.
                    413: //
                    414: // inOutSize: Pointer to an integer containing the size of the destination
                    415: //            buffer before the call. Overwritten by this method to the
                    416: //            actual number of bytes copied to the destination buffer.
                    417: //
                    418: // Returns kIOReturnSuccess if success,
                    419: // kIOReturnBadArgument if an argument provided is invalid,
                    420: // kIOReturnNoSpace if the destination buffer is too small,
                    421: // kIOReturnNotReadable if read access is not permitted,
                    422: // or an error from the notification handler.
                    423: 
                    424: IOReturn IONetworkData::read(void * inBuffer, UInt * inOutSize)
                    425: {
                    426:     IOReturn ret = kIOReturnUnsupported;
                    427: 
                    428:     LOCK;
                    429: 
                    430:     do {
                    431:         // Check the arguments.
                    432:         //
                    433:         if (!inBuffer || !inOutSize)
                    434:         {
                    435:             ret = kIOReturnBadArgument;
                    436:             break;
                    437:         }
                    438: 
                    439:         // Check access.
                    440:         //
                    441:         if ((_access & kIONDAccessTypeRead) == 0)
                    442:         {
                    443:             ret = kIOReturnNotReadable;
                    444:             break;
                    445:         }
                    446: 
                    447:         // Notify the target before the read operation.
                    448:         // The target can take this opportunity to update the
                    449:         // data buffer. If the target returns an error,
                    450:         // abort and return the error.
                    451:         //
                    452:         if (TAP_IS_VALID)
                    453:         {
                    454:             ret = (_tapTarget->*_tapAction)(this,
                    455:                                             (UInt32) kIONDAccessTypeRead,
                    456:                                             _tapArg,
                    457:                                             inBuffer,
                    458:                                             (UInt32 *) inOutSize);
                    459:             if (ret != kIOReturnSuccess)
                    460:                 break;
                    461:         }
                    462: 
                    463:         if ((_access & kIONDAccessNoBufferAccess) == 0)
                    464:         {
                    465:             ret = (copyBytes(inBuffer, inOutSize) ?
                    466:                   kIOReturnSuccess : kIOReturnNoSpace);
                    467:         }
                    468:     }
                    469:     while (0);
                    470: 
                    471:     UNLOCK;
                    472: 
                    473:     return ret;
                    474: }
                    475: 
                    476: //---------------------------------------------------------------------------
                    477: // Handle a request to write to the data buffer from a source buffer provided.
                    478: // If notification is enabled, then the notification handler is called after 
                    479: // the source buffer has been copied to the data buffer.
                    480: //
                    481: // inBuffer: Pointer to the source buffer.
                    482: //
                    483: // size:     Size of the source buffer in bytes.
                    484: //
                    485: // Returns kIOReturnSuccess on success,
                    486: // kIOReturnBadArgument if an argument provided is invalid,
                    487: // kIOReturnNoSpace if the source buffer is too big,
                    488: // kIOReturnNotWritable if write access is not permitted,
                    489: // or an error from the notification handler.
                    490: 
                    491: IOReturn IONetworkData::write(void * inBuffer, UInt size)
                    492: {
                    493:     IOReturn ret = kIOReturnUnsupported;
                    494: 
                    495:     LOCK;
                    496: 
                    497:     do {
                    498:         // Check the arguments.
                    499:         //
                    500:         if (!inBuffer)
                    501:         {
                    502:             ret = kIOReturnBadArgument;
                    503:             break;
                    504:         }
                    505: 
                    506:         // Check access.
                    507:         //
                    508:         if ((_access & kIONDAccessTypeWrite) == 0)
                    509:         {
                    510:             ret = kIOReturnNotWritable;
                    511:             break;
                    512:         }
                    513: 
                    514:         // Update the data buffer.
                    515:         //
                    516:         if ((_access & kIONDAccessNoBufferAccess) == 0)
                    517:         {
                    518:             ret = (setBytes(inBuffer, size)) ?
                    519:                   kIOReturnSuccess : kIOReturnNoSpace;
                    520: 
                    521:             if (ret != kIOReturnSuccess)
                    522:                 break;
                    523:         }
                    524: 
                    525:         // Notify the target after a successful write operation.
                    526:         //
                    527:         if (TAP_IS_VALID)
                    528:         {
                    529:             ret = (_tapTarget->*_tapAction)(this,
                    530:                                             (UInt32) kIONDAccessTypeWrite,
                    531:                                             _tapArg,
                    532:                                             inBuffer,
                    533:                                             (UInt32 *) &size);
                    534:         }
                    535:     }
                    536:     while (0);
                    537: 
                    538:     UNLOCK;
                    539: 
                    540:     return ret;
                    541: }
                    542: 
                    543: //---------------------------------------------------------------------------
                    544: // Serialize the IONetworkData object. If notification is enabled,
                    545: // then the notification handler is called before the data buffer is 
                    546: // serialized.
                    547: //
                    548: // s: An OSSerialize object.
                    549: 
                    550: bool IONetworkData::serialize(OSSerialize * s) const
                    551: {
                    552:     bool           ok;
                    553:     OSDictionary * dictToSerialize;
                    554:     OSData *       dataEntry;
                    555:     OSNumber *     numberEntry;
                    556: 
                    557:     dictToSerialize = OSDictionary::withCapacity(3);
                    558:     if (!dictToSerialize)
                    559:         return false;
                    560: 
                    561:     dataEntry = OSData::withBytesNoCopy((void *) &_access, sizeof(_access));
                    562:     if (dataEntry) {
                    563:         dictToSerialize->setObject(gIONDAccessKey, dataEntry);
                    564:         dataEntry->release();
                    565:     }
                    566: 
                    567:     numberEntry = OSNumber::withNumber(_capacity, sizeof(_capacity) * 8);
                    568:     if (numberEntry) {
                    569:         dictToSerialize->setObject(gIONDCapacityKey, numberEntry);
                    570:         numberEntry->release();
                    571:     }
                    572: 
                    573:     LOCK;
                    574: 
                    575:     do {
                    576:         // Check access.
                    577:         //
                    578:         if ((_access & kIONDAccessTypeSerialize) == 0)
                    579:             break;
                    580: 
                    581:         if (_access & kIONDAccessNoBufferAccess)
                    582:             break;
                    583: 
                    584:         // Notify the target before the read operation.
                    585:         // The target can take this opportunity to update the
                    586:         // data buffer. If the target returns an error,
                    587:         // then the data buffer is not serialized.
                    588:         //
                    589:         if (TAP_IS_VALID &&
                    590:             ((_tapTarget->*_tapAction)((IONetworkData *) this,
                    591:                                        kIONDAccessTypeSerialize,
                    592:                                        _tapArg, 0, 0) != kIOReturnSuccess))
                    593:         {
                    594:             break;
                    595:         }
                    596: 
                    597:         dataEntry = OSData::withBytesNoCopy(data, length);
                    598:         if (dataEntry) {
                    599:             dictToSerialize->setObject(gIONDDataKey, dataEntry);
                    600:             dataEntry->release();
                    601:         }
                    602:     }
                    603:     while (0);
                    604: 
                    605:     ok = dictToSerialize->serialize(s);
                    606:     dictToSerialize->release();
                    607: 
                    608:     UNLOCK;
                    609: 
                    610:     return ok;
                    611: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.