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 /* AppleUSBCDCACMControl.cpp - MacOSX implementation of */ 26 /* USB Communication Device Class (CDC) Driver, ACM Control Interface. */ 27 28#include <machine/limits.h> /* UINT_MAX */ 29#include <libkern/OSByteOrder.h> 30 31#include <IOKit/assert.h> 32#include <IOKit/IOLib.h> 33#include <IOKit/IOService.h> 34#include <IOKit/IOBufferMemoryDescriptor.h> 35#include <IOKit/IOMessage.h> 36 37#include <IOKit/pwr_mgt/RootDomain.h> 38 39#if !TARGET_OS_IPHONE 40#include <IOKit/usb/IOUSBBus.h> 41#endif /* TARGET_OS_IPHONE */ 42 43#include <IOKit/usb/IOUSBNub.h> 44#include <IOKit/usb/IOUSBDevice.h> 45#include <IOKit/usb/IOUSBLog.h> 46#include <IOKit/usb/IOUSBPipe.h> 47#include <IOKit/usb/USB.h> 48#include <IOKit/usb/IOUSBInterface.h> 49 50#include <IOKit/serial/IOSerialKeys.h> 51#include <IOKit/serial/IOSerialDriverSync.h> 52#include <IOKit/serial/IOModemSerialStreamSync.h> 53#include <IOKit/serial/IORS232SerialStreamSync.h> 54 55#include <UserNotification/KUNCUserNotifications.h> 56 57#define DEBUG_NAME "AppleUSBCDCACMControl" 58 59#include "AppleUSBCDCACM.h" 60#include "AppleUSBCDCACMControl.h" 61 62#define MIN_BAUD (50 << 1) 63 64 // Globals 65 66//AppleUSBCDCACMData *gDataDriver = NULL; 67 68static IOPMPowerState gOurPowerStates[kNumCDCStates] = 69{ 70 {1,0,0,0,0,0,0,0,0,0,0,0}, 71 {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0} 72}; 73 74#define super IOService 75 76OSDefineMetaClassAndStructors(AppleUSBCDCACMControl, IOService); 77 78/****************************************************************************************************/ 79// 80// Function: findCDCDriverAC 81// 82// Inputs: controlAddr - my address 83// 84// Outputs: 85// 86// Desc: Finds the initiating CDC driver 87// 88/****************************************************************************************************/ 89 90AppleUSBCDC *findCDCDriverAC(void *controlAddr, IOReturn *retCode) 91{ 92 AppleUSBCDCACMControl *me = (AppleUSBCDCACMControl *)controlAddr; 93 AppleUSBCDC *CDCDriver = NULL; 94 bool driverOK = false; 95 OSIterator *iterator = NULL; 96 OSDictionary *matchingDictionary = NULL; 97 98 XTRACE(me, 0, 0, "findCDCDriverAC"); 99 100 // Get matching dictionary 101 102 matchingDictionary = IOService::serviceMatching("AppleUSBCDC"); 103 if (!matchingDictionary) 104 { 105 XTRACE(me, 0, 0, "findCDCDriverAC - Couldn't create a matching dictionary"); 106 *retCode = kIOReturnError; 107 return NULL; 108 } 109 110 // Get an iterator 111 112 iterator = IOService::getMatchingServices(matchingDictionary); 113 if (!iterator) 114 { 115 XTRACE(me, 0, 0, "findCDCDriverAC - No AppleUSBCDC driver found!"); 116 matchingDictionary->release(); 117 *retCode = kIOReturnError; 118 return NULL; 119 } 120 121 // Iterate until we find our matching CDC driver 122 123 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 124 while (CDCDriver) 125 { 126 XTRACEP(me, 0, CDCDriver, "findCDCDriverAC - CDC driver candidate"); 127 128 if (me->fControlInterface->GetDevice() == CDCDriver->getCDCDevice()) 129 { 130 XTRACEP(me, 0, CDCDriver, "findCDCDriverAC - Found our CDC driver"); 131 driverOK = CDCDriver->confirmControl(kUSBAbstractControlModel, me->fControlInterface); 132 break; 133 } 134 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 135 } 136 137 matchingDictionary->release(); 138 iterator->release(); 139 140 if (!CDCDriver) 141 { 142 XTRACE(me, 0, 0, "findCDCDriverAC - CDC driver not found"); 143 *retCode = kIOReturnNotReady; 144 return NULL; 145 } 146 147 if (!driverOK) 148 { 149 XTRACE(me, kUSBAbstractControlModel, 0, "findCDCDriverAC - Not my interface"); 150 *retCode = kIOReturnError; 151 return NULL; 152 } 153 154 *retCode = kIOReturnSuccess; 155 156 return CDCDriver; 157 158}/* end findCDCDriverAC */ 159 160 // Encode the 4 modem status bits (so we only make one call to setState) 161 162#if 0 163static UInt32 sMapModemStates[16] = 164{ 165 0 | 0 | 0 | 0, // 0000 166 0 | 0 | 0 | PD_RS232_S_DCD, // 0001 167 0 | 0 | PD_RS232_S_DSR | 0, // 0010 168 0 | 0 | PD_RS232_S_DSR | PD_RS232_S_DCD, // 0011 169 0 | PD_RS232_S_BRK | 0 | 0, // 0100 170 0 | PD_RS232_S_BRK | 0 | PD_RS232_S_DCD, // 0101 171 0 | PD_RS232_S_BRK | PD_RS232_S_DSR | 0, // 0110 172 0 | PD_RS232_S_BRK | PD_RS232_S_DSR | PD_RS232_S_DCD, // 0111 173 PD_RS232_S_RNG | 0 | 0 | 0, // 1000 174 PD_RS232_S_RNG | 0 | 0 | PD_RS232_S_DCD, // 1001 175 PD_RS232_S_RNG | 0 | PD_RS232_S_DSR | 0, // 1010 176 PD_RS232_S_RNG | 0 | PD_RS232_S_DSR | PD_RS232_S_DCD, // 1011 177 PD_RS232_S_RNG | PD_RS232_S_BRK | 0 | 0, // 1100 178 PD_RS232_S_RNG | PD_RS232_S_BRK | 0 | PD_RS232_S_DCD, // 1101 179 PD_RS232_S_RNG | PD_RS232_S_BRK | PD_RS232_S_DSR | 0, // 1110 180 PD_RS232_S_RNG | PD_RS232_S_BRK | PD_RS232_S_DSR | PD_RS232_S_DCD, // 1111 181}; 182#endif 183 184/****************************************************************************************************/ 185// 186// Method: AppleUSBCDCACMControl::commReadComplete 187// 188// Inputs: obj - me 189// rc - return code 190// remaining - what's left 191// 192// Outputs: None 193// 194// Desc: Interrupt pipe (Comm interface) read completion routine 195// 196/****************************************************************************************************/ 197 198void AppleUSBCDCACMControl::commReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 199{ 200 AppleUSBCDCACMControl *me = (AppleUSBCDCACMControl*)obj; 201 IOReturn ior; 202 UInt32 dLen; 203 UInt16 *tState; 204 UInt32 tempS, value, mask; 205 206 XTRACE(me, rc, 0, "commReadComplete"); 207 208 if (me->fStopping) 209 return; 210 211 if (rc == kIOReturnSuccess) // If operation returned ok 212 { 213 dLen = COMM_BUFF_SIZE - remaining; 214 XTRACE(me, 0, dLen, "commReadComplete - data length"); 215 216 // Now look at the state stuff 217 218 if ((dLen > 7) && (me->fCommPipeBuffer[1] == kUSBSERIAL_STATE)) 219 { 220 tState = (UInt16 *)&me->fCommPipeBuffer[8]; 221 tempS = USBToHostWord(*tState); 222 XTRACE(me, 0, tempS, "commReadComplete - kUSBSERIAL_STATE"); 223 if (tempS & kUSBbRxCarrier) 224 { 225 value = PD_RS232_S_DCD; 226 mask = PD_RS232_S_DCD; 227 } 228 if (tempS & kUSBbTxCarrier) 229 { 230 value |= PD_RS232_S_DSR; 231 mask |= PD_RS232_S_DSR; 232 } 233 if (tempS & kUSBbBreak) 234 { 235 value |= PD_RS232_S_BRK; 236 mask |= PD_RS232_S_BRK; 237 } 238 if (tempS & kUSBbRingSignal) 239 { 240 value |= PD_RS232_S_RNG; 241 mask |= PD_RS232_S_RNG; 242 } 243 244// mask = sMapModemStates[15]; // All 4 on 245// value = sMapModemStates[tempS & 15]; // now the status bits 246 if (me->fDataDriver) 247 { 248 me->fDataDriver->setState(value, mask, NULL); 249 } 250 } else { 251 XTRACE(me, 0, me->fCommPipeBuffer[1], "commReadComplete - Unhandled notification"); 252 } 253 } else { 254 XTRACE(me, 0, rc, "commReadComplete - error"); 255 if (rc != kIOReturnAborted) 256 { 257 if ((rc == kIOUSBPipeStalled) || (rc = kIOUSBHighSpeedSplitError)) 258 { 259 rc = me->checkPipe(me->fCommPipe, true); 260 } else { 261 rc = me->checkPipe(me->fCommPipe, false); 262 } 263 if (rc != kIOReturnSuccess) 264 { 265 XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)"); 266 } 267 } 268 } 269 270 // Queue the next read only if not aborted 271 272 if (rc != kIOReturnAborted) 273 { 274 ior = me->fCommPipe->Read(me->fCommPipeMDP, &me->fCommCompletionInfo, NULL); 275 if (ior != kIOReturnSuccess) 276 { 277 XTRACE(me, 0, rc, "commReadComplete - Read io error"); 278 me->fReadDead = true; 279 } 280 } else { 281 me->fReadDead = true; 282 } 283 284}/* end commReadComplete */ 285 286/****************************************************************************************************/ 287// 288// Method: AppleUSBCDCACMControl::merWriteComplete 289// 290// Inputs: obj - me 291// param - MER 292// rc - return code 293// remaining - what's left 294// 295// Outputs: None 296// 297// Desc: Management Element Request write completion routine 298// 299/****************************************************************************************************/ 300 301void AppleUSBCDCACMControl::merWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 302{ 303 AppleUSBCDCACMControl *me = (AppleUSBCDCACMControl *)obj; 304 IOUSBDevRequest *MER = (IOUSBDevRequest *)param; 305 UInt16 dataLen; 306 307 XTRACE(me, 0, remaining, "merWriteComplete"); 308 309 if (me->fStopping) 310 { 311 if (MER) 312 { 313 dataLen = MER->wLength; 314 if ((dataLen != 0) && (MER->pData)) 315 { 316 IOFree(MER->pData, dataLen); 317 } 318 IOFree(MER, sizeof(IOUSBDevRequest)); 319 } 320 return; 321 } 322 323 if (MER) 324 { 325 if (rc == kIOReturnSuccess) 326 { 327 XTRACE(me, MER->bRequest, remaining, "merWriteComplete - request"); 328 } else { 329 XTRACE(me, MER->bRequest, rc, "merWriteComplete - io err"); 330 if ((rc == kIOUSBPipeStalled) || (rc == kIOUSBHighSpeedSplitError)) 331 { 332 rc = me->checkPipe(me->fCommPipe, false); 333 } 334 } 335 336 dataLen = MER->wLength; 337 XTRACE(me, 0, dataLen, "merWriteComplete - data length"); 338 if ((dataLen != 0) && (MER->pData)) 339 { 340 IOFree(MER->pData, dataLen); 341 } 342 IOFree(MER, sizeof(IOUSBDevRequest)); 343 344 } else { 345 if (rc == kIOReturnSuccess) 346 { 347 XTRACE(me, 0, remaining, "merWriteComplete (request unknown)"); 348 } else { 349 XTRACE(me, 0, rc, "merWriteComplete (request unknown) - io err"); 350 if ((rc == kIOUSBPipeStalled) || (rc == kIOUSBHighSpeedSplitError)) 351 { 352 rc = me->checkPipe(me->fCommPipe, false); 353 } 354 } 355 } 356 357}/* end merWriteComplete */ 358 359/****************************************************************************************************/ 360// 361// Method: AppleUSBCDCACMControl::probe 362// 363// Inputs: provider - my provider 364// 365// Outputs: IOService - from super::probe, score - probe score 366// 367// Desc: Modify the probe score if necessary (we don't at the moment) 368// 369/****************************************************************************************************/ 370 371IOService* AppleUSBCDCACMControl::probe( IOService *provider, SInt32 *score ) 372{ 373 IOService *res; 374 375 // If our IOUSBInterface has a "do not match" property, it means that we should not match and need 376 // to bail. See rdar://3716623 377 378 OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface")); 379 if (boolObj && boolObj->isTrue()) 380 { 381 XTRACE(this, 0, 0, "probe - provider doesn't want us to match"); 382 return NULL; 383 } 384 385 res = super::probe(provider, score); 386 387 return res; 388 389}/* end probe */ 390 391/****************************************************************************************************/ 392// 393// Method: AppleUSBCDCACMControl::start 394// 395// Inputs: provider - my provider 396// 397// Outputs: Return code - true (it's me), false (sorry it probably was me, but I can't configure it) 398// 399// Desc: This is called once it has beed determined I'm probably the best 400// driver for this interface. 401// 402/****************************************************************************************************/ 403 404bool AppleUSBCDCACMControl::start(IOService *provider) 405{ 406 IOReturn rtn; 407 UInt16 devDriverCount = 0; 408 409 fTerminate = false; 410 fStopping = false; 411 fdataAcquired = false; 412 fCDCDriver = NULL; 413 fCommPipeMDP = NULL; 414 fCommPipe = NULL; 415 fCommPipeBuffer = NULL; 416 fReadDead = false; 417 418 XTRACE(this, 0, 0, "start"); 419 420 if(!super::start(provider)) 421 { 422 ALERT(0, 0, "start - super failed"); 423 return false; 424 } 425 426 // Get my USB provider - the interface 427 428 fControlInterface = OSDynamicCast(IOUSBInterface, provider); 429 if(!fControlInterface) 430 { 431 ALERT(0, 0, "start - provider invalid"); 432 return false; 433 } 434 435 // See if we can find/wait for the CDC driver 436 437 while (!fCDCDriver) 438 { 439 rtn = kIOReturnSuccess; 440 fCDCDriver = findCDCDriverAC(this, &rtn); 441 if (fCDCDriver) 442 { 443 XTRACE (this, 0, fControlInterface->GetInterfaceNumber(), "start: Found the CDC device driver"); 444 break; 445 } else { 446 if (rtn == kIOReturnNotReady) 447 { 448 devDriverCount++; 449 XTRACE(this, devDriverCount, fControlInterface->GetInterfaceNumber(), "start - Waiting for CDC device driver..."); 450 if (devDriverCount > 9) 451 { 452 break; 453 } 454 IOSleep(100); 455 } else { 456 break; 457 } 458 } 459 } 460 461 // If we didn't find him then we have to bail 462 463 if (!fCDCDriver) 464 { 465 ALERT(0, fControlInterface->GetInterfaceNumber(), "start - Failed to find the CDC driver"); 466 return false; 467 } 468 469 if (!configureACM()) 470 { 471 ALERT(0, 0, "start - configureACM failed"); 472 return false; 473 } 474 475 if (!allocateResources()) 476 { 477 fControlInterface = NULL; //rs Since we did not retain it as yet. 478 ALERT(0, 0, "start - allocateResources failed"); 479 releaseResources(); 480 return false; 481 } 482 483 if (!initForPM(provider)) 484 { 485 ALERT(0, 0, "start - initForPM failed"); 486 releaseResources(); 487 return false; 488 } 489 490 fControlInterface->retain(); 491 492 registerService(); 493 494 XTRACE(this, 0, 0, "start - successful"); 495 496 return true; 497 498}/* end start */ 499 500/****************************************************************************************************/ 501// 502// Method: AppleUSBCDCACMControl::stop 503// 504// Inputs: provider - my provider 505// 506// Outputs: None 507// 508// Desc: Stops the driver 509// 510/****************************************************************************************************/ 511 512void AppleUSBCDCACMControl::stop(IOService *provider) 513{ 514 515 XTRACE(this, 0, 0, "stop"); 516 517 fStopping = true; 518 519 if (!fTerminate) // If we're terminated this has already been done 520 { 521 releaseResources(); 522 } 523 524 PMstop(); 525 526 super::stop(provider); 527 528 XTRACE(this, 0, 0, "stop - Exit"); 529 530}/* end stop */ 531 532/****************************************************************************************************/ 533// 534// Method: AppleUSBCDCACMControl::configureACM 535// 536// Inputs: 537// 538// Outputs: return Code - true (configured), false (not configured) 539// 540// Desc: Configures the Abstract Control Model interface etc. 541// 542/****************************************************************************************************/ 543 544bool AppleUSBCDCACMControl::configureACM() 545{ 546 UInt8 protocol; 547 548 XTRACE(this, 0, 0, "configureACM"); 549 550 fCommInterfaceNumber = fControlInterface->GetInterfaceNumber(); 551 XTRACE(this, 0, fCommInterfaceNumber, "configureACM - Comm interface number."); 552 553 protocol = fControlInterface->GetInterfaceProtocol(); 554 if (protocol == kUSBVendorSpecificProtocol) 555 { 556 ALERT(fCommInterfaceNumber, protocol, "configureACM - ACM Control interface has vendor specific protocol"); 557 return false; 558 } 559 560 if (!getFunctionalDescriptors()) 561 { 562 XTRACE(this, 0, 0, "configureACM - getFunctionalDescriptors failed"); 563 return false; 564 } 565 566 return true; 567 568}/* end configureACM */ 569 570/****************************************************************************************************/ 571// 572// Method: AppleUSBCDCACMControl::getFunctionalDescriptors 573// 574// Inputs: 575// 576// Outputs: return - true (descriptors ok), false (somethings not right or not supported) 577// 578// Desc: Finds all the functional descriptors for the specific interface 579// 580/****************************************************************************************************/ 581 582bool AppleUSBCDCACMControl::getFunctionalDescriptors() 583{ 584 bool gotDescriptors = false; 585 UInt16 vers; 586 UInt16 *hdrVers; 587 const FunctionalDescriptorHeader *funcDesc = NULL; 588 HDRFunctionalDescriptor *HDRFDesc; // hearder functional descriptor 589 CMFunctionalDescriptor *CMFDesc; // call management functional descriptor 590 ACMFunctionalDescriptor *ACMFDesc; // abstract control management functional descriptor 591 UnionFunctionalDescriptor *UNNFDesc; // union functional descriptor 592// AppleUSBCDC *CDCDriver = NULL; 593 594 XTRACE(this, 0, 0, "getFunctionalDescriptors"); 595 596 // Set some defaults just in case and then get the associated functional descriptors 597 598 fCMCapabilities = CM_ManagementData + CM_ManagementOnData; 599 fACMCapabilities = ACM_DeviceSuppControl + ACM_DeviceSuppBreak; 600 fDataInterfaceNumber = 0xFF; 601 602 do 603 { 604 funcDesc = (const FunctionalDescriptorHeader *)fControlInterface->FindNextAssociatedDescriptor((void*)funcDesc, CS_INTERFACE); 605 if (!funcDesc) 606 { 607 gotDescriptors = true; // We're done 608 } else { 609 switch (funcDesc->bDescriptorSubtype) 610 { 611 case Header_FunctionalDescriptor: 612 HDRFDesc = (HDRFunctionalDescriptor *)funcDesc; 613 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Header Functional Descriptor"); 614 hdrVers = (UInt16 *)&HDRFDesc->bcdCDC1; 615 vers = USBToHostWord(*hdrVers); 616 if (vers > kUSBRel11) 617 { 618 XTRACE(this, vers, kUSBRel11, "getFunctionalDescriptors - Header descriptor version number is incorrect"); 619 } 620 break; 621 case CM_FunctionalDescriptor: 622 CMFDesc = (CMFunctionalDescriptor *)funcDesc; 623 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - CM Functional Descriptor"); 624 if (fDataInterfaceNumber != 0xFF) 625 { 626 if (fDataInterfaceNumber != CMFDesc->bDataInterface) 627 { 628 XTRACE(this, fDataInterfaceNumber, CMFDesc->bDataInterface, "getFunctionalDescriptors - CMF and UNNF disagree"); 629 } 630 } 631 if (CMFDesc->bmCapabilities & CM_ManagementData) 632 { 633 fDataInterfaceNumber = CMFDesc->bDataInterface; // This will be the default if CM on data is set 634 } 635 fCMCapabilities = CMFDesc->bmCapabilities; 636 637 // Check the configuration supports data management on the data interface (that's all we support) 638 639 XTRACE(this, 0, CMFDesc->bmCapabilities, "getFunctionalDescriptors - CMFDesc->bmCapabilities"); 640 641 if (!(fCMCapabilities & CM_ManagementData)) 642 { 643 XTRACE(this, 0, 0, "getFunctionalDescriptors - Interface doesn't support Call Management"); 644 // return false; // We'll relax this check too 645 } 646 if (!(fCMCapabilities & CM_ManagementOnData)) 647 { 648 XTRACE(this, 0, 0, "getFunctionalDescriptors - Interface doesn't support Call Management on Data Interface"); 649 // return false; // Some devices get this wrong so we'll let it slide 650 } 651 break; 652 case ACM_FunctionalDescriptor: 653 ACMFDesc = (ACMFunctionalDescriptor *)funcDesc; 654 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - ACM Functional Descriptor"); 655 fACMCapabilities = ACMFDesc->bmCapabilities; 656 break; 657 case Union_FunctionalDescriptor: 658 UNNFDesc = (UnionFunctionalDescriptor *)funcDesc; 659 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Union Functional Descriptor"); 660 if (UNNFDesc->bFunctionLength > sizeof(FunctionalDescriptorHeader)) 661 { 662 if (fCommInterfaceNumber != UNNFDesc->bMasterInterface) 663 { 664 XTRACE(this, fCommInterfaceNumber, UNNFDesc->bMasterInterface, "getFunctionalDescriptors - Master interface incorrect"); 665 } 666 667 if (fDataInterfaceNumber == 0xFF) 668 { 669 fDataInterfaceNumber = UNNFDesc->bSlaveInterface[0]; // Use the first slave (may get overwritten by CMF) 670 } 671 if (fDataInterfaceNumber != UNNFDesc->bSlaveInterface[0]) 672 { 673 XTRACE(this, fDataInterfaceNumber, UNNFDesc->bSlaveInterface[1], "getFunctionalDescriptors - Slave interface incorrect"); 674 } 675 } else { 676 XTRACE(this, UNNFDesc->bFunctionLength, 0, "getFunctionalDescriptors - Union descriptor length error"); 677 } 678 break; 679 case CS_FunctionalDescriptor: 680 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - CS Functional Descriptor"); 681 break; 682 default: 683 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - unknown Functional Descriptor"); 684 break; 685 } 686 } 687 } while(!gotDescriptors); 688 689 // If we get this far and actually have a data interface number we're good to go (maybe...) 690 // If not ask the CDC driver if there's only one data interface so we can assume that one 691 692 if (fDataInterfaceNumber == 0xFF) 693 { 694 XTRACE(this, 0, 0, "getFunctionalDescriptors - No data interface specified"); 695// fCDCDriver = findCDCDriverAC(this); 696 if (fCDCDriver) 697 { 698 if (fCDCDriver->fDataInterfaceNumber != 0xFF) 699 { 700 fDataInterfaceNumber = fCDCDriver->fDataInterfaceNumber; 701 XTRACE(this, fACMCapabilities, fDataInterfaceNumber, "getFunctionalDescriptors - Data interface number (assumed from CDC driver)"); 702 } else { 703 return false; 704 } 705 } else { 706 return false; 707 } 708 } else { 709 XTRACE(this, fACMCapabilities, fDataInterfaceNumber, "getFunctionalDescriptors - Data interface number"); 710 711 // If these two are equal then this is probably the Conexant Functional descriptor problem 712 713 if (fCommInterfaceNumber == fDataInterfaceNumber) 714 { 715 ALERT(fCommInterfaceNumber, fDataInterfaceNumber, "getFunctionalDescriptors - Descriptors are incorrect, checking..."); 716 if (UNNFDesc) 717 { 718 fDataInterfaceNumber = UNNFDesc->bMasterInterface; 719 } else { 720 ALERT(fCommInterfaceNumber, fDataInterfaceNumber, "getFunctionalDescriptors - unable to continue"); 721 return false; 722 } 723 } 724 } 725 726 return true; 727 728}/* end getFunctionalDescriptors */ 729 730/****************************************************************************************************/ 731// 732// Method: AppleUSBCDCACMControl::dataAcquired 733// 734// Inputs: None 735// 736// Outputs: return Code - true (it worked), false (it didn't) 737// 738// Desc: Tells this driver the data driver's port has been acquired 739// 740/****************************************************************************************************/ 741 742bool AppleUSBCDCACMControl::dataAcquired() 743{ 744 IOReturn rtn = kIOReturnSuccess; 745 746 XTRACE(this, 0, 0, "dataAcquired"); 747 748 // Read the comm interrupt pipe for status 749 750 fCommCompletionInfo.target = this; 751 fCommCompletionInfo.action = commReadComplete; 752 fCommCompletionInfo.parameter = NULL; 753 754 rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL); 755 if (rtn == kIOReturnSuccess) 756 { 757 758 // Set up the management Element Request completion routine 759 760 fMERCompletionInfo.target = this; 761 fMERCompletionInfo.action = merWriteComplete; 762 fMERCompletionInfo.parameter = NULL; 763 } else { 764 XTRACE(this, 0, rtn, "dataAcquired - Reading the interrupt pipe failed"); 765 return false; 766 } 767 768 fdataAcquired = true; 769 return true; 770 771}/* end dataAcquired */ 772 773/****************************************************************************************************/ 774// 775// Method: AppleUSBCDCACMControl::dataReleased 776// 777// Inputs: None 778// 779// Outputs: None 780// 781// Desc: Tells this driver the data driver's port has been released 782// 783/****************************************************************************************************/ 784 785void AppleUSBCDCACMControl::dataReleased() 786{ 787 788 XTRACE(this, 0, 0, "dataReleased"); 789 790 if (fCommPipe) 791 { 792 fCommPipe->Abort(); 793 } 794 fdataAcquired = false; 795 796}/* end dataReleased */ 797 798/****************************************************************************************************/ 799// 800// Method: AppleUSBCDCACMControl::USBSendSetLineCoding 801// 802// Inputs: The line coding parameters 803// 804// Outputs: 805// 806// Desc: Set up and send SetLineCoding Management Element Request(MER) for all settings. 807// 808/****************************************************************************************************/ 809 810void AppleUSBCDCACMControl::USBSendSetLineCoding(UInt32 BaudRate, UInt8 StopBits, UInt8 TX_Parity, UInt8 CharLength) 811{ 812 LineCoding *lineParms; 813 UInt16 lcLen = sizeof(LineCoding)-1; 814 IOUSBDevRequest *MER; 815 IOReturn rc; 816 817 XTRACE(this, 0, 0, "USBSendSetLineCoding"); 818 819 if (!fControlInterface) 820 { 821 XTRACE(this, 0, 0, "USBSendSetLineCoding - Control interface has gone"); 822 return; 823 } 824 825 // First check that Set Line Coding is supported 826 827 if (!(fACMCapabilities & ACM_DeviceSuppControl)) 828 { 829 XTRACE(this, 0, 0, "USBSendSetLineCoding - SetLineCoding not supported"); 830 return; 831 } 832 833 lineParms = (LineCoding *)IOMalloc(lcLen); 834 if (!lineParms) 835 { 836 XTRACE(this, 0, 0, "USBSendSetLineCoding - allocate lineParms failed"); 837 return; 838 } 839 bzero(lineParms, lcLen); 840 841 // Convert BaudRate - intel format doubleword (32 bits) 842 843 OSWriteLittleInt32(lineParms, dwDTERateOffset, BaudRate); 844 lineParms->bCharFormat = StopBits - 2; 845 lineParms->bParityType = TX_Parity - 1; 846 lineParms->bDataBits = CharLength; 847 848 MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest)); 849 if (!MER) 850 { 851 XTRACE(this, 0, 0, "USBSendSetLineCoding - allocate MER failed"); 852 return; 853 } 854 bzero(MER, sizeof(IOUSBDevRequest)); 855 856 // now build the Management Element Request 857 858 MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface); 859 MER->bRequest = kUSBSET_LINE_CODING; 860 MER->wValue = 0; 861 MER->wIndex = fCommInterfaceNumber; 862 MER->wLength = lcLen; 863 MER->pData = lineParms; 864 865 fMERCompletionInfo.parameter = MER; 866 867 rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo); 868 if (rc != kIOReturnSuccess) 869 { 870 XTRACE(this, MER->bRequest, rc, "USBSendSetLineCoding - error issueing DeviceRequest"); 871 IOFree(MER->pData, lcLen); 872 IOFree(MER, sizeof(IOUSBDevRequest)); 873 } 874 875}/* end USBSendSetLineCoding */ 876 877/****************************************************************************************************/ 878// 879// Method: AppleUSBCDCACMControl::USBSendSetControlLineState 880// 881// Inputs: RTS - true(set RTS), false(clear RTS) 882// DTR - true(set DTR), false(clear DTR) 883// 884// Outputs: 885// 886// Desc: Set up and send SetControlLineState Management Element Request(MER). 887// 888/****************************************************************************************************/ 889 890void AppleUSBCDCACMControl::USBSendSetControlLineState(bool RTS, bool DTR) 891{ 892 IOReturn rc; 893 IOUSBDevRequest *MER; 894 UInt16 CSBitmap = 0; 895 896 XTRACE(this, 0, 0, "USBSendSetControlLineState"); 897 898 if (!fControlInterface) 899 { 900 XTRACE(this, 0, 0, "USBSendSetControlLineState - Control interface has gone"); 901 return; 902 } 903 904 // First check that Set Control Line State is supported 905 906 if (!(fACMCapabilities & ACM_DeviceSuppControl)) 907 { 908 XTRACE(this, 0, 0, "USBSendSetControlLineState - SetControlLineState not supported"); 909 return; 910 } 911 912 MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest)); 913 if (!MER) 914 { 915 XTRACE(this, 0, 0, "USBSendSetControlLineState - allocate MER failed"); 916 return; 917 } 918 bzero(MER, sizeof(IOUSBDevRequest)); 919 920 // now build the Management Element Request 921 922 MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface); 923 MER->bRequest = kUSBSET_CONTROL_LINE_STATE; 924 if (RTS) 925 CSBitmap |= kRTSOn; 926 if (DTR) 927 CSBitmap |= kDTROn; 928 MER->wValue = CSBitmap; 929 MER->wIndex = fCommInterfaceNumber; 930 MER->wLength = 0; 931 MER->pData = NULL; 932 933 fMERCompletionInfo.parameter = MER; 934 935 rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo); 936 if (rc != kIOReturnSuccess) 937 { 938 XTRACE(this, MER->bRequest, rc, "USBSendSetControlLineState - error issueing DeviceRequest"); 939 IOFree(MER, sizeof(IOUSBDevRequest)); 940 } 941 942}/* end USBSendSetControlLineState */ 943 944/****************************************************************************************************/ 945// 946// Method: AppleUSBCDCACMControl::USBSendBreak 947// 948// Inputs: sBreak - true(set Break), false(clear Break) 949// 950// Outputs: 951// 952// Desc: Set up and send SendBreak Management Element Request(MER). 953// 954/****************************************************************************************************/ 955 956void AppleUSBCDCACMControl::USBSendBreak(bool sBreak) 957{ 958 IOReturn rc; 959 IOUSBDevRequest *MER; 960 961 XTRACE(this, 0, 0, "USBSendBreak"); 962 963 if (!fControlInterface) 964 { 965 XTRACE(this, 0, 0, "USBSendBreak - Control interface has gone"); 966 return; 967 } 968 969 // First check that Send Break is supported 970 971 if (!(fACMCapabilities & ACM_DeviceSuppBreak)) 972 { 973 XTRACE(this, 0, 0, "USBSendBreak - SendBreak not supported"); 974 return; 975 } 976 977 MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest)); 978 if (!MER) 979 { 980 XTRACE(this, 0, 0, "USBSendBreak - allocate MER failed"); 981 return; 982 } 983 bzero(MER, sizeof(IOUSBDevRequest)); 984 985 // now build the Management Element Request 986 987 MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface); 988 MER->bRequest = kUSBSEND_BREAK; 989 if (sBreak) 990 { 991 MER->wValue = 0xFFFF; 992 } else { 993 MER->wValue = 0; 994 } 995 MER->wIndex = fCommInterfaceNumber; 996 MER->wLength = 0; 997 MER->pData = NULL; 998 999 fMERCompletionInfo.parameter = MER; 1000 1001 rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo); 1002 if (rc != kIOReturnSuccess) 1003 { 1004 XTRACE(this, MER->bRequest, rc, "USBSendBreak - error issueing DeviceRequest"); 1005 IOFree(MER, sizeof(IOUSBDevRequest)); 1006 } 1007 1008}/* end USBSendBreak */ 1009 1010/****************************************************************************************************/ 1011// 1012// Method: AppleUSBCDCACMControl::checkPipe 1013// 1014// Inputs: thePipe - the pipe 1015// devReq - true(send CLEAR_FEATURE), false(only if status returns stalled) 1016// 1017// Outputs: 1018// 1019// Desc: Clear a stall on the specified pipe. If ClearPipeStall is issued 1020// all outstanding I/O is returned with kIOUSBTransactionReturned and 1021// a CLEAR_FEATURE Endpoint stall is sent. 1022// 1023/****************************************************************************************************/ 1024 1025IOReturn AppleUSBCDCACMControl::checkPipe(IOUSBPipe *thePipe, bool devReq) 1026{ 1027 IOReturn rtn = kIOReturnSuccess; 1028 1029 XTRACEP(this, 0, thePipe, "checkPipe"); 1030 1031 if (!devReq) 1032 { 1033 rtn = thePipe->GetPipeStatus(); 1034 if (rtn != kIOUSBPipeStalled) 1035 { 1036 XTRACE(this, 0, 0, "checkPipe - Pipe not stalled"); 1037 return rtn; 1038 } 1039 } 1040 1041 rtn = thePipe->ClearPipeStall(true); 1042 if (rtn == kIOReturnSuccess) 1043 { 1044 XTRACE(this, 0, 0, "checkPipe - ClearPipeStall Successful"); 1045 } else { 1046 XTRACE(this, 0, rtn, "checkPipe - ClearPipeStall Failed"); 1047 } 1048 1049 return rtn; 1050 1051}/* end checkPipe */ 1052 1053/****************************************************************************************************/ 1054// 1055// Method: AppleUSBCDCACMControl::allocateResources 1056// 1057// Inputs: 1058// 1059// Outputs: return code - true (allocate was successful), false (it failed) 1060// 1061// Desc: Finishes up the rest of the configuration and gets all the endpoints open etc. 1062// 1063/****************************************************************************************************/ 1064 1065bool AppleUSBCDCACMControl::allocateResources() 1066{ 1067 IOUSBFindEndpointRequest epReq; 1068 1069 XTRACE(this, 0, 0, "allocateResources."); 1070 1071 // Open the end point and get the buffers 1072 1073 if (!fControlInterface->open(this)) 1074 { 1075 XTRACE(this, 0, 0, "allocateResources - open comm interface failed."); 1076 return false; 1077 } 1078 // Interrupt pipe 1079 1080 epReq.type = kUSBInterrupt; 1081 epReq.direction = kUSBIn; 1082 fCommPipe = fControlInterface->FindNextPipe(0, &epReq); 1083 if (!fCommPipe) 1084 { 1085 XTRACE(this, 0, 0, "allocateResources - no comm pipe."); 1086 return false; 1087 } 1088 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - comm pipe."); 1089 1090 // Allocate Memory Descriptor Pointer with memory for the Interrupt pipe: 1091 1092 fCommPipeMDP = IOBufferMemoryDescriptor::withCapacity(COMM_BUFF_SIZE, kIODirectionIn); 1093 if (!fCommPipeMDP) 1094 { 1095 XTRACE(this, 0, 0, "allocateResources - Couldn't allocate MDP for interrupt pipe"); 1096 return false; 1097 } 1098 1099 fCommPipeBuffer = (UInt8*)fCommPipeMDP->getBytesNoCopy(); 1100 XTRACEP(this, 0, fCommPipeBuffer, "allocateResources - comm buffer"); 1101 1102 return true; 1103 1104}/* end allocateResources */ 1105 1106/****************************************************************************************************/ 1107// 1108// Method: AppleUSBCDCACMControl::releaseResources 1109// 1110// Inputs: 1111// 1112// Outputs: 1113// 1114// Desc: Frees up the resources allocated in allocateResources 1115// 1116/****************************************************************************************************/ 1117 1118void AppleUSBCDCACMControl::releaseResources() 1119{ 1120 XTRACE(this, 0, 0, "releaseResources"); 1121 1122 if (fControlInterface) 1123 { 1124 fControlInterface->close(this); 1125 fControlInterface->release(); 1126 fControlInterface = NULL; 1127 } 1128 1129 if (fCommPipeMDP) 1130 { 1131 fCommPipeMDP->release(); 1132 fCommPipeMDP = 0; 1133 } 1134 1135}/* end releaseResources */ 1136 1137/****************************************************************************************************/ 1138// 1139// Method: AppleUSBCDCACMControl::checkInterfaceNumber 1140// 1141// Inputs: dataDriver - the data driver enquiring 1142// 1143// Outputs: 1144// 1145// Desc: Called by the data driver to ask if this is the correct 1146// control interface driver. 1147// 1148/****************************************************************************************************/ 1149 1150bool AppleUSBCDCACMControl::checkInterfaceNumber(AppleUSBCDCACMData *dataDriver) 1151{ 1152 IOUSBInterface *dataInterface; 1153 1154 XTRACEP(this, 0, dataDriver, "checkInterfaceNumber"); 1155 1156 // First check we have the same provider (Device) 1157 1158 dataInterface = OSDynamicCast(IOUSBInterface, dataDriver->getProvider()); 1159 if (dataInterface == NULL) 1160 { 1161 XTRACE(this, 0, 0, "checkInterfaceNumber - Error getting Data provider"); 1162 return FALSE; 1163 } 1164 1165 XTRACEP(this, dataInterface->GetDevice(), fControlInterface->GetDevice(), "checkInterfaceNumber - Checking device"); 1166 if (dataInterface->GetDevice() == fControlInterface->GetDevice()) 1167 { 1168 1169 // Then check to see if it's the correct data interface number 1170 1171 if (dataDriver->fPort.DataInterfaceNumber == fDataInterfaceNumber) 1172 { 1173 this->fDataDriver = dataDriver; 1174 return true; 1175 } else { 1176 XTRACE(this, 0, 0, "checkInterfaceNumber - Not correct interface number"); 1177 } 1178 } else { 1179 XTRACE(this, 0, 0, "checkInterfaceNumber - Not correct device"); 1180 } 1181 1182 return false; 1183 1184}/* end checkInterfaceNumber */ 1185 1186/****************************************************************************************************/ 1187// 1188// Method: AppleUSBCDCACMControl::resetDevice 1189// 1190// Inputs: 1191// 1192// Outputs: 1193// 1194// Desc: Check to see if we need to reset the device on wakeup. 1195// 1196/****************************************************************************************************/ 1197 1198void AppleUSBCDCACMControl::resetDevice(void) 1199{ 1200 IOReturn rtn = kIOReturnSuccess; 1201 USBStatus status; 1202 bool reset = false; 1203 bool reenum = false; 1204 1205 XTRACE(this, 0, 0, "resetDevice"); 1206 1207 if ((fStopping) || (fControlInterface == NULL) || (fTerminate)) 1208 { 1209 XTRACE(this, 0, 0, "resetDevice - returning early"); 1210 return; 1211 } 1212 1213 // Let everything settle down first 1214 1215// IOSleep(100); 1216 1217 rtn = fControlInterface->GetDevice()->GetDeviceStatus(&status); 1218 if (rtn != kIOReturnSuccess) 1219 { 1220 XTRACE(this, 0, rtn, "resetDevice - Error getting device status"); 1221 reset = true; 1222 } else { 1223 status = USBToHostWord(status); 1224 XTRACE(this, 0, status, "resetDevice - Device status"); 1225 if (status & kDeviceSelfPowered) // Self powered devices that need "reset on close" will also be reset 1226 { 1227 if (fDataDriver) 1228 { 1229 if (fDataDriver->fResetOnClose) 1230 { 1231 reset = true; 1232 } 1233 if (fDataDriver->fEnumOnWake) 1234 { 1235 reenum = true; 1236 } 1237 } 1238 } 1239 } 1240 1241 if ((fControlInterface) && (fDataDriver)) // Make sure the interface and data driver are still around 1242 { 1243 if (reenum) // Enumeration takes precedent 1244 { 1245 fDataDriver->fTerminate = true; // Warn the data driver early 1246 XTRACE(this, 0, 0, "resetDevice - Device is being re-enumerated"); 1247 rtn = fControlInterface->GetDevice()->ReEnumerateDevice(0); 1248 if (rtn != kIOReturnSuccess) 1249 { 1250 XTRACE(this, 0, rtn, "resetDevice - ReEnumerateDevice failed"); 1251 } 1252 } else { 1253 fDataDriver->fTerminate = false; 1254 if (reset) 1255 { 1256 XTRACE(this, 0, 0, "resetDevice - Device is being reset"); 1257 rtn = fControlInterface->GetDevice()->ResetDevice(); 1258 if (rtn != kIOReturnSuccess) 1259 { 1260 XTRACE(this, 0, rtn, "resetDevice - ResetDevice failed"); 1261 } 1262 } 1263 } 1264 } else { 1265 XTRACE(this, 0, 0, "resetDevice - Control interface or Data driver has gone"); 1266 } 1267 1268}/* end resetDevice */ 1269 1270/****************************************************************************************************/ 1271// 1272// Method: AppleUSBCDCACMControl::message 1273// 1274// Inputs: type - message type 1275// provider - my provider 1276// argument - additional parameters 1277// 1278// Outputs: return Code - kIOReturnSuccess 1279// 1280// Desc: Handles IOKit messages. 1281// 1282/****************************************************************************************************/ 1283 1284IOReturn AppleUSBCDCACMControl::message(UInt32 type, IOService *provider, void *argument) 1285{ 1286 IOReturn rtn; 1287 1288 XTRACE(this, 0, type, "message"); 1289 1290 switch (type) 1291 { 1292 case kIOMessageServiceIsTerminated: 1293 XTRACE(this, 0, type, "message - kIOMessageServiceIsTerminated"); 1294 fTerminate = true; // We're being terminated (unplugged) 1295 releaseResources(); 1296 return kIOReturnSuccess; 1297 case kIOMessageServiceIsSuspended: 1298 XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended"); 1299 break; 1300 case kIOMessageServiceIsResumed: 1301 XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed"); 1302 break; 1303 case kIOMessageServiceIsRequestingClose: 1304 XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose"); 1305 break; 1306 case kIOMessageServiceWasClosed: 1307 XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed"); 1308 break; 1309 case kIOMessageServiceBusyStateChange: 1310 XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange"); 1311 break; 1312 case kIOUSBMessagePortHasBeenResumed: 1313 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed"); 1314 if (fReadDead) 1315 { 1316 rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL); 1317 if (rtn != kIOReturnSuccess) 1318 { 1319 XTRACE(this, 0, rtn, "message - Read for interrupt-in pipe failed, still dead"); 1320 } else { 1321 fReadDead = false; 1322 } 1323 } 1324 return kIOReturnSuccess; 1325 case kIOUSBMessageHubResumePort: 1326 XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort"); 1327 break; 1328 case kIOUSBMessagePortHasBeenReset: 1329 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenReset"); 1330 if (fReadDead) 1331 { 1332 rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL); 1333 if (rtn != kIOReturnSuccess) 1334 { 1335 XTRACE(this, 0, rtn, "message - Read for interrupt-in pipe failed, still dead"); 1336 } else { 1337 fReadDead = false; 1338 } 1339 } 1340 return kIOReturnSuccess; 1341 default: 1342 XTRACE(this, 0, type, "message - unknown message"); 1343 break; 1344 } 1345 1346 return super::message(type, provider, argument); 1347 1348}/* end message */ 1349 1350/****************************************************************************************************/ 1351// 1352// Method: AppleUSBCDCACMControl::initForPM 1353// 1354// Inputs: provider - my provider 1355// 1356// Outputs: return code - true(initialized), false(failed) 1357// 1358// Desc: Add ourselves to the power management tree so we can do 1359// the right thing on sleep/wakeup. 1360// 1361/****************************************************************************************************/ 1362 1363bool AppleUSBCDCACMControl::initForPM(IOService *provider) 1364{ 1365 XTRACE(this, 0, 0, "initForPM"); 1366 1367 fPowerState = kCDCPowerOnState; // init our power state to be 'on' 1368 PMinit(); // init power manager instance variables 1369 provider->joinPMtree(this); // add us to the power management tree 1370 if (pm_vars != NULL) 1371 { 1372 1373 // register ourselves with ourself as policy-maker 1374 1375 registerPowerDriver(this, gOurPowerStates, kNumCDCStates); 1376 return true; 1377 } else { 1378 XTRACE(this, 0, 0, "initForPM - Initializing power manager failed"); 1379 } 1380 1381 return false; 1382 1383}/* end initForPM */ 1384 1385/****************************************************************************************************/ 1386// 1387// Method: AppleUSBCDCACMControl::initialPowerStateForDomainState 1388// 1389// Inputs: flags - 1390// 1391// Outputs: return code - Current power state 1392// 1393// Desc: Request for our initial power state. 1394// 1395/****************************************************************************************************/ 1396 1397unsigned long AppleUSBCDCACMControl::initialPowerStateForDomainState(IOPMPowerFlags flags) 1398{ 1399 1400 XTRACE(this, 0, flags, "initialPowerStateForDomainState"); 1401 1402 return fPowerState; 1403 1404}/* end initialPowerStateForDomainState */ 1405 1406/****************************************************************************************************/ 1407// 1408// Method: AppleUSBCDCACMControl::setPowerState 1409// 1410// Inputs: powerStateOrdinal - on/off 1411// 1412// Outputs: return code - IOPMNoErr, IOPMAckImplied or IOPMNoSuchState 1413// 1414// Desc: Request to turn device on or off. 1415// 1416/****************************************************************************************************/ 1417 1418IOReturn AppleUSBCDCACMControl::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice) 1419{ 1420 1421 XTRACE(this, 0, powerStateOrdinal, "setPowerState"); 1422 1423 if (powerStateOrdinal != fPowerState) 1424 { 1425 fPowerState = powerStateOrdinal; 1426 switch (fPowerState) 1427 { 1428 case kCDCPowerOffState: 1429 1430 // Warn our data driver and clean up any threads, if we can 1431 1432 if (fDataDriver) 1433 { 1434 fControlInterface->GetDevice()->SuspendDevice(true); 1435 } 1436 1437 break; 1438 1439 case kCDCPowerOnState: 1440 fControlInterface->GetDevice()->SuspendDevice(false); 1441 break; 1442 1443 default: 1444 return IOPMNoSuchState; 1445 } 1446 } 1447 1448 return IOPMAckImplied; 1449 1450}/* end setPowerState */