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