1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1998-2003 Apple Computer, Inc. All Rights Reserved. 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include <machine/limits.h> /* UINT_MAX */ 26#include <libkern/OSByteOrder.h> 27 28#include <IOKit/network/IOEthernetController.h> 29#include <IOKit/network/IOEthernetInterface.h> 30#include <IOKit/network/IOGatedOutputQueue.h> 31 32#include <IOKit/IOTimerEventSource.h> 33#include <IOKit/assert.h> 34#include <IOKit/IOLib.h> 35#include <IOKit/IOService.h> 36#include <IOKit/IOBufferMemoryDescriptor.h> 37#include <IOKit/IOMessage.h> 38 39#include <IOKit/pwr_mgt/RootDomain.h> 40 41#if !TARGET_OS_IPHONE 42#include <IOKit/usb/IOUSBBus.h> 43#endif /* TARGET_OS_IPHONE */ 44 45#include <IOKit/usb/IOUSBNub.h> 46#include <IOKit/usb/IOUSBDevice.h> 47#include <IOKit/usb/IOUSBPipe.h> 48#include <IOKit/usb/USB.h> 49#include <IOKit/usb/IOUSBInterface.h> 50 51#include <UserNotification/KUNCUserNotifications.h> 52 53extern "C" 54{ 55 #include <sys/param.h> 56 #include <sys/mbuf.h> 57} 58 59#define DEBUG_NAME "AppleUSBCDCEEM" 60 61#include "AppleUSBCDCEEM.h" 62 63#define MIN_BAUD (50 << 1) 64 65static struct MediumTable 66{ 67 UInt32 type; 68 UInt32 speed; 69} 70 71mediumTable[] = 72{ 73 {kIOMediumEthernetNone, 0}, 74 {kIOMediumEthernetAuto, 0}, 75 {kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, 10}, 76 {kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, 10}, 77 {kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, 100}, 78 {kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, 100} 79}; 80 81#define super IOEthernetController 82 83OSDefineMetaClassAndStructors(AppleUSBCDCEEM, IOEthernetController); 84 85/****************************************************************************************************/ 86// 87// Function: findCDCDriverEED 88// 89// Inputs: myDevice - Address of the controlling device 90// dataAddr - my address 91// dataInterfaceNum - the data interface number 92// 93// Outputs: 94// 95// Desc: Finds the initiating CDC driver and confirm the interface number 96// 97/****************************************************************************************************/ 98 99IOReturn findCDCDriverEED(IOUSBDevice *myDevice, void *dataAddr, UInt8 dataInterfaceNum) 100{ 101 AppleUSBCDCEEM *me = (AppleUSBCDCEEM *)dataAddr; 102 AppleUSBCDC *CDCDriver = NULL; 103 bool driverOK = false; 104 OSIterator *iterator = NULL; 105 OSDictionary *matchingDictionary = NULL; 106 107 XTRACE(me, 0, 0, "findCDCDriverEED"); 108 109 // Get matching dictionary 110 111 matchingDictionary = IOService::serviceMatching("AppleUSBCDC"); 112 if (!matchingDictionary) 113 { 114 XTRACE(me, 0, 0, "findCDCDriverEED - Couldn't create a matching dictionary"); 115 return kIOReturnError; 116 } 117 118 // Get an iterator 119 120 iterator = IOService::getMatchingServices(matchingDictionary); 121 if (!iterator) 122 { 123 XTRACE(me, 0, 0, "findCDCDriverEED - No AppleUSBCDC driver found!"); 124 matchingDictionary->release(); 125 return kIOReturnError; 126 } 127 128#if 0 129 // Use iterator to find driver (there's only one so we won't bother to iterate) 130 131 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 132 if (CDCDriver) 133 { 134 driverOK = CDCDriver->confirmDriver(kUSBEthernetEmulationModel, dataInterfaceNum); 135 } 136#endif 137 138 // Iterate until we find our matching CDC driver 139 140 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 141 while (CDCDriver) 142 { 143 XTRACE(me, 0, 0, "findCDCDriverEED - CDC driver candidate"); 144 145 if (me->fDataInterface->GetDevice() == CDCDriver->getCDCDevice()) 146 { 147 XTRACE(me, 0, 0, "findCDCDriverEED - Found our CDC driver"); 148 driverOK = CDCDriver->confirmDriver(kUSBEthernetEmulationModel, dataInterfaceNum); 149 break; 150 } 151 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 152 } 153 154 matchingDictionary->release(); 155 iterator->release(); 156 157 if (!CDCDriver) 158 { 159 XTRACE(me, 0, 0, "findCDCDriverEED - CDC driver not found"); 160 return kIOReturnError; 161 } 162 163 if (!driverOK) 164 { 165 XTRACE(me, kUSBEthernetEmulationModel, dataInterfaceNum, "findCDCDriverEED - Not my interface"); 166 return kIOReturnError; 167 } 168 169 me->fConfigAttributes = CDCDriver->fbmAttributes; 170 171 return kIOReturnSuccess; 172 173}/* end findCDCDriverEED */ 174 175#if LOG_DATA 176#define dumplen 32 // Set this to the number of bytes to dump and the rest should work out correct 177 178#define buflen ((dumplen*2)+dumplen)+3 179#define Asciistart (dumplen*2)+3 180 181/****************************************************************************************************/ 182// 183// Function: AppleUSBCDCEEM::USBLogData 184// 185// Inputs: Dir - direction 186// Count - number of bytes 187// buf - the data 188// 189// Outputs: 190// 191// Desc: Puts the data in the log. 192// 193/****************************************************************************************************/ 194 195void AppleUSBCDCEEM::USBLogData(UInt8 Dir, SInt32 Count, char *buf) 196{ 197 SInt32 wlen; 198 UInt8 tDir = Dir; 199 SInt32 llen, rlen; 200 SInt16 i, Aspnt, Hxpnt; 201 UInt8 wchr; 202 char LocBuf[buflen+1]; 203 204 switch (tDir) 205 { 206 case kDataIn: 207 Log("AppleUSBCDCEEM: USBLogData - Read Complete, address = %8p, size = %8d\n", (void *)buf, (UInt)Count); 208 break; 209 case kDataOut: 210 Log("AppleUSBCDCEEM: USBLogData - Write, address = %8p, size = %8d\n", (void *)buf, (UInt)Count); 211 break; 212 case kDataOther: 213 Log("AppleUSBCDCEEM: USBLogData - Other, address = %8p, size = %8d\n", (void *)buf, (UInt)Count); 214 break; 215 case kDataNone: 216 tDir = kDataOther; 217 break; 218 } 219 220#if DUMPALL 221 wlen = Count; 222#else 223 if (Count > dumplen) 224 { 225 wlen = dumplen; 226 } else { 227 wlen = Count; 228 } 229#endif 230 231 if (wlen == 0) 232 { 233 Log("AppleUSBCDCEEM: USBLogData - No data, Count=0\n"); 234 return; 235 } 236 237 rlen = 0; 238 do 239 { 240 memset(LocBuf, 0x20, buflen); 241 242 if (wlen > dumplen) 243 { 244 llen = dumplen; 245 wlen -= dumplen; 246 } else { 247 llen = wlen; 248 wlen = 0; 249 } 250 Aspnt = Asciistart; 251 Hxpnt = 0; 252 for (i=1; i<=llen; i++) 253 { 254 wchr = buf[i-1]; 255 LocBuf[Hxpnt++] = Asciify(wchr >> 4); 256 LocBuf[Hxpnt++] = Asciify(wchr); 257 if ((wchr < 0x20) || (wchr > 0x7F)) // Non printable characters 258 { 259 LocBuf[Aspnt++] = 0x2E; // Replace with a period 260 } else { 261 LocBuf[Aspnt++] = wchr; 262 } 263 } 264 LocBuf[Aspnt] = 0x00; 265 266 Log("%s\n", LocBuf); 267#if USE_IOL 268 IOSleep(Sleep_Time); // Try and keep the log from overflowing 269#endif 270 271 rlen += llen; 272 buf = &buf[rlen]; 273 } while (wlen != 0); 274 275}/* end USBLogData */ 276 277/****************************************************************************************************/ 278// 279// Function: AppleUSBCDCEEM::dumpData 280// 281// Inputs: buf - the data 282// size - number of bytes 283// 284// Outputs: None 285// 286// Desc: Creates formatted data for the log (cannot be used at interrupt time) 287// 288/****************************************************************************************************/ 289 290void AppleUSBCDCEEM::dumpData(char *buf, SInt32 size) 291{ 292 SInt32 curr, len, dlen; 293 294 Log("AppleUSBCDCEEM: dumpData - Address = %8p, size = %8d\n", (void *)buf, (UInt)size); 295 296 dlen = 0; 297 len = size; 298 299 for (curr=0; curr<size; curr+=dumplen) 300 { 301 if (len > dumplen) 302 { 303 dlen = dumplen; 304 } else { 305 dlen = len; 306 } 307 Log("%8p ", (void *)&buf[curr]); 308 USBLogData(kDataNone, dlen, &buf[curr]); 309 len -= dlen; 310 } 311 312}/* end dumpData */ 313#endif 314 315/****************************************************************************************************/ 316// 317// Method: AppleUSBCDCEEM::dataReadComplete 318// 319// Inputs: obj - me 320// param - pool index 321// rc - return code 322// remaining - what's left 323// 324// Outputs: 325// 326// Desc: BulkIn pipe (Data interface) read completion routine 327// 328/****************************************************************************************************/ 329 330void AppleUSBCDCEEM::dataReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 331{ 332 AppleUSBCDCEEM *me = (AppleUSBCDCEEM*)obj; 333 IOReturn ior; 334 pipeInBuffers *pipeBuf = (pipeInBuffers *)param; 335// UInt32 poolIndx = (UInt32)param; 336 UInt16 EEMHeader; 337 UInt16 *EEMHeaderAddress = &EEMHeader; 338 SInt16 actualLen, dataLen, i = 0; 339 bool done = false; 340 341 XTRACE(me, 0, pipeBuf->indx, "dataReadComplete"); 342 343 if (rc == kIOReturnSuccess) 344 { 345 dataLen = me->fMax_Block_Size - remaining; 346 XTRACE(me, 0, dataLen, "dataReadComplete - data length"); 347 348 while (!done) 349 { 350 EEMHeaderAddress[0] = pipeBuf->pipeInBuffer[i]; 351 EEMHeaderAddress[1] = pipeBuf->pipeInBuffer[i+1]; 352 353 if (EEMHeader & bmTypeCommand) 354 { 355 356 // Look at the command 357 358 me->processEEMCommand(EEMHeader, pipeBuf->indx, i+2, &actualLen); 359 } else { 360 actualLen = EEMHeader & frameLenMask; 361 meLogData(kDataIn, actualLen+2, &pipeBuf->pipeInBuffer[i]); 362 363 // Move the incoming bytes up the stack 364 365 me->receivePacket(&pipeBuf->pipeInBuffer[i+2], actualLen); 366 } 367 i += actualLen; 368 if (i >= dataLen) 369 { 370 done = true; 371 } 372 } 373 } else { 374 XTRACE(me, 0, rc, "dataReadComplete - Read completion io err"); 375 if (rc != kIOReturnAborted) 376 { 377 rc = me->clearPipeStall(me->fInPipe); 378 if (rc != kIOReturnSuccess) 379 { 380 XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)"); 381 } 382 } 383 } 384 385 // Queue the next read, only if not aborted 386 387 if (rc != kIOReturnAborted) 388 { 389 ior = me->fInPipe->Read(pipeBuf->pipeInMDP, &pipeBuf->readCompletionInfo, NULL); 390 if (ior != kIOReturnSuccess) 391 { 392 XTRACE(me, 0, ior, "dataReadComplete - Failed to queue read"); 393 pipeBuf->dead = true; 394 } 395 } else { 396 XTRACE(me, 0, 0, "dataReadComplete - Read terminated"); 397 pipeBuf->dead = true; 398 } 399 400 return; 401 402}/* end dataReadComplete */ 403 404/****************************************************************************************************/ 405// 406// Method: AppleUSBCDCEEM::dataWriteComplete 407// 408// Inputs: obj - me 409// param - pool index 410// rc - return code 411// remaining - what's left 412// 413// Outputs: 414// 415// Desc: BulkOut pipe (Data interface) write completion routine 416// 417/****************************************************************************************************/ 418 419void AppleUSBCDCEEM::dataWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 420{ 421 AppleUSBCDCEEM *me = (AppleUSBCDCEEM *)obj; 422 mbuf_t m; 423 UInt32 pktLen = 0; 424 UInt32 numbufs = 0; 425 pipeOutBuffers *pipeBuf = (pipeOutBuffers *)param; 426// UInt32 poolIndx = (UInt32)param; 427 428 XTRACE(me, rc, pipeBuf->indx, "dataWriteComplete"); 429 430 if (me->fBufferPoolLock) 431 { 432 IOLockLock(me->fBufferPoolLock); 433 } 434 435 if (rc == kIOReturnSuccess) // If operation returned ok 436 { 437 if (pipeBuf->m != NULL) // Null means zero length write or command 438 { 439 m = pipeBuf->m; 440 while (m) 441 { 442 pktLen += mbuf_len(m); 443 numbufs++; 444 m = mbuf_next(m); 445 } 446 me->freePacket(pipeBuf->m); // Free the mbuf 447 pipeBuf->m = NULL; 448 449 if ((pktLen % me->fOutPacketSize) == 0) // If it was a multiple of max packet size then we need to do a zero length write 450 { 451 XTRACE(me, rc, pktLen, "dataWriteComplete - writing zero length packet"); 452 pipeBuf->pipeOutMDP->setLength(0); 453 pipeBuf->writeCompletionInfo.parameter = (void *)pipeBuf; 454 me->fOutPipe->Write(pipeBuf->pipeOutMDP, &pipeBuf->writeCompletionInfo); 455 } else { 456 pipeBuf->avail = true; 457 if (me->fTxStalled) 458 { 459 me->fTxStalled = false; 460 me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); 461 } 462 } 463 } else { 464 pipeBuf->avail = true; // Make the buffer available again 465 if (me->fTxStalled) 466 { 467 me->fTxStalled = false; 468 me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); 469 } 470 } 471 } else { 472 XTRACE(me, rc, pipeBuf->indx, "dataWriteComplete - IO err"); 473 474 if (pipeBuf->m != NULL) 475 { 476 me->freePacket(pipeBuf->m); // Free the mbuf anyway 477 pipeBuf->m = NULL; 478 pipeBuf->avail = true; 479 if (me->fTxStalled) 480 { 481 me->fTxStalled = false; 482 me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); 483 } 484 } 485 if (rc != kIOReturnAborted) 486 { 487 rc = me->clearPipeStall(me->fOutPipe); 488 if (rc != kIOReturnSuccess) 489 { 490 XTRACE(me, 0, rc, "dataWriteComplete - clear stall failed (trying to continue)"); 491 } 492 } 493 } 494 495 if (me->fBufferPoolLock) 496 { 497 IOLockUnlock(me->fBufferPoolLock); 498 } 499 500 return; 501 502}/* end dataWriteComplete */ 503 504/****************************************************************************************************/ 505// 506// Method: AppleUSBCDCEEM::probe 507// 508// Inputs: provider - my provider 509// 510// Outputs: IOService - from super::probe, score - probe score 511// 512// Desc: Modify the probe score if necessary (we don't at the moment) 513// 514/****************************************************************************************************/ 515 516IOService* AppleUSBCDCEEM::probe( IOService *provider, SInt32 *score ) 517{ 518 IOService *res; 519 520 // If our IOUSBInterface has a "do not match" property, it means that we should not match and need 521 // to bail. See rdar://3716623 522 523 OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface")); 524 if (boolObj && boolObj->isTrue()) 525 { 526 XTRACE(this, 0, 0, "probe - provider doesn't want us to match"); 527 return NULL; 528 } 529 530 res = super::probe(provider, score); 531 532 return res; 533 534}/* end probe */ 535 536/****************************************************************************************************/ 537// 538// Method: AppleUSBCDCEEM::init 539// 540// Inputs: properties - data (keys and values) used to match 541// 542// Outputs: Return code - true (init successful), false (init failed) 543// 544// Desc: Initialize the driver. 545// 546/****************************************************************************************************/ 547 548bool AppleUSBCDCEEM::init(OSDictionary *properties) 549{ 550 UInt32 i; 551 552 XTRACE(this, 0, 0, "init"); 553 554 if (super::init(properties) == false) 555 { 556 XTRACE(this, 0, 0, "init - initialize super failed"); 557 return false; 558 } 559 560 for (i=0; i<kMaxOutBufPool; i++) 561 { 562 fPipeOutBuff[i].pipeOutMDP = NULL; 563 fPipeOutBuff[i].pipeOutBuffer = NULL; 564 fPipeOutBuff[i].m = NULL; 565 fPipeOutBuff[i].avail = false; 566 fPipeOutBuff[i].writeCompletionInfo.target = NULL; 567 fPipeOutBuff[i].writeCompletionInfo.action = NULL; 568 fPipeOutBuff[i].writeCompletionInfo.parameter = NULL; 569 fPipeOutBuff[i].indx = i; 570 } 571 fOutPoolIndex = 0; 572 573 for (i=0; i<kMaxInBufPool; i++) 574 { 575 fPipeInBuff[i].pipeInMDP = NULL; 576 fPipeInBuff[i].pipeInBuffer = NULL; 577 fPipeInBuff[i].dead = false; 578 fPipeInBuff[i].readCompletionInfo.target = NULL; 579 fPipeInBuff[i].readCompletionInfo.action = NULL; 580 fPipeInBuff[i].readCompletionInfo.parameter = NULL; 581 fPipeInBuff[i].indx = i; 582 } 583 584 return true; 585 586}/* end init*/ 587 588/****************************************************************************************************/ 589// 590// Method: AppleUSBCDCEEM::start 591// 592// Inputs: provider - my provider 593// 594// Outputs: Return code - true (it's me), false (sorry it probably was me, but I can't configure it) 595// 596// Desc: This is called once it has beed determined I'm probably the best 597// driver for this device. 598// 599/****************************************************************************************************/ 600 601bool AppleUSBCDCEEM::start(IOService *provider) 602{ 603 OSNumber *bufNumber = NULL; 604 UInt16 bufValue = 0; 605 606 XTRACE(this, 0, 0, "start"); 607 608 return false; // Don't load for EEM hardware at this time 609 610 if(!super::start(provider)) 611 { 612 ALERT(0, 0, "start - start super failed"); 613 return false; 614 } 615 616 // Get my USB provider - the interface 617 618 fDataInterface = OSDynamicCast(IOUSBInterface, provider); 619 if(!fDataInterface) 620 { 621 ALERT(0, 0, "start - provider invalid"); 622 return false; 623 } 624 625 fDataInterfaceNumber = fDataInterface->GetInterfaceNumber(); 626 627 if (findCDCDriverEED(fDataInterface->GetDevice(), this, fDataInterfaceNumber) != kIOReturnSuccess) 628 { 629 XTRACE(this, 0, 0, "start - Find CDC driver failed"); 630 super::stop(provider); 631 return false; 632 } 633 634 fBufferPoolLock = IOLockAlloc(); 635 if (!fBufferPoolLock) 636 { 637 ALERT(0, 0, "start - Buffer pool lock allocate failed"); 638 return false; 639 } 640 641 // get workloop 642 643 fWorkLoop = getWorkLoop(); 644 if (!fWorkLoop) 645 { 646 ALERT(0, 0, "start - getWorkLoop failed"); 647 return false; 648 } 649 650 if (!configureData()) 651 { 652 ALERT(0, 0, "start - configureData failed"); 653 return false; 654 } 655 656 // Check for an input buffer pool override first 657 658 fInBufPool = 0; 659 fOutBufPool = 0; 660 661 bufNumber = (OSNumber *)provider->getProperty(inputTag); 662 if (bufNumber) 663 { 664 bufValue = bufNumber->unsigned16BitValue(); 665 XTRACE(this, 0, bufValue, "start - Number of input buffers override value"); 666 if (bufValue <= kMaxInBufPool) 667 { 668 fInBufPool = bufValue; 669 } else { 670 fInBufPool = kMaxInBufPool; 671 } 672 } else { 673 fInBufPool = 0; 674 } 675 676 // Now set up the real input buffer pool values (only if not overridden) 677 678 if (fInBufPool == 0) 679 { 680 bufNumber = NULL; 681 bufNumber = (OSNumber *)getProperty(inputTag); 682 if (bufNumber) 683 { 684 bufValue = bufNumber->unsigned16BitValue(); 685 XTRACE(this, 0, bufValue, "start - Number of input buffers requested"); 686 if (bufValue <= kMaxInBufPool) 687 { 688 fInBufPool = bufValue; 689 } else { 690 fInBufPool = kMaxInBufPool; 691 } 692 } else { 693 fInBufPool = kInBufPool; 694 } 695 } 696 697 // Check for an output buffer pool override 698 699 bufNumber = NULL; 700 bufNumber = (OSNumber *)provider->getProperty(outputTag); 701 if (bufNumber) 702 { 703 bufValue = bufNumber->unsigned16BitValue(); 704 XTRACE(this, 0, bufValue, "start - Number of output buffers override value"); 705 if (bufValue <= kMaxInBufPool) 706 { 707 fOutBufPool = bufValue; 708 } else { 709 fOutBufPool = kMaxOutBufPool; 710 } 711 } else { 712 fOutBufPool = 0; 713 } 714 715 // Now set up the real output buffer pool values (only if not overridden) 716 717 if (fOutBufPool == 0) 718 { 719 bufNumber = NULL; 720 bufNumber = (OSNumber *)getProperty(outputTag); 721 if (bufNumber) 722 { 723 bufValue = bufNumber->unsigned16BitValue(); 724 XTRACE(this, 0, bufValue, "start - Number of output buffers requested"); 725 if (bufValue <= kMaxOutBufPool) 726 { 727 fOutBufPool = bufValue; 728 } else { 729 fOutBufPool = kMaxOutBufPool; 730 } 731 } else { 732 fOutBufPool = kOutBufPool; 733 } 734 } 735 736 XTRACE(this, fInBufPool, fOutBufPool, "start - Buffer pools (input, output)"); 737 738 if (!createNetworkInterface()) 739 { 740 ALERT(0, 0, "start - createNetworkInterface failed"); 741 return false; 742 } 743 744 // Looks like we're ok 745 746 fDataInterface->retain(); 747 fWorkLoop->retain(); 748 fTransmitQueue->retain(); 749 750 // Ready to service interface requests 751 752 fNetworkInterface->registerService(); 753 754 XTRACE(this, 0, 0, "start - successful"); 755 Log(DEBUG_NAME ": Version number - %s, Input buffers %d, Output buffers %d\n", VersionNumber, fInBufPool, fOutBufPool); 756 757 return true; 758 759}/* end start */ 760 761/****************************************************************************************************/ 762// 763// Method: AppleUSBCDCEEM::stop 764// 765// Inputs: provider - my provider 766// 767// Outputs: 768// 769// Desc: Stops the driver 770// 771/****************************************************************************************************/ 772 773void AppleUSBCDCEEM::stop(IOService *provider) 774{ 775 776 XTRACE(this, 0, 0, "stop"); 777 778 // Release all resources 779 780 releaseResources(); 781 782 if (fDataInterface) 783 { 784 fDataInterface->close(this); 785 fDataInterface->release(); 786 fDataInterface = NULL; 787 } 788 789 if (fNetworkInterface) 790 { 791 fNetworkInterface->release(); 792 fNetworkInterface = NULL; 793 } 794 795 if (fMediumDict) 796 { 797 fMediumDict->release(); 798 fMediumDict = NULL; 799 } 800 801 if (fBufferPoolLock) 802 { 803 IOLockFree(fBufferPoolLock); 804 fBufferPoolLock = NULL; 805 } 806 807 if (fWorkLoop) 808 { 809 fWorkLoop->release(); 810 fWorkLoop = NULL; 811 } 812 813 if (fTransmitQueue) 814 { 815 fTransmitQueue->release(); 816 fTransmitQueue = NULL; 817 } 818 819 super::stop(provider); 820 821 return; 822 823}/* end stop */ 824 825/****************************************************************************************************/ 826// 827// Method: AppleUSBCDCEEM::configureData 828// 829// Inputs: 830// 831// Outputs: return code - true (configure was successful), false (it failed) 832// 833// Desc: Finishes up the rest of the configuration 834// 835/****************************************************************************************************/ 836 837bool AppleUSBCDCEEM::configureData() 838{ 839 IOUSBFindInterfaceRequest req; 840 const IOUSBInterfaceDescriptor *altInterfaceDesc; 841 IOReturn ior = kIOReturnSuccess; 842 UInt16 numends = 0; 843 UInt16 alt; 844 845 XTRACE(this, 0, 0, "configureData."); 846 847 if (!fDataInterface) 848 { 849 XTRACE(this, 0, 0, "configureData - Data interface is NULL"); 850 return false; 851 } 852 853 if (!fDataInterface->open(this)) 854 { 855 XTRACE(this, 0, 0, "configureData - open data interface failed"); 856 fDataInterface->release(); 857 fDataInterface = NULL; 858 return false; 859 } 860 861 // Check we have the correct interface (there maybe an alternate) 862 863 numends = fDataInterface->GetNumEndpoints(); 864 if (numends < 2) 865 { 866 req.bInterfaceClass = kUSBDataClass; 867 req.bInterfaceSubClass = 0; 868 req.bInterfaceProtocol = 0; 869 req.bAlternateSetting = kIOUSBFindInterfaceDontCare; 870 altInterfaceDesc = fDataInterface->FindNextAltInterface(NULL, &req); 871 if (!altInterfaceDesc) 872 { 873 XTRACE(this, 0, 0, "configureData - FindNextAltInterface failed"); 874 return false; 875 } 876 while (altInterfaceDesc) 877 { 878 numends = altInterfaceDesc->bNumEndpoints; 879 if (numends > 1) 880 { 881 alt = altInterfaceDesc->bAlternateSetting; 882 XTRACE(this, numends, alt, "configureData - Data Class interface (alternate) found"); 883 ior = fDataInterface->SetAlternateInterface(this, alt); 884 if (ior == kIOReturnSuccess) 885 { 886 XTRACE(this, 0, 0, "configureData - Alternate set"); 887 break; 888 } else { 889 XTRACE(this, 0, 0, "configureData - SetAlternateInterface failed"); 890 return false; 891 } 892 } else { 893 XTRACE(this, 0, 0, "configureData - No endpoints this alternate"); 894 } 895 altInterfaceDesc = fDataInterface->FindNextAltInterface(altInterfaceDesc, &req); 896 } 897 } 898 899 if (numends < 2) 900 { 901 XTRACE(this, 0, 0, "configureData - Could not find the correct interface"); 902 return false; 903 } 904 905 return true; 906 907}/* end configureData */ 908 909/****************************************************************************************************/ 910// 911// Method: AppleUSBCDCEEM::createNetworkInterface 912// 913// Inputs: 914// 915// Outputs: return Code - true (created and initialilzed ok), false (it failed) 916// 917// Desc: Creates and initializes the network interface 918// 919/****************************************************************************************************/ 920 921bool AppleUSBCDCEEM::createNetworkInterface() 922{ 923 924 XTRACE(this, 0, 0, "createNetworkInterface"); 925 926 // Allocate memory for transmit queue 927 928 fTransmitQueue = (IOGatedOutputQueue *)getOutputQueue(); 929 if (!fTransmitQueue) 930 { 931 ALERT(0, 0, "createNetworkInterface - Output queue initialization failed"); 932 return false; 933 } 934 935 // Attach an IOEthernetInterface client 936 937 XTRACE(this, 0, 0, "createNetworkInterface - attaching and registering interface"); 938 939 if (!attachInterface((IONetworkInterface **)&fNetworkInterface, false)) 940 { 941 ALERT(0, 0, "createNetworkInterface - attachInterface failed"); 942 return false; 943 } 944 945 XTRACE(this, 0, 0, "createNetworkInterface - Exiting, successful"); 946 947 return true; 948 949}/* end createNetworkInterface */ 950 951/****************************************************************************************************/ 952// 953// Method: AppleUSBCDCEEM::enable 954// 955// Inputs: netif - the interface being enabled 956// 957// Outputs: Return code - kIOReturnSuccess or kIOReturnIOError 958// 959// Desc: Called by IOEthernetInterface client to enable the controller. 960// This method is always called while running on the default workloop 961// thread 962// 963/****************************************************************************************************/ 964 965IOReturn AppleUSBCDCEEM::enable(IONetworkInterface *netif) 966{ 967 IONetworkMedium *medium; 968 IOMediumType mediumType = kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex; 969 970 XTRACE(this, 0, 0, "enable"); 971 972 IOSleep(5); // Just in case (to let start finish - on another thread) 973 974 // If an interface client has previously enabled us, 975 // and we know there can only be one interface client 976 // for this driver, then simply return success. 977 978 if (fNetifEnabled) 979 { 980 XTRACE(this, 0, 0, "enable - already enabled"); 981 return kIOReturnSuccess; 982 } 983 984 if (!fReady) 985 { 986 if (!wakeUp()) 987 { 988 XTRACE(this, 0, fReady, "enable - wakeUp failed"); 989 return kIOReturnIOError; 990 } 991 } 992 993 // Mark the controller as enabled by the interface. 994 995 fNetifEnabled = true; 996 997 // Assume an active link (leave this in for now - until we know better) 998 // Should probably use the values returned in the Network Connection notification 999 // that is if we have an interrupt pipe, otherwise default to these 1000 1001 fLinkStatus = 1; 1002 1003 medium = IONetworkMedium::getMediumWithType(fMediumDict, mediumType); 1004 XTRACE(this, mediumType, 0, "enable - medium type"); 1005 setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 10 * 1000000); 1006 XTRACE(this, 0, 0, "enable - LinkStatus set"); 1007 1008 // Start our IOOutputQueue object. 1009 1010 fTransmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); 1011 XTRACE(this, 0, TRANSMIT_QUEUE_SIZE, "enable - capicity set"); 1012 fTransmitQueue->start(); 1013 XTRACE(this, 0, 0, "enable - transmit queue started"); 1014 1015 return kIOReturnSuccess; 1016 1017}/* end enable */ 1018 1019/****************************************************************************************************/ 1020// 1021// Method: AppleUSBCDCEEM::disable 1022// 1023// Inputs: netif - the interface being disabled 1024// 1025// Outputs: Return code - kIOReturnSuccess 1026// 1027// Desc: Called by IOEthernetInterface client to disable the controller. 1028// This method is always called while running on the default workloop 1029// thread 1030// 1031/****************************************************************************************************/ 1032 1033IOReturn AppleUSBCDCEEM::disable(IONetworkInterface *netif) 1034{ 1035 1036 XTRACE(this, 0, 0, "disable"); 1037 1038 // Disable our IOOutputQueue object. This will prevent the 1039 // outputPacket() method from being called 1040 1041 fTransmitQueue->stop(); 1042 1043 // Flush all packets currently in the output queue 1044 1045 fTransmitQueue->setCapacity(0); 1046 fTransmitQueue->flush(); 1047 1048 putToSleep(); 1049 1050 fNetifEnabled = false; 1051 fReady = false; 1052 1053 return kIOReturnSuccess; 1054 1055}/* end disable */ 1056 1057/****************************************************************************************************/ 1058// 1059// Method: AppleUSBCDCEEM::setWakeOnMagicPacket 1060// 1061// Inputs: active - true(wake), false(don't) 1062// 1063// Outputs: Return code - kIOReturnSuccess 1064// 1065// Desc: Set for wake on magic packet 1066// 1067/****************************************************************************************************/ 1068 1069IOReturn AppleUSBCDCEEM::setWakeOnMagicPacket(bool active) 1070{ 1071 IOUSBDevRequest devreq; 1072 IOReturn ior = kIOReturnSuccess; 1073 1074 XTRACE(this, 0, active, "setWakeOnMagicPacket"); 1075 1076 fWOL = active; 1077 1078 if (fConfigAttributes & kUSBAtrRemoteWakeup) 1079 { 1080 1081 // Set/Clear the Device Remote Wake feature depending upon the active flag 1082 1083 devreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice); 1084 if (active) 1085 { 1086 devreq.bRequest = kUSBRqSetFeature; 1087 } else { 1088 devreq.bRequest = kUSBRqClearFeature; 1089 } 1090 devreq.wValue = kUSBFeatureDeviceRemoteWakeup; 1091 devreq.wIndex = 0; 1092 devreq.wLength = 0; 1093 devreq.pData = 0; 1094 1095 ior = fDataInterface->GetDevice()->DeviceRequest(&devreq); 1096 if (ior == kIOReturnSuccess) 1097 { 1098 XTRACE(this, 0, ior, "setWakeOnMagicPacket - Set/Clear remote wake up feature successful"); 1099 } else { 1100 XTRACE(this, 0, ior, "setWakeOnMagicPacket - Set/Clear remote wake up feature failed"); 1101 } 1102 } else { 1103 XTRACE(this, 0, 0, "setWakeOnMagicPacket - Remote wake up not supported"); 1104 } 1105 1106 1107 return kIOReturnSuccess; 1108 1109}/* end setWakeOnMagicPacket */ 1110 1111/****************************************************************************************************/ 1112// 1113// Method: AppleUSBCDCEEM::getPacketFilters 1114// 1115// Inputs: group - the filter group 1116// 1117// Outputs: Return code - kIOReturnSuccess and others 1118// filters - the capability 1119// 1120// Desc: Set the filter capability for the driver 1121// 1122/****************************************************************************************************/ 1123 1124IOReturn AppleUSBCDCEEM::getPacketFilters(const OSSymbol *group, UInt32 *filters) const 1125{ 1126 IOReturn rtn = kIOReturnSuccess; 1127 1128 XTRACE(this, 0, 0, "getPacketFilters"); 1129 1130 if (group == gIOEthernetWakeOnLANFilterGroup) 1131 { 1132 if (fConfigAttributes & kUSBAtrRemoteWakeup) 1133 { 1134 *filters = kIOEthernetWakeOnMagicPacket; 1135 } else { 1136 *filters = 0; 1137 } 1138 } else { 1139 if (group == gIONetworkFilterGroup) 1140 { 1141 *filters = kIOPacketFilterUnicast | kIOPacketFilterBroadcast; 1142 } else { 1143 rtn = super::getPacketFilters(group, filters); 1144 } 1145 } 1146 1147 if (rtn != kIOReturnSuccess) 1148 { 1149 XTRACE(this, 0, rtn, "getPacketFilters - failed"); 1150 } 1151 1152 return rtn; 1153 1154}/* end getPacketFilters */ 1155 1156/****************************************************************************************************/ 1157// 1158// Method: AppleUSBCDCEEM::selectMedium 1159// 1160// Inputs: 1161// 1162// Outputs: 1163// 1164// Desc: Lets us know if someone is playing with ifconfig 1165// 1166/****************************************************************************************************/ 1167 1168IOReturn AppleUSBCDCEEM::selectMedium(const IONetworkMedium *medium) 1169{ 1170 1171 XTRACE(this, 0, 0, "selectMedium"); 1172 1173 setSelectedMedium(medium); 1174 1175 return kIOReturnSuccess; 1176 1177}/* end selectMedium */ 1178 1179/****************************************************************************************************/ 1180// 1181// Method: AppleUSBCDCEEM::getHardwareAddress 1182// 1183// Inputs: 1184// 1185// Outputs: Return code - kIOReturnSuccess or kIOReturnError 1186// ea - the address 1187// 1188// Desc: Make up an ethernet address for now 1189// ***** THIS IS TEMPORARY AND MUST BE CHANGED ***** 1190// 1191/****************************************************************************************************/ 1192 1193IOReturn AppleUSBCDCEEM::getHardwareAddress(IOEthernetAddress *ea) 1194{ 1195 UInt32 i; 1196 OSNumber *location; 1197 UInt32 locVal; 1198 UInt8 *rlocVal; 1199 1200 XTRACE(this, 0, 0, "getHardwareAddress"); 1201 1202 location = (OSNumber *)fDataInterface->GetDevice()->getProperty(kUSBDevicePropertyLocationID); 1203 if (location) 1204 { 1205 locVal = location->unsigned32BitValue(); 1206 rlocVal = (UInt8*)&locVal; 1207 ea->bytes[0] = 0x00; 1208 ea->bytes[1] = 0x03; 1209 for (i=0; i<4; i++) 1210 { 1211 ea->bytes[i+2] = rlocVal[i]; 1212 } 1213 } else { 1214 XTRACE(this, 0, 0, "getHardwareAddress - Get location failed"); 1215 return kIOReturnError; 1216 } 1217 1218 return kIOReturnSuccess; 1219 1220}/* end getHardwareAddress */ 1221 1222/****************************************************************************************************/ 1223// 1224// Method: AppleUSBCDCEEM::newVendorString 1225// 1226// Inputs: 1227// 1228// Outputs: Return code - the vendor string 1229// 1230// Desc: Identifies the hardware vendor 1231// 1232/****************************************************************************************************/ 1233 1234const OSString* AppleUSBCDCEEM::newVendorString() const 1235{ 1236 1237 XTRACE(this, 0, 0, "newVendorString"); 1238 1239 return OSString::withCString((const char *)defaultName); // Maybe we should use the descriptors 1240 1241}/* end newVendorString */ 1242 1243/****************************************************************************************************/ 1244// 1245// Method: AppleUSBCDCEEM::newModelString 1246// 1247// Inputs: 1248// 1249// Outputs: Return code - the model string 1250// 1251// Desc: Identifies the hardware model 1252// 1253/****************************************************************************************************/ 1254 1255const OSString* AppleUSBCDCEEM::newModelString() const 1256{ 1257 1258 XTRACE(this, 0, 0, "newModelString"); 1259 1260 return OSString::withCString("USB"); // Maybe we should use the descriptors 1261 1262}/* end newModelString */ 1263 1264/****************************************************************************************************/ 1265// 1266// Method: AppleUSBCDCEEM::newRevisionString 1267// 1268// Inputs: 1269// 1270// Outputs: Return code - the revision string 1271// 1272// Desc: Identifies the hardware revision 1273// 1274/****************************************************************************************************/ 1275 1276const OSString* AppleUSBCDCEEM::newRevisionString() const 1277{ 1278 1279 XTRACE(this, 0, 0, "newRevisionString"); 1280 1281 return OSString::withCString(""); 1282 1283}/* end newRevisionString */ 1284 1285/****************************************************************************************************/ 1286// 1287// Method: AppleUSBCDCEEM::setMulticastMode 1288// 1289// Inputs: active - true (set it), false (don't) 1290// 1291// Outputs: Return code - kIOReturnSuccess 1292// 1293// Desc: Sets multicast mode (not supported in this driver) 1294// 1295/****************************************************************************************************/ 1296 1297IOReturn AppleUSBCDCEEM::setMulticastMode(bool active) 1298{ 1299 1300 XTRACE(this, 0, active, "setMulticastMode"); 1301 1302 return kIOReturnIOError; 1303 1304}/* end setMulticastMode */ 1305 1306/****************************************************************************************************/ 1307// 1308// Method: AppleUSBCDCEEM::setMulticastList 1309// 1310// Inputs: addrs - list of addresses 1311// count - number in the list 1312// 1313// Outputs: Return code - kIOReturnSuccess or kIOReturnIOError 1314// 1315// Desc: Sets multicast list (not supported in this driver 1316// 1317/****************************************************************************************************/ 1318 1319IOReturn AppleUSBCDCEEM::setMulticastList(IOEthernetAddress *addrs, UInt32 count) 1320{ 1321// bool uStat; 1322 1323 XTRACE(this, 0, count, "setMulticastList"); 1324 1325 return kIOReturnIOError; 1326 1327}/* end setMulticastList */ 1328 1329/****************************************************************************************************/ 1330// 1331// Method: AppleUSBCDCEEM::setPromiscuousMode 1332// 1333// Inputs: active - true (set it), false (don't) 1334// 1335// Outputs: Return code - kIOReturnSuccess 1336// 1337// Desc: Sets promiscuous mode (not supported by this driver) 1338// 1339/****************************************************************************************************/ 1340 1341IOReturn AppleUSBCDCEEM::setPromiscuousMode(bool active) 1342{ 1343 1344 XTRACE(this, 0, active, "setPromiscuousMode"); 1345 1346 return kIOReturnIOError; 1347 1348}/* end setPromiscuousMode */ 1349 1350/****************************************************************************************************/ 1351// 1352// Method: AppleUSBCDCEEM::createOutputQueue 1353// 1354// Inputs: 1355// 1356// Outputs: Return code - the output queue 1357// 1358// Desc: Creates the output queue 1359// 1360/****************************************************************************************************/ 1361 1362IOOutputQueue* AppleUSBCDCEEM::createOutputQueue() 1363{ 1364 1365 XTRACE(this, 0, 0, "createOutputQueue"); 1366 1367 return IOBasicOutputQueue::withTarget(this, TRANSMIT_QUEUE_SIZE); 1368 1369}/* end createOutputQueue */ 1370 1371/****************************************************************************************************/ 1372// 1373// Method: AppleUSBCDCEEM::outputPacket 1374// 1375// Inputs: mbuf - the packet 1376// param - optional parameter 1377// 1378// Outputs: Return code - kIOReturnOutputSuccess or kIOReturnOutputStall 1379// 1380// Desc: Packet transmission. The BSD mbuf needs to be formatted correctly 1381// and transmitted 1382// 1383/****************************************************************************************************/ 1384 1385UInt32 AppleUSBCDCEEM::outputPacket(mbuf_t pkt, void *param) 1386{ 1387 UInt32 ior = kIOReturnSuccess; 1388 1389 XTRACE(this, 0, 0, "outputPacket"); 1390 1391 if (!fLinkStatus) 1392 { 1393 XTRACE(this, 0, fLinkStatus, "outputPacket - link is down"); 1394 fpNetStats->outputErrors++; 1395 freePacket(pkt); 1396 return kIOReturnOutputDropped; 1397 } 1398 1399 ior = USBTransmitPacket(pkt); 1400 if (ior != kIOReturnOutputStall) 1401 { 1402 freePacket(pkt); 1403 } 1404 1405 XTRACE(this, 0, ior, "outputPacket - Exit"); 1406 1407 return ior; 1408 1409}/* end outputPacket */ 1410 1411/****************************************************************************************************/ 1412// 1413// Method: AppleUSBCDCEEM::configureInterface 1414// 1415// Inputs: netif - the interface being configured 1416// 1417// Outputs: Return code - true (configured ok), false (not) 1418// 1419// Desc: Finish the network interface configuration 1420// 1421/****************************************************************************************************/ 1422 1423bool AppleUSBCDCEEM::configureInterface(IONetworkInterface *netif) 1424{ 1425 IONetworkData *nd; 1426 1427 XTRACE(this, 0, 0, "configureInterface"); 1428 1429 if (super::configureInterface(netif) == false) 1430 { 1431 ALERT(0, 0, "configureInterface - super failed"); 1432 return false; 1433 } 1434 1435 // Get a pointer to the statistics structure in the interface 1436 1437 nd = netif->getNetworkData(kIONetworkStatsKey); 1438 if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer())) 1439 { 1440 ALERT(0, 0, "configureInterface - Invalid network statistics"); 1441 return false; 1442 } 1443 1444 // Get the Ethernet statistics structure 1445 1446 nd = netif->getParameter(kIOEthernetStatsKey); 1447 if (!nd || !(fpEtherStats = (IOEthernetStats*)nd->getBuffer())) 1448 { 1449 ALERT(0, 0, "configureInterface - Invalid ethernet statistics\n"); 1450 return false; 1451 } 1452 1453 return true; 1454 1455}/* end configureInterface */ 1456 1457/****************************************************************************************************/ 1458// 1459// Method: AppleUSBCDCEEM::wakeUp 1460// 1461// Inputs: 1462// 1463// Outputs: Return Code - true(we're awake), false(failed) 1464// 1465// Desc: Resumes the device it it was suspended and then gets all the data 1466// structures sorted out and all the pipes ready. 1467// 1468/****************************************************************************************************/ 1469 1470bool AppleUSBCDCEEM::wakeUp() 1471{ 1472 IOReturn rtn = kIOReturnSuccess; 1473 UInt32 i; 1474 bool readOK = false; 1475 1476 XTRACE(this, 0, 0, "wakeUp"); 1477 1478 fReady = false; 1479 1480 setLinkStatus(0, 0); // Initialize the link state 1481 1482 if (!allocateResources()) 1483 { 1484 ALERT(0, 0, "wakeUp - allocateResources failed"); 1485 return false; 1486 } 1487 1488 // Kick off the data-in bulk pipe reads 1489 1490 for (i=0; i<fInBufPool; i++) 1491 { 1492 if (fPipeInBuff[i].pipeInMDP) 1493 { 1494 fPipeInBuff[i].readCompletionInfo.parameter = (void *)&fPipeInBuff[i]; 1495 rtn = fInPipe->Read(fPipeInBuff[i].pipeInMDP, &fPipeInBuff[i].readCompletionInfo, NULL); 1496 if (rtn == kIOReturnSuccess) 1497 { 1498 readOK = true; 1499 } else { 1500 XTRACE(this, i, rtn, "wakeUp - Read failed"); 1501 } 1502 } 1503 } 1504 1505 if (!readOK) 1506 { 1507 1508 // We failed for some reason 1509 1510 ALERT(0, 0, "wakeUp - Starting the input pipe read(s) failed"); 1511 return false; 1512 } else { 1513 if (!fMediumDict) 1514 { 1515 if (!createMediumTables()) 1516 { 1517 ALERT(0, 0, "wakeUp - createMediumTables failed"); 1518 return false; 1519 } 1520 } 1521 1522 fReady = true; 1523 } 1524 1525 return true; 1526 1527}/* end wakeUp */ 1528 1529/****************************************************************************************************/ 1530// 1531// Method: AppleUSBCDCEEM::putToSleep 1532// 1533// Inputs: 1534// 1535// Outputs: Return Code - true(we're asleep), false(failed) 1536// 1537// Desc: Do clean up and suspend the device. 1538// 1539/****************************************************************************************************/ 1540 1541void AppleUSBCDCEEM::putToSleep() 1542{ 1543 1544 XTRACE(this, 0, 0, "putToSleep"); 1545 1546 fReady = false; 1547 1548 setLinkStatus(0, 0); 1549 1550}/* end putToSleep */ 1551 1552/****************************************************************************************************/ 1553// 1554// Method: AppleUSBCDCEEM::createMediumTables 1555// 1556// Inputs: 1557// 1558// Outputs: Return code - true (tables created), false (not created) 1559// 1560// Desc: Creates the medium tables 1561// 1562/****************************************************************************************************/ 1563 1564bool AppleUSBCDCEEM::createMediumTables() 1565{ 1566 IONetworkMedium *medium; 1567 UInt64 maxSpeed; 1568 UInt32 i; 1569 1570 XTRACE(this, 0, 0, "createMediumTables"); 1571 1572 maxSpeed = 100; 1573 fMediumDict = OSDictionary::withCapacity(sizeof(mediumTable) / sizeof(mediumTable[0])); 1574 if (fMediumDict == 0) 1575 { 1576 XTRACE(this, 0, 0, "createMediumTables - create dict. failed"); 1577 return false; 1578 } 1579 1580 for (i = 0; i < sizeof(mediumTable) / sizeof(mediumTable[0]); i++) 1581 { 1582 medium = IONetworkMedium::medium(mediumTable[i].type, mediumTable[i].speed); 1583 if (medium && (medium->getSpeed() <= maxSpeed)) 1584 { 1585 IONetworkMedium::addMedium(fMediumDict, medium); 1586 medium->release(); 1587 } 1588 } 1589 1590 if (publishMediumDictionary(fMediumDict) != true) 1591 { 1592 XTRACE(this, 0, 0, "createMediumTables - publish dict. failed"); 1593 return false; 1594 } 1595 1596 medium = IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetAuto); 1597 setCurrentMedium(medium); 1598 1599 return true; 1600 1601}/* end createMediumTables */ 1602 1603/****************************************************************************************************/ 1604// 1605// Method: AppleUSBCDCEEM::allocateResources 1606// 1607// Inputs: 1608// 1609// Outputs: return code - true (allocate was successful), false (it failed) 1610// 1611// Desc: Gets all the endpoints open and buffers allocated etc. 1612// 1613/****************************************************************************************************/ 1614 1615bool AppleUSBCDCEEM::allocateResources() 1616{ 1617 IOUSBFindEndpointRequest epReq; 1618 UInt32 i; 1619 1620 XTRACE(this, 0, 0, "allocateResources."); 1621 1622 // Open all the end points 1623 1624 epReq.type = kUSBBulk; 1625 epReq.direction = kUSBIn; 1626 epReq.maxPacketSize = 0; 1627 epReq.interval = 0; 1628 fInPipe = fDataInterface->FindNextPipe(0, &epReq); 1629 if (!fInPipe) 1630 { 1631 XTRACE(this, 0, 0, "allocateResources - no bulk input pipe."); 1632 return false; 1633 } 1634 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk input pipe."); 1635 1636 epReq.direction = kUSBOut; 1637 fOutPipe = fDataInterface->FindNextPipe(0, &epReq); 1638 if (!fOutPipe) 1639 { 1640 XTRACE(this, 0, 0, "allocateResources - no bulk output pipe."); 1641 return false; 1642 } 1643 fOutPacketSize = epReq.maxPacketSize; 1644 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk output pipe."); 1645 1646 // Allocate Memory Descriptor Pointer with memory for the data-in bulk pipe 1647 1648 for (i=0; i<fInBufPool; i++) 1649 { 1650// fPipeInBuff[i].pipeInMDP = IOBufferMemoryDescriptor::withCapacity(fMax_Block_Size, kIODirectionIn); 1651 fPipeInBuff[i].pipeInMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionIn | kIOMemoryPhysicallyContiguous, fMax_Block_Size, PAGE_SIZE); 1652 if (!fPipeInBuff[i].pipeInMDP) 1653 { 1654 XTRACE(this, 0, i, "allocateResources - Allocate input descriptor failed"); 1655 return false; 1656 } 1657 1658 fPipeInBuff[i].pipeInMDP->setLength(fMax_Block_Size); 1659 fPipeInBuff[i].pipeInBuffer = (UInt8*)fPipeInBuff[i].pipeInMDP->getBytesNoCopy(); 1660 XTRACE(this, 0, i, "allocateResources - input buffer"); 1661 fPipeInBuff[i].dead = false; 1662 fPipeInBuff[i].readCompletionInfo.target = this; 1663 fPipeInBuff[i].readCompletionInfo.action = dataReadComplete; 1664 fPipeInBuff[i].readCompletionInfo.parameter = NULL; 1665 } 1666 1667 // Allocate Memory Descriptor Pointers with memory for the data-out bulk pipe pool 1668 1669 for (i=0; i<fOutBufPool; i++) 1670 { 1671// fPipeOutBuff[i].pipeOutMDP = IOBufferMemoryDescriptor::withCapacity(fMax_Block_Size, kIODirectionOut); 1672 fPipeOutBuff[i].pipeOutMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionOut | kIOMemoryPhysicallyContiguous, fMax_Block_Size, PAGE_SIZE); 1673 if (!fPipeOutBuff[i].pipeOutMDP) 1674 { 1675 XTRACE(this, 0, i, "allocateResources - Allocate output descriptor failed"); 1676 return false; 1677 } 1678 1679 fPipeOutBuff[i].pipeOutMDP->setLength(fMax_Block_Size); 1680 fPipeOutBuff[i].pipeOutBuffer = (UInt8*)fPipeOutBuff[i].pipeOutMDP->getBytesNoCopy(); 1681 XTRACE(this, 0, i, "allocateResources - output buffer"); 1682 fPipeOutBuff[i].avail = true; 1683 fPipeOutBuff[i].writeCompletionInfo.target = this; 1684 fPipeOutBuff[i].writeCompletionInfo.action = dataWriteComplete; 1685 fPipeOutBuff[i].writeCompletionInfo.parameter = NULL; // for now, filled in with pool index when sent 1686 } 1687 1688 return true; 1689 1690}/* end allocateResources */ 1691 1692/****************************************************************************************************/ 1693// 1694// Method: AppleUSBCDCEEM::releaseResources 1695// 1696// Inputs: 1697// 1698// Outputs: 1699// 1700// Desc: Frees up the resources allocated in allocateResources 1701// 1702/****************************************************************************************************/ 1703 1704void AppleUSBCDCEEM::releaseResources() 1705{ 1706 UInt32 i; 1707 1708 XTRACE(this, 0, 0, "releaseResources"); 1709 1710 for (i=0; i<fOutBufPool; i++) 1711 { 1712 if (fPipeOutBuff[i].pipeOutMDP) 1713 { 1714 fPipeOutBuff[i].pipeOutMDP->release(); 1715 fPipeOutBuff[i].pipeOutMDP = NULL; 1716 fPipeOutBuff[i].avail = false; 1717 fPipeOutBuff[i].writeCompletionInfo.target = NULL; 1718 fPipeOutBuff[i].writeCompletionInfo.action = NULL; 1719 fPipeOutBuff[i].writeCompletionInfo.parameter = NULL; 1720 } 1721 } 1722 fOutPoolIndex = 0; 1723 1724 for (i=0; i<fInBufPool; i++) 1725 { 1726 if (fPipeInBuff[i].pipeInMDP) 1727 { 1728 fPipeInBuff[i].pipeInMDP->release(); 1729 fPipeInBuff[i].pipeInMDP = NULL; 1730 fPipeInBuff[i].dead = false; 1731 fPipeInBuff[i].readCompletionInfo.target = NULL; 1732 fPipeInBuff[i].readCompletionInfo.action = NULL; 1733 fPipeInBuff[i].readCompletionInfo.parameter = NULL; 1734 } 1735 } 1736 1737}/* end releaseResources */ 1738 1739/****************************************************************************************************/ 1740// 1741// Method: AppleUSBCDCEEM::getOutputBuffer 1742// 1743// Inputs: bufIndx - index of an available buffer 1744// 1745// Outputs: Return code - True (got one), False (none available) 1746// 1747// Desc: Get an available buffer from the output buffer pool 1748// 1749/****************************************************************************************************/ 1750 1751bool AppleUSBCDCEEM::getOutputBuffer(UInt32 *bufIndx) 1752{ 1753 bool gotBuffer = false; 1754 UInt32 indx; 1755 1756 XTRACE(this, 0, 0, "getOutputBuffer"); 1757 1758 if (fBufferPoolLock) 1759 { 1760 IOLockLock(fBufferPoolLock); 1761 } else { 1762 return false; 1763 } 1764 1765 while (!gotBuffer) 1766 { 1767 // Get an ouput buffer (use the hint first then if that's not available look for one) 1768 1769 indx = fOutPoolIndex; 1770 if (!fPipeOutBuff[indx].avail) 1771 { 1772 for (indx=0; indx<fOutBufPool; indx++) 1773 { 1774 if (fPipeOutBuff[indx].avail) 1775 { 1776 fOutPoolIndex = indx; 1777 gotBuffer = true; 1778 break; 1779 } 1780 } 1781 } else { 1782 gotBuffer = true; 1783 } 1784 1785 if (gotBuffer) 1786 { 1787 fPipeOutBuff[indx].avail = false; 1788 fOutPoolIndex++; 1789 if (fOutPoolIndex >= fOutBufPool) 1790 { 1791 fOutPoolIndex = 0; 1792 } 1793 } 1794 break; 1795 } 1796 1797 IOLockUnlock(fBufferPoolLock); 1798 1799 *bufIndx = indx; 1800 1801 return gotBuffer; 1802 1803}/* end getOutputBuffer */ 1804 1805/****************************************************************************************************/ 1806// 1807// Method: AppleUSBCDCEEM::USBTransmitPacket 1808// 1809// Inputs: packet - the packet 1810// 1811// Outputs: Return code - kIOReturnSuccess (transmit started), everything else (it didn't) 1812// 1813// Desc: Set up and then transmit the packet. 1814// 1815/****************************************************************************************************/ 1816 1817IOReturn AppleUSBCDCEEM::USBTransmitPacket(mbuf_t packet) 1818{ 1819 UInt32 numbufs = 0; // number of mbufs for this packet 1820 mbuf_t m; // current mbuf 1821 UInt32 total_pkt_length = 0; 1822 UInt32 rTotal = 0; 1823 IOReturn ior = kIOReturnSuccess; 1824 UInt32 indx; 1825 1826 XTRACE(this, 0, 0, "USBTransmitPacket"); 1827 1828 // Count the number of mbufs in this packet 1829 1830 m = packet; 1831 while (m) 1832 { 1833 if (mbuf_len(m) != 0) 1834 { 1835 total_pkt_length += mbuf_len(m); 1836 numbufs++; 1837 } 1838 m = mbuf_next(m); 1839 } 1840 1841 XTRACE(this, total_pkt_length, numbufs, "USBTransmitPacket - Total packet length and Number of mbufs"); 1842 1843 if (total_pkt_length > fMax_Block_Size) 1844 { 1845 XTRACE(this, 0, 0, "USBTransmitPacket - Bad packet size"); // Note for now and revisit later 1846 fpNetStats->outputErrors++; 1847 return kIOReturnInternalError; 1848 } 1849 1850 if (!getOutputBuffer(&indx)) 1851 { 1852 ALERT(fOutBufPool, fOutPoolIndex, "USBTransmitPacket - Output buffer unavailable"); 1853 fTxStalled = true; 1854 return kIOReturnOutputStall; 1855 } 1856 1857 // Start filling in the send buffer 1858 1859 m = packet; // start with the first mbuf of the packet 1860 rTotal = 0; // running total 1861 do 1862 { 1863 if (mbuf_len(m) == 0) // Ignore zero length buffers 1864 continue; 1865 1866 bcopy(mbuf_data(m), &fPipeOutBuff[indx].pipeOutBuffer[rTotal], mbuf_len(m)); 1867 rTotal += mbuf_len(m); 1868 1869 } while ((m = mbuf_next(m)) != 0); 1870 1871 LogData(kDataOut, rTotal, fPipeOutBuff[indx].pipeOutBuffer); 1872 1873 fPipeOutBuff[indx].m = packet; 1874 fPipeOutBuff[indx].writeCompletionInfo.parameter = (void *)&fPipeOutBuff[indx]; 1875 fPipeOutBuff[indx].pipeOutMDP->setLength(rTotal); 1876 ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo); 1877 if (ior != kIOReturnSuccess) 1878 { 1879 XTRACE(this, 0, ior, "USBTransmitPacket - Write failed"); 1880 if (ior == kIOUSBPipeStalled) 1881 { 1882 fOutPipe->Reset(); 1883 ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo); 1884 if (ior != kIOReturnSuccess) 1885 { 1886 XTRACE(this, 0, ior, "USBTransmitPacket - Write really failed"); 1887 fpNetStats->outputErrors++; 1888 return ior; 1889 } 1890 } 1891 } 1892 1893 fpNetStats->outputPackets++; 1894 1895 return ior; 1896 1897}/* end USBTransmitPacket */ 1898 1899/****************************************************************************************************/ 1900// 1901// Method: AppleUSBCDCEEM::USBSendCommand 1902// 1903// Inputs: command - the command to be sent 1904// length - length of any data to be sent 1905// anyData - any actual data (must be present if length > 0) 1906// 1907// Outputs: Return code - kIOReturnSuccess (transmit started), everything else (it didn't) 1908// 1909// Desc: Set up and a command packet. 1910// 1911/****************************************************************************************************/ 1912 1913IOReturn AppleUSBCDCEEM::USBSendCommand(UInt16 command, UInt16 length, UInt8 *anyData) 1914{ 1915 IOReturn ior = kIOReturnSuccess; 1916 UInt32 indx; 1917 bool gotBuffer = false; 1918 UInt16 EEMHeader = bmTypeCommand; 1919 1920 XTRACE(this, command, length, "USBSendCommand"); 1921 1922 if ((length > 0) && (anyData == NULL)) 1923 { 1924 return kIOReturnBadArgument; 1925 } 1926 1927 // Get an ouput buffer (use the hint first then if that's not available look for one) 1928 1929 if (fBufferPoolLock) 1930 { 1931 IOLockLock(fBufferPoolLock); 1932 } 1933 1934 indx = fOutPoolIndex; 1935 if (!fPipeOutBuff[indx].avail) 1936 { 1937 for (indx=0; indx<fOutBufPool; indx++) 1938 { 1939 if (fPipeOutBuff[indx].avail) 1940 { 1941 fOutPoolIndex = indx; 1942 gotBuffer = true; 1943 break; 1944 } 1945 } 1946 if (!gotBuffer) 1947 { 1948 XTRACE(this, fOutBufPool, fOutPoolIndex, "USBSendCommand - Output buffer unavailable"); 1949 fpNetStats->outputErrors++; 1950 if (fBufferPoolLock) 1951 { 1952 IOLockUnlock(fBufferPoolLock); 1953 } 1954 return kIOReturnInternalError; 1955 } 1956 } 1957 fOutPoolIndex++; 1958 if (fOutPoolIndex >= fOutBufPool) 1959 { 1960 fOutPoolIndex = 0; 1961 } 1962 1963 if (fBufferPoolLock) 1964 { 1965 IOLockUnlock(fBufferPoolLock); 1966 } 1967 1968 // Now handle the data 1969 1970 EEMHeader |= command; 1971 EEMHeader |= length; 1972 1973 bcopy(&EEMHeader, fPipeOutBuff[indx].pipeOutBuffer, sizeof(EEMHeader)); 1974 if (length > 0) 1975 { 1976 bcopy(anyData, &fPipeOutBuff[indx].pipeOutBuffer[2], length); 1977 } 1978 1979 LogData(kDataOut, length+2, fPipeOutBuff[indx].pipeOutBuffer); 1980 1981 fPipeOutBuff[indx].m = NULL; 1982 fPipeOutBuff[indx].writeCompletionInfo.parameter = (void *)indx; 1983 fPipeOutBuff[indx].pipeOutMDP->setLength(length+2); 1984 ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo); 1985 if (ior != kIOReturnSuccess) 1986 { 1987 XTRACE(this, 0, ior, "USBSendCommand - Write failed"); 1988 if (ior == kIOUSBPipeStalled) 1989 { 1990 fOutPipe->Reset(); 1991 ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo); 1992 if (ior != kIOReturnSuccess) 1993 { 1994 XTRACE(this, 0, ior, "USBSendCommand - Write really failed"); 1995 fpNetStats->outputErrors++; 1996 return ior; 1997 } 1998 } 1999 } 2000 2001 fpNetStats->outputPackets++; 2002 2003 return ior; 2004 2005}/* end USBSendCommand */ 2006 2007/****************************************************************************************************/ 2008// 2009// Method: AppleUSBCDCEEM::clearPipeStall 2010// 2011// Inputs: thePipe - the pipe 2012// 2013// Outputs: 2014// 2015// Desc: Clear a stall on the specified pipe. 2016// 2017/****************************************************************************************************/ 2018 2019IOReturn AppleUSBCDCEEM::clearPipeStall(IOUSBPipe *thePipe) 2020{ 2021 IOReturn rtn = kIOReturnSuccess; 2022 2023 XTRACE(this, 0, 0, "clearPipeStall"); 2024 2025 rtn = thePipe->GetPipeStatus(); 2026 if (rtn == kIOUSBPipeStalled) 2027 { 2028 rtn = thePipe->ClearPipeStall(true); 2029 if (rtn == kIOReturnSuccess) 2030 { 2031 XTRACE(this, 0, 0, "clearPipeStall - Successful"); 2032 } else { 2033 XTRACE(this, 0, rtn, "clearPipeStall - Failed"); 2034 } 2035 } else { 2036 XTRACE(this, 0, 0, "clearPipeStall - Pipe not stalled"); 2037 } 2038 2039 return rtn; 2040 2041}/* end clearPipeStall */ 2042 2043/****************************************************************************************************/ 2044// 2045// Method: AppleUSBCDCEEM::receivePacket 2046// 2047// Inputs: packet - the packet 2048// size - Number of bytes in the packet 2049// 2050// Outputs: 2051// 2052// Desc: Build the mbufs and then send to the network stack. 2053// 2054/****************************************************************************************************/ 2055 2056void AppleUSBCDCEEM::receivePacket(UInt8 *packet, UInt32 size) 2057{ 2058 mbuf_t m; 2059 UInt32 submit; 2060 2061 XTRACE(this, 0, size, "receivePacket"); 2062 2063 if (size > fMax_Block_Size) 2064 { 2065 XTRACE(this, 0, 0, "receivePacket - Packet size error, packet dropped"); 2066 fpNetStats->inputErrors++; 2067 return; 2068 } 2069 2070 m = allocatePacket(size); 2071 if (m) 2072 { 2073 bcopy(packet, mbuf_data(m), size); 2074 submit = fNetworkInterface->inputPacket(m, size); 2075 XTRACE(this, 0, submit, "receivePacket - Packets submitted"); 2076 fpNetStats->inputPackets++; 2077 } else { 2078 XTRACE(this, 0, 0, "receivePacket - Buffer allocation failed, packet dropped"); 2079 fpNetStats->inputErrors++; 2080 } 2081 2082}/* end receivePacket */ 2083 2084/****************************************************************************************************/ 2085// 2086// Method: AppleUSBCDCEEM::processEEMCommand 2087// 2088// Inputs: EEMHeader - the EEM packet header 2089// poolIndx - Index into the buffer pool 2090// dataIndx - Index into the buffer for the current command 2091// 2092// Outputs: len - actual length of the command 2093// 2094// Desc: Handle the EEM command. 2095// 2096/****************************************************************************************************/ 2097 2098void AppleUSBCDCEEM::processEEMCommand(UInt16 EEMHeader, UInt32 poolIndx, SInt16 dataIndx, SInt16 *len) 2099{ 2100 IOReturn rtn = kIOReturnSuccess; 2101 UInt16 EEMCommand; 2102 UInt16 param; 2103 UInt8 *buff = NULL; 2104 2105 XTRACE(this, EEMHeader, poolIndx, "processEEMCommand"); 2106 2107 EEMCommand = EEMHeader & bmEEMCmdMask; 2108 param = EEMHeader & bmEEMCmdParamMask; 2109 2110 switch (EEMCommand) 2111 { 2112 case EEMEcho: 2113 XTRACE(this, EEMCommand, param, "processEEMCommand - Echo"); 2114 if (param != 0) 2115 { 2116 buff = &fPipeInBuff[poolIndx].pipeInBuffer[2]; 2117 } 2118 rtn = USBSendCommand(EEMEchoResponse, param, buff); 2119 if (rtn != kIOReturnSuccess) 2120 { 2121 XTRACE(this, 0, rtn, "processEEMCommand - Failed to send echo response"); 2122 } 2123 *len = param + 2; 2124 break; 2125 case EEMEchoResponse: 2126 XTRACE(this, EEMCommand, param, "processEEMCommand - Echo Response"); 2127 2128 *len = param + 2; 2129 break; 2130 case EEMSuspendHint: 2131 XTRACE(this, EEMCommand, param, "processEEMCommand - Suspend Hint"); 2132 2133 *len = 2; 2134 break; 2135 case EEMResponseHint: 2136 XTRACE(this, EEMCommand, param, "processEEMCommand - Response Hint"); 2137 2138 *len = 2; 2139 break; 2140 case EEMResponseCompleteHint: 2141 XTRACE(this, EEMCommand, param, "processEEMCommand - Response Hint Complete"); 2142 2143 *len = 2; 2144 break; 2145 case EEMTickle: 2146 XTRACE(this, EEMCommand, param, "processEEMCommand - Tickle"); 2147 2148 *len = 2; 2149 break; 2150 default: 2151 XTRACE(this, EEMCommand, param, "processEEMCommand - unknown command"); 2152 *len = 2; 2153 break; 2154 } 2155 2156}/* end processEEMCommand */ 2157 2158/****************************************************************************************************/ 2159// 2160// Method: AppleUSBCDCEEM::message 2161// 2162// Inputs: type - message type 2163// provider - my provider 2164// argument - additional parameters 2165// 2166// Outputs: return Code - kIOReturnSuccess 2167// 2168// Desc: Handles IOKit messages. 2169// 2170/****************************************************************************************************/ 2171 2172IOReturn AppleUSBCDCEEM::message(UInt32 type, IOService *provider, void *argument) 2173{ 2174 UInt16 i; 2175 IOReturn ior; 2176 2177 XTRACE(this, 0, type, "message"); 2178 2179 switch (type) 2180 { 2181 case kIOMessageServiceIsTerminated: 2182 XTRACE(this, fReady, type, "message - kIOMessageServiceIsTerminated"); 2183 2184 if (fReady) 2185 { 2186 if (!fTerminate) // Check if we're already being terminated 2187 { 2188#if 0 2189 // NOTE! This call below depends on the hard coded path of this KEXT. Make sure 2190 // that if the KEXT moves, this path is changed! 2191 KUNCUserNotificationDisplayNotice( 2192 0, // Timeout in seconds 2193 0, // Flags (for later usage) 2194 "", // iconPath (not supported yet) 2195 "", // soundPath (not supported yet) 2196 "/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBCDCEEM.kext", // localizationPath 2197 "Unplug Header", // the header 2198 "Unplug Notice", // the notice - look in Localizable.strings 2199 "OK"); 2200#endif 2201 } 2202 } 2203 2204 releaseResources(); 2205 if (fDataInterface) 2206 { 2207 fDataInterface->close(this); 2208 fDataInterface->release(); 2209 fDataInterface = NULL; 2210 } 2211 fTerminate = true; // we're being terminated (unplugged) 2212 fLinkStatus = 0; // and of course we're offline 2213 return kIOReturnSuccess; 2214 case kIOMessageServiceIsSuspended: 2215 XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended"); 2216 break; 2217 case kIOMessageServiceIsResumed: 2218 XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed"); 2219 break; 2220 case kIOMessageServiceIsRequestingClose: 2221 XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose"); 2222 break; 2223 case kIOMessageServiceWasClosed: 2224 XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed"); 2225 break; 2226 case kIOMessageServiceBusyStateChange: 2227 XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange"); 2228 break; 2229 case kIOUSBMessagePortHasBeenResumed: 2230 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed"); 2231 for (i=0; i<fInBufPool; i++) 2232 { 2233 if (fPipeInBuff[i].dead) // If it's dead try and resurrect it 2234 { 2235 ior = fInPipe->Read(fPipeInBuff[i].pipeInMDP, &fPipeInBuff[i].readCompletionInfo, NULL); 2236 if (ior != kIOReturnSuccess) 2237 { 2238 XTRACE(this, 0, ior, "message - Read io error"); 2239 } else { 2240 fPipeInBuff[i].dead = false; 2241 } 2242 } 2243 } 2244 return kIOReturnSuccess; 2245 case kIOUSBMessageHubResumePort: 2246 XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort"); 2247 break; 2248 default: 2249 XTRACE(this, 0, type, "message - unknown message"); 2250 break; 2251 } 2252 2253 return super::message(type, provider, argument); 2254 2255}/* end message */