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 /* AppleUSBCDCACMData.cpp - MacOSX implementation of */ 26 /* USB Communication Device Class (CDC) Driver, ACM Data 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 "AppleUSBCDCACMData" 58 59#include "AppleUSBCDCACM.h" 60#include "AppleUSBCDCACMData.h" 61 62#define MIN_BAUD (50 << 1) 63 64//AppleUSBCDCACMControl *gControlDriver = NULL; // Our Control driver 65 66static const OSSymbol *gPMWakeOnRingSymbol = NULL; 67 68#define super IOSerialDriverSync 69 70OSDefineMetaClassAndStructors(AppleUSBCDCACMData, IOSerialDriverSync); 71 72/****************************************************************************************************/ 73// 74// Function: findCDCDriverAD 75// 76// Inputs: dataAddr - my address 77// dataInterfaceNum - the data interface number 78// 79// Outputs: Pointer to the CDC driver 80// 81// Desc: Finds the initiating CDC driver and confirms the interface number 82// 83/****************************************************************************************************/ 84 85AppleUSBCDC *findCDCDriverAD(void *dataAddr, UInt8 dataInterfaceNum, IOReturn *retCode) 86{ 87 AppleUSBCDCACMData *me = (AppleUSBCDCACMData *)dataAddr; 88 AppleUSBCDC *CDCDriver = NULL; 89 bool driverOK = false; 90 OSIterator *iterator = NULL; 91 OSDictionary *matchingDictionary = NULL; 92 93 XTRACE(me, 0, 0, "findCDCDriverAD"); 94 95 // Get matching dictionary 96 97 matchingDictionary = IOService::serviceMatching("AppleUSBCDC"); 98 if (!matchingDictionary) 99 { 100 XTRACE(me, 0, 0, "findCDCDriverAD - Couldn't create a matching dictionary"); 101 *retCode = kIOReturnError; 102 return NULL; 103 } 104 105 // Get an iterator 106 107 iterator = IOService::getMatchingServices(matchingDictionary); 108 if (!iterator) 109 { 110 XTRACE(me, 0, 0, "findCDCDriverAD - No AppleUSBCDC driver found!"); 111 matchingDictionary->release(); 112 *retCode = kIOReturnError; 113 return NULL; 114 } 115 116 // Iterate until we find our matching CDC driver 117 118 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 119 while (CDCDriver) 120 { 121 XTRACEP(me, 0, CDCDriver, "findCDCDriverAD - CDC driver candidate"); 122 123 if (me->fDataInterface->GetDevice() == CDCDriver->getCDCDevice()) 124 { 125 XTRACEP(me, 0, CDCDriver, "findCDCDriverAD - Found our CDC driver"); 126 driverOK = CDCDriver->confirmDriver(kUSBAbstractControlModel, dataInterfaceNum); 127 break; 128 } 129 CDCDriver = (AppleUSBCDC *)iterator->getNextObject(); 130 } 131 132 matchingDictionary->release(); 133 iterator->release(); 134 135 if (!CDCDriver) 136 { 137 XTRACE(me, 0, 0, "findCDCDriverAD - CDC driver not found"); 138 *retCode = kIOReturnNotReady; 139 return NULL; 140 } 141 142 if (!driverOK) 143 { 144 XTRACE(me, kUSBAbstractControlModel, dataInterfaceNum, "findCDCDriverAD - Not my interface"); 145 *retCode = kIOReturnError; 146 return NULL; 147 } 148 149 me->fConfigAttributes = CDCDriver->fbmAttributes; 150 151 *retCode = kIOReturnSuccess; 152 153 return CDCDriver; 154 155}/* end findCDCDriverAD */ 156 157/****************************************************************************************************/ 158// 159// Function: findControlDriverAD 160// 161// Inputs: me - my address 162// 163// Outputs: AppleUSBCDCACMControl 164// 165// Desc: Finds our matching control driver 166// 167/****************************************************************************************************/ 168 169AppleUSBCDCACMControl *findControlDriverAD(void *me) 170{ 171 Boolean worked = false; 172 AppleUSBCDCACMControl *tempDriver = NULL; 173 OSIterator *iterator = NULL; 174 OSDictionary *matchingDictionary = NULL; 175 176 XTRACE(me, 0, 0, "findControlDriverAD"); 177 178 // Get matching dictionary 179 180 matchingDictionary = IOService::serviceMatching("AppleUSBCDCACMControl"); 181 if (!matchingDictionary) 182 { 183 XTRACE(me, 0, 0, "findControlDriverAD - Couldn't create a matching dictionary"); 184 return NULL; 185 } 186 187 // Get an iterator 188 189 iterator = IOService::getMatchingServices(matchingDictionary); 190 if (!iterator) 191 { 192 XTRACE(me, 0, 0, "findControlDriverAD - No AppleUSBCDCACMControl drivers found (iterator)"); 193 matchingDictionary->release(); 194 return NULL; 195 } 196 197 // Iterate until we find our matching driver 198 199 tempDriver = (AppleUSBCDCACMControl *)iterator->getNextObject(); 200 while (tempDriver) 201 { 202 XTRACEP(me, 0, tempDriver, "findControlDriverAD - Data driver candidate"); 203 if (tempDriver->checkInterfaceNumber((AppleUSBCDCACMData *)me)) 204 { 205 XTRACEP(me, 0, tempDriver, "findControlDriverAD - Found our data driver"); 206 worked = true; 207 break; 208 } 209 tempDriver = (AppleUSBCDCACMControl *)iterator->getNextObject(); 210 } 211 212 matchingDictionary->release(); 213 iterator->release(); 214 215 if (!worked) 216 { 217 XTRACE(me, 0, 0, "findControlDriverAD - Failed"); 218 return NULL; 219 } 220 221 return tempDriver; 222 223}/* end findControlDriverAD */ 224 225#if LOG_DATA 226#define dumplen 32 // Set this to the number of bytes to dump and the rest should work out correct 227 228#define buflen ((dumplen*2)+dumplen)+3 229#define Asciistart (dumplen*2)+3 230 231/****************************************************************************************************/ 232// 233// Function: USBLogData 234// 235// Inputs: Dir - direction 236// Count - number of bytes 237// buf - the data 238// 239// Outputs: 240// 241// Desc: Puts the data in the log. 242// 243/****************************************************************************************************/ 244 245void AppleUSBCDCACMData::USBLogData(UInt8 Dir, SInt32 Count, char *buf) 246{ 247 SInt32 wlen; 248 SInt32 llen, rlen; 249 SInt16 i, Aspnt, Hxpnt; 250 UInt8 wchr; 251 UInt8 LocBuf[buflen+1]; 252 253 switch (Dir) 254 { 255 case kDataIn: 256 Log( "AppleUSBCDCACMData: USBLogData - Read Complete, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 257 break; 258 case kDataOut: 259 Log( "AppleUSBCDCACMData: USBLogData - Write, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 260 break; 261 case kDataOther: 262 Log( "AppleUSBCDCACMData: USBLogData - Other, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 263 break; 264 } 265 266 if (Count > dumplen) 267 { 268 wlen = dumplen; 269 } else { 270 wlen = Count; 271 } 272 273 if (wlen == 0) 274 { 275 Log( "AppleUSBCDCACMData: USBLogData - No data, Count=0\n" ); 276 return; 277 } 278 279 rlen = 0; 280 do 281 { 282 memset(LocBuf, 0x20, buflen); 283 284 if (wlen > dumplen) 285 { 286 llen = dumplen; 287 wlen -= dumplen; 288 } else { 289 llen = wlen; 290 wlen = 0; 291 } 292 Aspnt = Asciistart; 293 Hxpnt = 0; 294 for (i=1; i<=llen; i++) 295 { 296 wchr = buf[i-1]; 297 LocBuf[Hxpnt++] = Asciify(wchr >> 4); 298 LocBuf[Hxpnt++] = Asciify(wchr); 299 if ((wchr < 0x20) || (wchr > 0x7F)) // Non printable characters 300 { 301 LocBuf[Aspnt++] = 0x2E; // Replace with a period 302 } else { 303 LocBuf[Aspnt++] = wchr; 304 } 305 } 306 LocBuf[Aspnt] = 0x00; 307 308 Log("%s\n", LocBuf); 309#if USE_IOL 310 IOSleep(Sleep_Time); // Try and keep the log from overflowing 311#endif 312 rlen += llen; 313 buf = &buf[rlen]; 314 } while (wlen != 0); 315 316}/* end USBLogData */ 317 318/****************************************************************************************************/ 319// 320// Function: AppleUSBCDCACMData::dumpData 321// 322// Inputs: Dir - direction 323// buf - the data 324// size - number of bytes 325// 326// Outputs: None 327// 328// Desc: Creates formatted data for the log 329// 330/****************************************************************************************************/ 331 332void AppleUSBCDCACMData::dumpData(UInt8 Dir, char *buf, SInt32 Count) 333{ 334 SInt32 curr, len, dlen; 335 336 switch (Dir) 337 { 338 case kDataIn: 339 Log( "AppleUSBCDCACMData: dumpData - Read Complete, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 340 break; 341 case kDataOut: 342 Log( "AppleUSBCDCACMData: dumpData - Write, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 343 break; 344 case kDataOther: 345 Log( "AppleUSBCDCACMData: dumpData - Other, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 346 break; 347 } 348 349 dlen = 0; 350 len = Count; 351 352 for (curr=0; curr<Count; curr+=dumplen) 353 { 354 if (len > dumplen) 355 { 356 dlen = dumplen; 357 } else { 358 dlen = len; 359 } 360 Log("%8p ", (void *)&buf[curr]); 361 USBLogData(kDataNone, dlen, &buf[curr]); 362 len -= dlen; 363 } 364 365}/* end dumpData */ 366#endif 367 368/****************************************************************************************************/ 369// 370// Method: AddBytetoQueue 371// 372// Inputs: Queue - the queue to be added to 373// Value - Byte to be added 374// 375// Outputs: Queue status - full or no error 376// 377// Desc: Add a byte to the circular queue. 378// Check to see if there is space by comparing the next pointer, 379// with the last, If they match we are either Empty or full, so 380// check InQueue for zero. 381// 382/****************************************************************************************************/ 383 384QueueStatus AppleUSBCDCACMData::AddBytetoQueue(CirQueue *Queue, char Value) 385{ 386 387 if ((Queue->NextChar == Queue->LastChar) && Queue->InQueue) 388 { 389 return queueFull; 390 } 391 392 *Queue->NextChar++ = Value; 393 Queue->InQueue++; 394 395 // Check to see if we need to wrap the pointer. 396 397 if (Queue->NextChar >= Queue->End) 398 Queue->NextChar = Queue->Start; 399 400 return queueNoError; 401 402}/* end AddBytetoQueue */ 403 404/****************************************************************************************************/ 405// 406// Method: GetBytetoQueue 407// 408// Inputs: Queue - the queue to be removed from 409// 410// Outputs: Value - where to put the byte 411// QueueStatus - empty or no error 412// 413// Desc: Remove a byte from the circular queue. 414// 415/****************************************************************************************************/ 416 417QueueStatus AppleUSBCDCACMData::GetBytetoQueue(CirQueue *Queue, UInt8 *Value) 418{ 419 420 if ((Queue->NextChar == Queue->LastChar) && !Queue->InQueue) 421 { 422 return queueEmpty; 423 } 424 425 *Value = *Queue->LastChar++; 426 Queue->InQueue--; 427 428 // Check to see if we need to wrap the pointer. 429 430 if (Queue->LastChar >= Queue->End) 431 Queue->LastChar = Queue->Start; 432 433 return queueNoError; 434 435}/* end GetBytetoQueue */ 436 437/****************************************************************************************************/ 438// 439// Method: InitQueue 440// 441// Inputs: Queue - the queue to be initialized 442// Buffer - the buffer 443// size - length of buffer 444// 445// Outputs: QueueStatus - queueNoError. 446// 447// Desc: Pass a buffer of memory and this routine will set up the internal data structures. 448// 449/****************************************************************************************************/ 450 451QueueStatus AppleUSBCDCACMData::InitQueue(CirQueue *Queue, UInt8 *Buffer, size_t Size) 452{ 453 Queue->Start = Buffer; 454 Queue->End = (UInt8*)((size_t)Buffer + Size); 455 Queue->Size = Size; 456 Queue->NextChar = Buffer; 457 Queue->LastChar = Buffer; 458 Queue->InQueue = 0; 459 460// IOSleep(1); 461 462 return queueNoError ; 463 464}/* end InitQueue */ 465 466/****************************************************************************************************/ 467// 468// Method: CloseQueue 469// 470// Inputs: Queue - the queue to be closed 471// 472// Outputs: QueueStatus - queueNoError. 473// 474// Desc: Clear out all of the data structures. 475// 476/****************************************************************************************************/ 477 478QueueStatus AppleUSBCDCACMData::CloseQueue(CirQueue *Queue) 479{ 480 481 Queue->Start = 0; 482 Queue->End = 0; 483 Queue->NextChar = 0; 484 Queue->LastChar = 0; 485 Queue->Size = 0; 486 487 return queueNoError; 488 489}/* end CloseQueue */ 490 491/****************************************************************************************************/ 492// 493// Function: AppleUSBCDCACMData::AddtoRXQueue 494// 495// Inputs: Queue - the queue to be added to 496// buffs - data to add 497// Size - length of data 498// 499// Outputs: BytesWritten - Number of bytes actually put in the queue. 500// 501// Desc: Add an entire buffer to the queue. 502// 503/****************************************************************************************************/ 504 505size_t AppleUSBCDCACMData::AddtoRXQueue(CirQueue *Queue, inPipeBuffers *buffs, size_t Size) 506{ 507 UInt8 *Buffer = buffs->pipeBuffer; 508 size_t BytesWritten = 0; 509 size_t inQueue = 0; 510 511 inQueue = FreeSpaceinQueue(Queue); 512 if (inQueue < Size) 513 { 514 XTRACE(this, inQueue, Size, "AddtoRXQueue - Queue full, buffer will be held" ); 515 return 0; 516 } 517 518 while (FreeSpaceinQueue(Queue) && (Size > BytesWritten)) 519 { 520 AddBytetoQueue(Queue, *Buffer++); 521 BytesWritten++; 522 } 523 524 if (BytesWritten < Size) 525 { 526 ALERT(BytesWritten, Size, "AddtoRXQueue - Queue full, data has been dropped" ); 527 } 528 529 return BytesWritten; 530 531}/* end AddtoRXQueue */ 532 533/****************************************************************************************************/ 534// 535// Method: AddtoQueue 536// 537// Inputs: Queue - the queue to be added to 538// Buffer - data to add 539// Size - length of data 540// 541// Outputs: BytesWritten - Number of bytes actually put in the queue. 542// 543// Desc: Add an entire buffer to the queue. 544// 545/****************************************************************************************************/ 546 547size_t AppleUSBCDCACMData::AddtoQueue(CirQueue *Queue, UInt8 *Buffer, size_t Size) 548{ 549 size_t BytesWritten = 0; 550 551 while (FreeSpaceinQueue(Queue) && (Size > BytesWritten)) 552 { 553 AddBytetoQueue(Queue, *Buffer++); 554 BytesWritten++; 555 } 556 557 return BytesWritten; 558 559}/* end AddtoQueue */ 560 561/****************************************************************************************************/ 562// 563// Method: RemovefromQueue 564// 565// Inputs: Queue - the queue to be removed from 566// Size - size of buffer 567// 568// Outputs: Buffer - Where to put the data 569// BytesReceived - Number of bytes actually put in Buffer. 570// 571// Desc: Get a buffers worth of data from the queue. 572// 573/****************************************************************************************************/ 574 575size_t AppleUSBCDCACMData::RemovefromQueue(CirQueue *Queue, UInt8 *Buffer, size_t MaxSize) 576{ 577 size_t BytesReceived = 0; 578 UInt8 Value; 579 580 // while((GetBytetoQueue(Queue, &Value) == queueNoError) && (MaxSize >= BytesReceived)) 581 while((MaxSize > BytesReceived) && (GetBytetoQueue(Queue, &Value) == queueNoError)) 582 { 583 *Buffer++ = Value; 584 BytesReceived++; 585 }/* end while */ 586 587 return BytesReceived; 588 589}/* end RemovefromQueue */ 590 591/****************************************************************************************************/ 592// 593// Method: FreeSpaceinQueue 594// 595// Inputs: Queue - the queue to be queried 596// 597// Outputs: Return Value - Free space left 598// 599// Desc: Return the amount of free space left in this buffer. 600// 601/****************************************************************************************************/ 602 603size_t AppleUSBCDCACMData::FreeSpaceinQueue(CirQueue *Queue) 604{ 605 size_t retVal = 0; 606 607 retVal = Queue->Size - Queue->InQueue; 608 609 return retVal; 610 611}/* end FreeSpaceinQueue */ 612 613/****************************************************************************************************/ 614// 615// Method: UsedSpaceinQueue 616// 617// Inputs: Queue - the queue to be queried 618// 619// Outputs: UsedSpace - Amount of data in buffer 620// 621// Desc: Return the amount of data in this buffer. 622// 623/****************************************************************************************************/ 624 625size_t AppleUSBCDCACMData::UsedSpaceinQueue(CirQueue *Queue) 626{ 627 return Queue->InQueue; 628 629}/* end UsedSpaceinQueue */ 630 631/****************************************************************************************************/ 632// 633// Method: GetQueueSize 634// 635// Inputs: Queue - the queue to be queried 636// 637// Outputs: QueueSize - The size of the queue. 638// 639// Desc: Return the total size of the queue. 640// 641/****************************************************************************************************/ 642 643size_t AppleUSBCDCACMData::GetQueueSize(CirQueue *Queue) 644{ 645 return Queue->Size; 646 647}/* end GetQueueSize */ 648 649/****************************************************************************************************/ 650// 651// Method: GetQueueStatus 652// 653// Inputs: Queue - the queue to be queried 654// 655// Outputs: Queue status - full, empty or no error 656// 657// Desc: Returns the status of the circular queue. 658// 659/****************************************************************************************************/ 660 661QueueStatus AppleUSBCDCACMData::GetQueueStatus(CirQueue *Queue) 662{ 663 if ((Queue->NextChar == Queue->LastChar) && Queue->InQueue) 664 return queueFull; 665 else if ((Queue->NextChar == Queue->LastChar) && !Queue->InQueue) 666 return queueEmpty; 667 668 return queueNoError ; 669 670}/* end GetQueueStatus */ 671 672/****************************************************************************************************/ 673// 674// Method: CheckQueues 675// 676// Inputs: 677// 678// Outputs: 679// 680// Desc: Checks the various queue's etc and manipulates the state(s) accordingly 681// Must be called from a gated method or completion routine. 682// 683/****************************************************************************************************/ 684 685void AppleUSBCDCACMData::CheckQueues() 686{ 687 UInt32 Used; 688 UInt32 Free; 689 UInt32 QueuingState; 690 UInt32 DeltaState; 691 692 // Initialise the QueueState with the current state. 693 694 QueuingState = fPort.State; 695 696 // Check to see if there is anything in the Transmit buffer. 697 698 Used = UsedSpaceinQueue(&fPort.TX); 699 Free = FreeSpaceinQueue(&fPort.TX); 700 701 XTRACE(this, Free, Used, "CheckQueues"); 702 703 if (Free == 0) 704 { 705 QueuingState |= PD_S_TXQ_FULL; 706 QueuingState &= ~PD_S_TXQ_EMPTY; 707 } else { 708 if (Used == 0) 709 { 710 QueuingState &= ~PD_S_TXQ_FULL; 711 QueuingState |= PD_S_TXQ_EMPTY; 712 } else { 713 QueuingState &= ~PD_S_TXQ_FULL; 714 QueuingState &= ~PD_S_TXQ_EMPTY; 715 } 716 } 717 718 // Check to see if we are below the low water mark. 719 720 if (Used < fPort.TXStats.LowWater) 721 QueuingState |= PD_S_TXQ_LOW_WATER; 722 else QueuingState &= ~PD_S_TXQ_LOW_WATER; 723 724 if (Used > fPort.TXStats.HighWater) 725 QueuingState |= PD_S_TXQ_HIGH_WATER; 726 else QueuingState &= ~PD_S_TXQ_HIGH_WATER; 727 728 729 // Check to see if there is anything in the Receive buffer. 730 731 Used = UsedSpaceinQueue(&fPort.RX); 732 Free = FreeSpaceinQueue(&fPort.RX); 733 734 if (Free == 0) 735 { 736 QueuingState |= PD_S_RXQ_FULL; 737 QueuingState &= ~PD_S_RXQ_EMPTY; 738 } else { 739 if (Used == 0) 740 { 741 QueuingState &= ~PD_S_RXQ_FULL; 742 QueuingState |= PD_S_RXQ_EMPTY; 743 } else { 744 QueuingState &= ~PD_S_RXQ_FULL; 745 QueuingState &= ~PD_S_RXQ_EMPTY; 746 } 747 } 748 749 // Check to see if we are below the low water mark. 750 751 if (Used < fPort.RXStats.LowWater) 752 QueuingState |= PD_S_RXQ_LOW_WATER; 753 else QueuingState &= ~PD_S_RXQ_LOW_WATER; 754 755 if (Used > fPort.RXStats.HighWater) 756 QueuingState |= PD_S_RXQ_HIGH_WATER; 757 else QueuingState &= ~PD_S_RXQ_HIGH_WATER; 758 759 // Figure out what has changed to get mask. 760 761 DeltaState = QueuingState ^ fPort.State; 762 setStateGated(&QueuingState, &DeltaState); 763 764}/* end CheckQueues */ 765 766/****************************************************************************************************/ 767// 768// Method: CheckHold 769// 770// Inputs: 771// 772// Outputs: 773// 774// Desc: Checks to see if there's any held buffers 775// 776/****************************************************************************************************/ 777 778void AppleUSBCDCACMData::CheckHold() 779{ 780 SInt32 size; 781 inPipeBuffers *buffs; 782 IOReturn ior = kIOReturnSuccess; 783 784 XTRACE(this, fPort.holdQueueIndxIn, fPort.holdQueueIndxOut, "CheckHold"); 785 786 while (1) 787 { 788 if (fPort.holdQueue[fPort.holdQueueIndxOut] != 0) 789 { 790 buffs = fPort.holdQueue[fPort.holdQueueIndxOut]; 791 size = AddtoRXQueue(&fPort.RX, buffs, buffs->count); 792 if (size == 0) 793 { 794 XTRACE(this, fPort.holdQueueIndxIn, fPort.holdQueueIndxOut, "CheckHold - Still holding"); 795 break; 796 } else { 797 buffs->count = 0; 798 buffs->held = false; 799 XTRACE(this, fPort.holdQueueIndxIn, fPort.holdQueueIndxOut, "CheckHold - Read issued"); 800 ior = fPort.InPipe->Read(buffs->pipeMDP, &buffs->completionInfo, NULL); 801 if (ior != kIOReturnSuccess) 802 { 803 XTRACE(this, fPort.holdQueueIndxOut, ior, "CheckHold - Read io err"); 804 buffs->dead = true; 805 } 806 fPort.holdQueue[fPort.holdQueueIndxOut] = 0; 807 fPort.holdQueueIndxOut++; 808 if (fPort.holdQueueIndxOut >= kMaxInBufPool) 809 { 810 fPort.holdQueueIndxOut = 0; 811 } 812 } 813 } else { 814 break; 815 } 816 } 817 818 CheckQueues(); 819 820 XTRACE(this, fPort.holdQueueIndxIn, fPort.holdQueueIndxOut, "CheckHold - Exit"); 821 822}/* end CheckHold */ 823 824/****************************************************************************************************/ 825// 826// Method: AppleUSBCDCACMData::dataReadComplete 827// 828// Inputs: obj - me 829// param - the buffer pool pointer 830// rc - return code 831// remaining - what's left 832// 833// Outputs: None 834// 835// Desc: BulkIn pipe read completion routine 836// 837/****************************************************************************************************/ 838 839void AppleUSBCDCACMData::dataReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 840{ 841 AppleUSBCDCACMData *me = (AppleUSBCDCACMData*)obj; 842 inPipeBuffers *buffs = (inPipeBuffers *)param; 843 IOReturn ior; 844 size_t length; 845 SInt32 putInQueue = 0; 846 847 XTRACE(me, rc, 0, "dataReadComplete"); 848 849 if (me->fStopping) 850 return; 851 852 if (rc == kIOReturnSuccess) // If operation returned ok 853 { 854 length = DATA_BUFF_SIZE - remaining; 855 XTRACE(me, me->fPort.State, length, "dataReadComplete - data length"); 856 857 if (length > 0) 858 { 859// me->LogData(kDataIn, length, buffs->pipeBuffer); 860 861 // Move the incoming bytes to the ring buffer, if we can 862 863// me->AddtoQueue(&me->fPort.RX, buffs->pipeBuffer, length); 864 865 // If the indices are not equal then there's something in the hold queue 866 867 if (me->fPort.holdQueueIndxIn != me->fPort.holdQueueIndxOut) 868 { 869 XTRACE(me, me->fPort.holdQueueIndxIn, me->fPort.holdQueueIndxOut, "dataReadComplete - holdQueueIndxIn holdQueueIndxOut !!!"); 870 putInQueue = 0; 871 } else { 872 putInQueue = me->AddtoRXQueue(&me->fPort.RX, buffs, length); 873 } 874 if (putInQueue == 0) 875 { 876 XTRACE(me, 0, me->fPort.holdQueueIndxIn, "dataReadComplete - Buffer held"); 877 buffs->held = true; 878 buffs->count = length; 879 me->fPort.holdQueue[me->fPort.holdQueueIndxIn++] = buffs; 880 if (me->fPort.holdQueueIndxIn >= kMaxInBufPool) 881 { 882 me->fPort.holdQueueIndxIn = 0; 883 } 884 } 885 } 886 } else { 887 XTRACE(me, 0, rc, "dataReadComplete - error"); 888 if (rc != kIOReturnAborted) 889 { 890 if ((rc == kIOUSBPipeStalled) || (rc == kIOUSBHighSpeedSplitError)) 891 { 892 rc = me->checkPipe(me->fPort.InPipe, true); 893 } else { 894 rc = me->checkPipe(me->fPort.InPipe, false); 895 } 896 if (rc != kIOReturnSuccess) 897 { 898 XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)"); 899 } 900 } 901 } 902 903 // Queue the read only if not aborted and the buffer is not held 904 905 if (rc != kIOReturnAborted) 906 { 907 if (!buffs->held) 908 { 909 XTRACE(me, 0, me->fPort.holdQueueIndxIn, "dataReadComplete - Read issued"); 910 ior = me->fPort.InPipe->Read(buffs->pipeMDP, &buffs->completionInfo, NULL); 911 if (ior != kIOReturnSuccess) 912 { 913 XTRACEP(me, buffs, ior, "dataReadComplete - Read io err"); 914 buffs->dead = true; 915 } else { 916 XTRACEP(me, buffs, me->fPort.InPipe, "dataReadComplete - Read posted"); 917 } 918 } 919 me->CheckQueues(); 920 } else { 921 XTRACEP(me, buffs, me->fPort.InPipe, "dataReadComplete - Read aborted"); 922 } 923 924}/* end dataReadComplete */ 925 926/****************************************************************************************************/ 927// 928// Method: AppleUSBCDCACMData::dataWriteComplete 929// 930// Inputs: obj - me 931// param - the buffer pool pointer 932// rc - return code 933// remaining - what's left 934// 935// Outputs: None 936// 937// Desc: BulkOut pipe write completion routine 938// 939/****************************************************************************************************/ 940 941void AppleUSBCDCACMData::dataWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 942{ 943 AppleUSBCDCACMData *me = (AppleUSBCDCACMData *)obj; 944 outPipeBuffers *buffs = (outPipeBuffers *)param; 945 SInt32 dLen; 946 UInt16 i; 947 bool busy = false; 948 UInt32 state; 949 UInt32 mask; 950 951 XTRACE(me, rc, 0, "dataWriteComplete"); 952 953 if (me->fStopping) 954 return; 955 956 if (rc == kIOReturnSuccess) 957 { 958 dLen = buffs->count - remaining; 959 XTRACE(me, 0, dLen, "dataWriteComplete - data length"); 960 if (dLen > 0) // Check if it was a zero length write 961 { 962 if ((dLen % me->fPort.OutPacketSize) == 0) // If it was a multiple of max packet size then we need to do a zero length write 963 { 964 XTRACE(me, rc, dLen, "dataWriteComplete - writing zero length packet"); 965 buffs->count = 0; 966 buffs->pipeMDP->setLength(0); 967 968 me->fPort.OutPipe->Write(buffs->pipeMDP, &buffs->completionInfo); 969 return; 970 } else { 971 buffs->avail = true; 972 } 973 } else { 974 buffs->avail = true; 975 } 976 977 me->CheckQueues(); 978 979 // If any of the buffers are unavailable then we're still busy 980 981 for (i=0; i<me->fOutBufPool; i++) 982 { 983 if (!me->fPort.outPool[i].avail) 984 { 985 busy = true; 986 break; 987 } 988 } 989 990 if (!busy) 991 { 992 state = 0; 993 mask = PD_S_TX_BUSY; 994 me->setStateGated(&state, &mask); // Clear the busy state 995 } 996 997 me->setUpTransmit(); // just to keep it going?? 998 999 } else { 1000 XTRACE(me, 0, rc, "dataWriteComplete - io error"); 1001 if (rc != kIOReturnAborted) 1002 { 1003 if ((rc == kIOUSBPipeStalled) || (rc == kIOUSBHighSpeedSplitError)) 1004 { 1005 rc = me->checkPipe(me->fPort.InPipe, true); 1006 } else { 1007 rc = me->checkPipe(me->fPort.InPipe, false); 1008 } 1009 if (rc != kIOReturnSuccess) 1010 { 1011 XTRACE(me, 0, rc, "dataWriteComplete - clear stall failed (trying to continue)"); 1012 } 1013 } 1014 1015 1016 buffs->avail = true; 1017 1018 // If any of the buffers are unavailable then we're still busy 1019 1020 for (i=0; i<me->fOutBufPool; i++) 1021 { 1022 if (!me->fPort.outPool[i].avail) 1023 { 1024 busy = true; 1025 break; 1026 } 1027 } 1028 1029 if (!busy) 1030 { 1031 state = 0; 1032 mask = PD_S_TX_BUSY; 1033 me->setStateGated(&state, &mask); 1034 } 1035 } 1036 1037}/* end dataWriteComplete */ 1038 1039/****************************************************************************************************/ 1040// 1041// Method: AppleUSBCDCACMData::probe 1042// 1043// Inputs: provider - my provider 1044// 1045// Outputs: IOService - from super::probe, score - probe score 1046// 1047// Desc: Modify the probe score if necessary (we don't at the moment) 1048// 1049/****************************************************************************************************/ 1050 1051IOService* AppleUSBCDCACMData::probe( IOService *provider, SInt32 *score ) 1052{ 1053 IOService *res; 1054 1055 // If our IOUSBInterface has a "do not match" property, it means that we should not match and need 1056 // to bail. See rdar://3716623 1057 1058 OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface")); 1059 if (boolObj && boolObj->isTrue()) 1060 { 1061 XTRACE(this, 0, 0, "probe - Provider doesn't want us to match"); 1062 return NULL; 1063 } 1064 1065 res = super::probe(provider, score); 1066 1067 return res; 1068 1069}/* end probe */ 1070 1071/****************************************************************************************************/ 1072// 1073// Method: AppleUSBCDCACMData::start 1074// 1075// Inputs: provider - my provider 1076// 1077// Outputs: Return code - true (it's me), false (sorry it probably was me, but I can't configure it) 1078// 1079// Desc: This is called once it has been determined I'm probably the best 1080// driver for this device. 1081// 1082/****************************************************************************************************/ 1083 1084bool AppleUSBCDCACMData::start(IOService *provider) 1085{ 1086 IOReturn rtn; 1087 UInt16 devDriverCount = 0; 1088 OSNumber *bufNumber = NULL; 1089 UInt16 bufValue = 0; 1090 IOUSBDevice *usbDevice; 1091 1092 XTRACE(this, 0, 0, "start"); 1093 1094 fSessions = 0; 1095 fTerminate = false; 1096 fSuppressWarning = false; 1097 fEnumOnWake = false; 1098 fStopping = false; 1099 fCDCDriver = NULL; 1100 fControlDriver = NULL; 1101 fWorkLoop = NULL; 1102 fPMRootDomain = NULL; 1103 fWoR = false; 1104 fWakeSettingControllerHandle = NULL; 1105 fWanDevice = kOSBooleanFalse; 1106 fThreadSleepCount = 0; 1107 fReady = false; 1108 1109 initStructure(); 1110 1111 if(!super::start(provider)) 1112 { 1113 ALERT(0, 0, "start - super failed"); 1114 return false; 1115 } 1116 1117 // Get my USB provider - the interface 1118 1119 fDataInterface = OSDynamicCast(IOUSBInterface, provider); 1120 if(!fDataInterface) 1121 { 1122 ALERT(0, 0, "start - provider invalid"); 1123 return false; 1124 } 1125 1126 usbDevice = OSDynamicCast (IOUSBDevice, fDataInterface->GetDevice()); 1127 fWanDevice = (OSBoolean *) usbDevice->getProperty("WWAN"); 1128 fInterfaceMappings = (OSDictionary *) usbDevice->getProperty("InterfaceMapping"); 1129 if (fInterfaceMappings == NULL) 1130 { 1131 1132 fWanDevice = kOSBooleanFalse; 1133 } 1134 else 1135 fWanDevice = kOSBooleanTrue; 1136 1137 1138 fPort.DataInterfaceNumber = fDataInterface->GetInterfaceNumber(); 1139 1140 // See if we can find/wait for the CDC driver 1141 1142 while (!fCDCDriver) 1143 { 1144 rtn = kIOReturnSuccess; 1145 fCDCDriver = findCDCDriverAD(this, fPort.DataInterfaceNumber, &rtn); 1146 if (fCDCDriver) 1147 { 1148 XTRACE (this, 0, 0, "start: Found the CDC device driver"); 1149 break; 1150 } else { 1151 if (rtn == kIOReturnNotReady) 1152 { 1153 devDriverCount++; 1154 XTRACE(this, devDriverCount, fPort.DataInterfaceNumber, "start - Waiting for CDC device driver..."); 1155 if (devDriverCount > 9) 1156 { 1157 break; 1158 } 1159 IOSleep(100); 1160 } else { 1161 break; 1162 } 1163 } 1164 } 1165 1166 // If we didn't find him then we have to bail 1167 1168 if (!fCDCDriver) 1169 { 1170 ALERT(0, fPort.DataInterfaceNumber, "start - Find CDC driver for ACM data interface failed"); 1171 return false; 1172 } 1173 1174 // get workloop 1175 1176 fWorkLoop = getWorkLoop(); 1177 if (!fWorkLoop) 1178 { 1179 ALERT(0, 0, "start - getWorkLoop failed"); 1180 return false; 1181 } 1182 1183 fCommandGate = IOCommandGate::commandGate(this); 1184 if (!fCommandGate) 1185 { 1186 ALERT(0, 0, "start - commandGate failed"); 1187 return false; 1188 } 1189 1190 if (fWorkLoop->addEventSource(fCommandGate) != kIOReturnSuccess) 1191 { 1192 ALERT(0, 0, "start - addEventSource(commandGate) failed"); 1193 return false; 1194 } 1195 1196 // Check for an input buffer pool override first 1197 1198 fInBufPool = 0; 1199 fOutBufPool = 0; 1200 1201 bufNumber = (OSNumber *)provider->getProperty(inputTag); 1202 if (bufNumber) 1203 { 1204 bufValue = bufNumber->unsigned16BitValue(); 1205 XTRACE(this, 0, bufValue, "start - Number of input buffers override value"); 1206 if (bufValue <= kMaxInBufPool) 1207 { 1208 fInBufPool = bufValue; 1209 } else { 1210 fInBufPool = kMaxInBufPool; 1211 } 1212 } else { 1213 fInBufPool = 0; 1214 } 1215 1216 // Now set up the real input buffer pool values (only if not overridden) 1217 1218 if (fInBufPool == 0) 1219 { 1220 bufNumber = NULL; 1221 bufNumber = (OSNumber *)getProperty(inputTag); 1222 if (bufNumber) 1223 { 1224 bufValue = bufNumber->unsigned16BitValue(); 1225 XTRACE(this, 0, bufValue, "start - Number of input buffers requested"); 1226 if (bufValue <= kMaxInBufPool) 1227 { 1228 fInBufPool = bufValue; 1229 } else { 1230 fInBufPool = kMaxInBufPool; 1231 } 1232 } else { 1233 fInBufPool = kInBufPool; 1234 } 1235 } 1236 1237 // Check for an output buffer pool override 1238 1239 bufNumber = NULL; 1240 bufNumber = (OSNumber *)provider->getProperty(outputTag); 1241 if (bufNumber) 1242 { 1243 bufValue = bufNumber->unsigned16BitValue(); 1244 XTRACE(this, 0, bufValue, "start - Number of output buffers override value"); 1245 if (bufValue <= kMaxOutBufPool) 1246 { 1247 fOutBufPool = bufValue; 1248 } else { 1249 fOutBufPool = kMaxOutBufPool; 1250 } 1251 } else { 1252 fOutBufPool = 0; 1253 } 1254 1255 // Now set up the real output buffer pool values (only if not overridden) 1256 1257 if (fOutBufPool == 0) 1258 { 1259 bufNumber = NULL; 1260 bufNumber = (OSNumber *)getProperty(outputTag); 1261 if (bufNumber) 1262 { 1263 bufValue = bufNumber->unsigned16BitValue(); 1264 XTRACE(this, 0, bufValue, "start - Number of output buffers requested"); 1265 if (bufValue <= kMaxOutBufPool) 1266 { 1267 fOutBufPool = bufValue; 1268 } else { 1269 fOutBufPool = kMaxOutBufPool; 1270 } 1271 } else { 1272 fOutBufPool = kOutBufPool; 1273 } 1274 } 1275 1276 XTRACE(this, fInBufPool, fOutBufPool, "start - Buffer pools (input, output)"); 1277 1278 // Check Reset on Close 1279 1280 OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("ResetOnClose")); 1281 if (boolObj && boolObj->isTrue()) 1282 { 1283 fResetOnClose = TRUE; 1284 XTRACE(this, 0, 0, "start - Reset on close is on"); 1285 } else { 1286 fResetOnClose = FALSE; 1287 } 1288 1289 // Check Suppress Warning 1290 1291 OSBoolean *boolObj1 = OSDynamicCast(OSBoolean, provider->getProperty("SuppressWarning")); 1292 if (boolObj1 && boolObj1->isTrue()) 1293 { 1294 fSuppressWarning = TRUE; 1295 XTRACE(this, 0, 0, "start - Suppress Warning is on"); 1296 } else { 1297 fSuppressWarning = FALSE; 1298 } 1299 1300 // Check Enumerate on wake 1301 1302 OSBoolean *boolObj2 = OSDynamicCast(OSBoolean, provider->getProperty("EnumerateOnWake")); 1303 if (boolObj2 && boolObj2->isTrue()) 1304 { 1305 fEnumOnWake = TRUE; 1306 XTRACE(this, 0, 0, "start - Enumerate on wake is on"); 1307 } else { 1308 fEnumOnWake = FALSE; 1309 } 1310 1311 if (!createSerialStream()) // Publish SerialStream services 1312 { 1313 ALERT(0, 0, "start - createSerialStream failed"); 1314 return false; 1315 } 1316 1317 if (!allocateResources()) 1318 { 1319 ALERT(0, 0, "start - allocateResources failed"); 1320 return false; 1321 } 1322 1323 // Looks like we're ok 1324 1325 fDataInterface->retain(); 1326 fWorkLoop->retain(); 1327 fCommandGate->enable(); 1328 1329 gPMWakeOnRingSymbol = OSSymbol::withCString(kIOPMSettingWakeOnRingKey); 1330 1331 if (fConfigAttributes & kUSBAtrRemoteWakeup) 1332 { 1333 XTRACE(this, 0, 0, "start - Remote wake up is supported"); 1334 WakeonRing(); 1335 setWakeFeature(); 1336 if (!setupWakeOnRingPMCallback()) 1337 { 1338 XTRACE(this, 0, 0, "start - Setting the Wake on Ring callback failed"); 1339 } 1340 } else { 1341 XTRACE(this, 0, 0, "start - Remote wake up not supported"); 1342 } 1343 1344 // Save the ID's 1345 1346 fVendorID = fDataInterface->GetDevice()->GetVendorID(); 1347 fProductID = fDataInterface->GetDevice()->GetProductID(); 1348 1349 char vendorString[20]; 1350 char productString[20]; 1351 snprintf(vendorString, sizeof(vendorString), "0x%X", fVendorID); 1352 snprintf(productString, sizeof(productString), "0x%X", fProductID); 1353 1354 cdc_LogToMessageTracer(CDC_ASL_DOMAIN, "AppleUSBCDCACMData", vendorString, productString, 0, 0); 1355 1356 fReady = true; 1357 1358 IOLog(DEBUG_NAME ": Version number - %s, Input buffers %d, Output buffers %d\n", VersionNumber, fInBufPool, fOutBufPool); 1359 1360 return true; 1361 1362}/* end start */ 1363 1364/****************************************************************************************************/ 1365// 1366// Method: AppleUSBCDCACMData::stop 1367// 1368// Inputs: provider - my provider 1369// 1370// Outputs: None 1371// 1372// Desc: Stops the driver 1373// 1374/****************************************************************************************************/ 1375 1376void AppleUSBCDCACMData::stop(IOService *provider) 1377{ 1378 IOReturn ret; 1379 1380 XTRACE(this, 0, 0, "stop"); 1381 1382 fStopping = true; 1383 fReady = false; 1384 1385 retain(); 1386 ret = fCommandGate->runAction(stopAction); 1387 release(); 1388 1389 if (fWakeSettingControllerHandle) 1390 { 1391 fWakeSettingControllerHandle->release(); 1392 } 1393 1394 if (fPMRootDomain) 1395 { 1396 fPMRootDomain->deRegisterInterestedDriver(this); 1397 } 1398 1399 removeProperty((const char *)propertyTag); 1400 1401 super::stop(provider); 1402 1403}/* end stop */ 1404 1405/****************************************************************************************************/ 1406// 1407// Method: AppleUSBCDCACMData::stopAction 1408// 1409// Desc: Dummy pass through for stopGated. 1410// 1411/****************************************************************************************************/ 1412 1413IOReturn AppleUSBCDCACMData::stopAction(OSObject *owner, void *, void *, void *, void *) 1414{ 1415 1416 ((AppleUSBCDCACMData *)owner)->stopGated(); 1417 1418 return kIOReturnSuccess; 1419 1420}/* end stopAction */ 1421 1422/****************************************************************************************************/ 1423// 1424// Method: AppleUSBCDCACMData::stopGated 1425// 1426// Inputs: 1427// 1428// Outputs: 1429// 1430// Desc: Releases the resources 1431// 1432/****************************************************************************************************/ 1433 1434void AppleUSBCDCACMData::stopGated() 1435{ 1436 1437 XTRACE(this, 0, 0, "stopGated"); 1438 1439 releaseResources(); 1440 1441}/* end stopGated */ 1442 1443/****************************************************************************************************/ 1444// 1445// Method: AppleUSBCDCACMData::createSuffix 1446// 1447// Inputs: 1448// 1449// Outputs: return Code - true (suffix created), false (suffix not create) 1450// sufKey - the key 1451// 1452// Desc: Creates the suffix key. It attempts to use the serial number string from the device 1453// if it's reasonable i.e. less than 8 bytes ascii. Remember it's stored in unicode 1454// format. If it's not present or not reasonable it will generate the suffix based 1455// on the location property tag. At least this remains the same across boots if the 1456// device is plugged into the same physical location. In the latter case trailing 1457// zeros are removed. 1458// The interface number is also added to make it unique for 1459// multiple CDC configuration devices. 1460// 1461/****************************************************************************************************/ 1462 1463bool AppleUSBCDCACMData::createSuffix(unsigned char *sufKey) 1464{ 1465 1466 IOReturn rc; 1467 UInt8 serBuf[12]; // arbitrary size > 8 1468 OSNumber *location; 1469 UInt32 locVal; 1470 SInt16 i, sig = 0; 1471 UInt8 indx; 1472 bool keyOK = false; 1473 1474 XTRACE(this, 0, 0, "createSuffix"); 1475 1476 indx = fDataInterface->GetDevice()->GetSerialNumberStringIndex(); 1477 if (indx != 0) 1478 { 1479 // Generate suffix key based on the serial number string (if reasonable <= 8 and > 0) 1480 1481 rc = fDataInterface->GetDevice()->GetStringDescriptor(indx, (char *)&serBuf, sizeof(serBuf)); 1482 if (!rc) 1483 { 1484 if ((strlen((char *)&serBuf) < 9) && (strlen((char *)&serBuf) > 0)) 1485 { 1486 strlcpy((char *)sufKey, (const char *)&serBuf, strlen((char *)&serBuf)); 1487// strcpy((char *)sufKey, (const char *)&serBuf); 1488 sig = strlen((char *)sufKey); 1489 keyOK = true; 1490 } 1491 } else { 1492 XTRACE(this, 0, rc, "createSuffix error reading serial number string"); 1493 } 1494 } 1495 1496 if (!keyOK) 1497 { 1498 // Generate suffix key based on the location property tag 1499 1500 location = (OSNumber *)fDataInterface->GetDevice()->getProperty(kUSBDevicePropertyLocationID); 1501 if (location) 1502 { 1503 locVal = location->unsigned32BitValue(); 1504 snprintf((char *)sufKey, (sizeof(locVal)*2)+1, "%x", (unsigned int)locVal); 1505 sig = strlen((const char *)sufKey)-1; 1506 for (i=sig; i>=0; i--) 1507 { 1508 if (sufKey[i] != '0') 1509 { 1510 break; 1511 } 1512 } 1513 sig = i + 1; 1514 keyOK = true; 1515 } 1516 } 1517 1518 // Make it unique just in case there's more than one CDC configuration on this device 1519 1520 if (keyOK) 1521 { 1522 sufKey[sig] = Asciify((UInt8)fPort.DataInterfaceNumber >> 4); 1523 if (sufKey[sig] != '0') 1524 sig++; 1525 sufKey[sig++] = Asciify((UInt8)fPort.DataInterfaceNumber); 1526 sufKey[sig] = 0x00; 1527 } 1528 1529 return keyOK; 1530 1531}/* end createSuffix */ 1532 1533 1534 1535 1536 1537bool AppleUSBCDCACMData::findSerialBSDClient (IOModemSerialStreamSync *nub) 1538{ 1539 IOReturn resultCode = kIOReturnError; 1540 1541 bsdClientState = 0; 1542 1543 XTRACE (this, 0, 0,"findSerialBSDClient Adding notification with custom matching dictionary"); 1544 bsdClientAddedNotifier = addMatchingNotification (gIOFirstPublishNotification, 1545 serviceMatching("IOSerialBSDClient"), 1546 (IOServiceMatchingNotificationHandler)&bsdClientPublished, 1547 this, 1548 nub); 1549 1550 resultCode = fCommandGate->runAction(waitForBSDClienAction); 1551 XTRACE (this, 0, resultCode, "findSerialBSDClient Exiting...."); 1552 if (resultCode == kIOReturnSuccess) 1553 return TRUE; 1554 else 1555 return FALSE; 1556} 1557 1558/****************************************************************************************************/ 1559// 1560// Method: AppleUSBCDCACMData::waitForBSDClienAction 1561// 1562// Desc: Dummy pass through for sendDeviceRequestGated 1563// 1564/****************************************************************************************************/ 1565 1566IOReturn AppleUSBCDCACMData::waitForBSDClienAction(OSObject *owner, void *, void *, void *, void *) 1567{ 1568 return ((AppleUSBCDCACMData *)owner)->waitForBSDClientGated(); 1569} // end sendDeviceRequestAction 1570 1571 1572/****************************************************************************************************/ 1573// 1574// Method: AppleUSBCDCACMData::waitForBSDClientGated 1575// 1576// Inputs: 1577// 1578// Outputs: return Code - true that the device object appeared 1579// 1580// Desc: wait for the BSDClient object to be ready 1581// 1582/****************************************************************************************************/ 1583 1584IOReturn AppleUSBCDCACMData::waitForBSDClientGated() 1585{ 1586 IOReturn result = kIOReturnSuccess; 1587 1588 AbsoluteTime when; 1589 AbsoluteTime offset; 1590 uint64_t now; 1591 1592 now = mach_absolute_time(); 1593 nanoseconds_to_absolutetime (9000000000ULL, &offset); //rcs We will wait for up to 9 Seconds before timing out.. 1594 ADD_ABSOLUTETIME (&now, &offset); //when we timeout 1595 nanoseconds_to_absolutetime (now, &when); //rcs We will wait for up to 9 Seconds before timing out.. 1596 1597 if (bsdClientState == 1) 1598 { 1599 XTRACE(this, 0, 0, "waitForBSDClientGated - bsdClientState is already 1 no need to wait..."); //Sometimes the match callback gets called before this... 1600 return result; //no Need it was already published.... 1601 } 1602 1603 result = fCommandGate->commandSleep((void *) &bsdClientState,when, THREAD_INTERRUPTIBLE); 1604 // result = fCommandGate->commandSleep((void *) &bsdClientState); 1605 1606 if (result == THREAD_TIMED_OUT) 1607 { 1608 result = kIOReturnTimeout; 1609 XTRACE(this, 0, 0, "waitForBSDClientGated - fCommandGate returned THREAD_TIMED_OUT"); 1610 return result; 1611 } 1612 else if (result == THREAD_INTERRUPTED) 1613 { 1614 result = kIOReturnAborted; 1615 XTRACE(this, 0, 0, "waitForBSDClientGated - fCommandGate returned THREAD_INTERRUPTED"); 1616 return result; 1617 } 1618 1619 XTRACE(this, 0, 0, "waitForBSDClientGated - Exit"); 1620 return result; 1621} 1622 1623bool AppleUSBCDCACMData::bsdClientPublished (AppleUSBCDCACMData * target, void * ref, IOService * newService, IONotifier * notifier) 1624{ 1625 bool resultCode = TRUE; 1626 1627 resultCode = FALSE; // Assume failure 1628 1629 XTRACE(target, 0, 0, "bsdClientPublished"); 1630 1631 if (ref == newService->getProvider()) //is the bsdclient that was just published the one we created (since they can be multiple IOBSDClient objects on any given Sunday) 1632 { 1633 XTRACE (target, 0, 0, "bsdClientPublished - waking up command gate + removing Notifier"); 1634 notifier->remove(); 1635 resultCode = TRUE; 1636 target->bsdClientState = 1; 1637 target->fCommandGate->commandWakeup((void *) &target->bsdClientState); 1638 } 1639 return resultCode; 1640} 1641 1642 1643/****************************************************************************************************/ 1644// 1645// Method: AppleUSBCDCACMData::createSerialStream 1646// 1647// Inputs: 1648// 1649// Outputs: return Code - true (created and initialilzed ok), false (it failed) 1650// 1651// Desc: Creates and initializes the nub 1652// 1653/****************************************************************************************************/ 1654 1655bool AppleUSBCDCACMData::createSerialStream() 1656{ 1657 IOModemSerialStreamSync *pNub = new IOModemSerialStreamSync; 1658 bool ret; 1659 UInt8 indx; 1660 IOReturn rc; 1661 unsigned char rname[20]; 1662 OSString *portName; 1663 const char *suffix = (const char *)&rname; 1664// OSBoolean *hideProp = NULL; 1665 1666 OSString *portSuffixString = NULL; 1667 OSDictionary *fInfoCommands = NULL; 1668 OSDictionary *hiddenProperties = NULL; 1669 UInt32 ttyNameSize = 0; 1670 char *ttyName = NULL; 1671 OSString *ttyNameStr = NULL; 1672 1673 XTRACEP(this, 0, pNub, "createSerialStream"); 1674 if (!pNub) 1675 { 1676 XTRACEP(this, 0, pNub, "createSerialStream - Could not create serial stream"); 1677 return false; 1678 } 1679 1680 // Either we attached and should get rid of our reference 1681 // or we failed in which case we should get rid our reference as well. 1682 // This just makes sure the reference count is correct. 1683 1684 ret = (pNub->init(0, 0) && pNub->attach(this)); 1685 1686 pNub->release(); 1687 if (!ret) 1688 { 1689 XTRACE(this, ret, 0, "createSerialStream - Failed to attach to the nub"); 1690 return false; 1691 } 1692 1693 if (fWanDevice == kOSBooleanTrue) 1694 pNub->setProperty("WWAN", true); 1695 else 1696 { 1697 XTRACE(this, 0, 0, "createSerialStream - NON WAN CDC Device"); 1698 } 1699 1700 1701 // Get the name from the InterfaceMapping dictionary. 1702 1703 portName = getPortNameForInterface(fDataInterface->GetInterfaceNumber()); 1704 if (portName != NULL) 1705 { 1706 pNub->setProperty(kIOTTYBaseNameKey, portName->getCStringNoCopy()); 1707 if (!(portName->isEqualTo("wwan"))) 1708 { 1709 pNub->setProperty((const char *)hiddenTag, true); 1710 pNub->setProperty((const char *)WWANTag, true); 1711 } 1712 } else { 1713 // Report the base name to be used for generating device nodes 1714 1715 if (!fControlDriver) 1716 { 1717 fControlDriver = findControlDriverAD(this); 1718 if (fControlDriver == NULL) 1719 { 1720 return false; 1721 } 1722 } 1723 1724 if (!(fControlDriver->fCMCapabilities & CM_ManagementOnData)) 1725 { 1726 XTRACE(this, 0, 0, "createSerialStream - Interface doesn't support Call Management on Data Interface Hiding port"); 1727 pNub->setProperty((const char *)hiddenTag, true); 1728 } 1729 1730 pNub->setProperty(kIOTTYBaseNameKey, baseName); 1731 XTRACE(this, 0, fDataInterface->GetInterfaceNumber(), "createSerialStream - using default naming and suffix..."); 1732 1733 // Create suffix key and set it 1734 1735 if (createSuffix((unsigned char *)suffix)) 1736 { 1737 pNub->setProperty(kIOTTYSuffixKey, suffix); 1738 } 1739 } 1740 1741 pNub->registerService(kIOServiceSynchronous); 1742 1743 XTRACE(this, 0, 0, "createSerialStream with kIOServiceSynchronous - wait for a sec..."); 1744 if (!findSerialBSDClient(pNub)) 1745 { 1746 XTRACE (this, 0, 0, "createSerialStream - findSerialBSDClient failed terminating nub"); 1747 if (pNub != NULL) 1748 pNub->close(this); 1749 XTRACE (this, 0, 0, "createSerialStream - findSerialBSDClient returning false"); 1750 return false; 1751 } 1752 1753// IOSleep(500); 1754 1755 fInfoCommands = (OSDictionary *) fDataInterface->GetDevice()->getProperty("InfoCommands"); 1756 1757 if ( (fInfoCommands != NULL) && (portName != NULL) ) 1758 { 1759 hiddenProperties = (OSDictionary *) fInfoCommands->getObject("HiddenProperties"); 1760 if (hiddenProperties) 1761 { 1762 portSuffixString = (OSSymbol *) pNub->copyProperty(kIOTTYSuffixKey); 1763 1764 if (portSuffixString != NULL) 1765 { 1766 if ( (portSuffixString->getCStringNoCopy() != NULL) ) 1767 { 1768 OSCollectionIterator *propertyIterator; 1769 propertyIterator = OSCollectionIterator::withCollection( hiddenProperties); 1770 1771 if ( propertyIterator != NULL ) 1772 { 1773 OSString *key; 1774 propertyIterator->reset(); 1775 1776 while( key = (OSString *)propertyIterator->getNextObject()) 1777 { 1778 OSString *value; 1779 value = (OSString *) hiddenProperties->getObject(key); 1780 1781 if (value->isEqualTo(portName)) 1782 { 1783 ttyNameSize = (portSuffixString->getLength() + portName->getLength() ); 1784 ttyName = (char *)IOMallocAligned(ttyNameSize+4, sizeof (char)); 1785 bzero(ttyName,ttyNameSize+4); 1786 strncpy(ttyName, value->getCStringNoCopy(), value->getLength()); 1787 strncat(ttyName, portSuffixString->getCStringNoCopy(), portSuffixString->getLength()); 1788 1789 ttyNameStr = OSString::withCString(ttyName); 1790 if ( ttyNameStr != NULL ) 1791 { 1792 //OSString *foo; 1793 XTRACE(this, 0, 0, "createSerialStream - hiddenProperties: collision"); 1794 fDataInterface->GetDevice()->setProperty(key->getCStringNoCopy(),ttyNameStr); 1795 //hiddenProperties->setObject(key->getCStringNoCopy(),ttyNameStr); 1796 1797 //foo = (OSString *)hiddenProperties->getObject(key->getCStringNoCopy()); 1798 //hiddenProperties->setObject(foo,ttyNameStr); 1799 } 1800 } 1801 } 1802 propertyIterator->release(); 1803 } else { XTRACE(this, 0, 0, "createSerialStream - propertyIterator is NULL...");} 1804 } else { XTRACE(this, 0, 0, "createSerialStream - portSuffixString->getCStringNoCopy is NULL...");} 1805 } else { XTRACE(this, 0, 0, "createSerialStream - portSuffixString is NULL...");} 1806 } else { XTRACE(this, 0, 0, "createSerialStream - hiddenProperties is NULL...");} 1807 } else { XTRACE(this, 0, fDataInterface->GetInterfaceNumber(), "createSerialStream - fInfoCommands or portname is NULL...");} 1808 1809 // Save the Product String (at least the first productNameLength's worth). 1810 1811 indx = fDataInterface->GetDevice()->GetProductStringIndex(); 1812 if (indx != 0) 1813 { 1814 rc = fDataInterface->GetDevice()->GetStringDescriptor(indx, (char *)&fProductName, sizeof(fProductName)); 1815 if (!rc) 1816 { 1817 if (strlen((char *)fProductName) == 0) // Believe it or not this sometimes happens - null string with an index defined??? 1818 { 1819 strlcpy((char *)fProductName, defaultName, sizeof(defaultName)); 1820// strcpy((char *)fProductName, defaultName); 1821 } 1822 pNub->setProperty((const char *)propertyTag, (const char *)fProductName); 1823 } 1824 } 1825 1826 return true; 1827 1828}/* end createSerialStream */ 1829 1830/****************************************************************************************************/ 1831// 1832// Method: AppleUSBCDCACMData::acquirePort 1833// 1834// Inputs: sleep - true (wait for it), false (don't) 1835// refCon - unused 1836// 1837// Outputs: Return Code - kIOReturnSuccess, kIOReturnExclusiveAccess, kIOReturnIOError and various others 1838// 1839// Desc: Set up for gated acquirePort call. 1840// 1841/****************************************************************************************************/ 1842 1843IOReturn AppleUSBCDCACMData::acquirePort(bool sleep, void *refCon) 1844{ 1845 IOReturn ret; 1846 1847 XTRACEP(this, refCon, 0, "acquirePort"); 1848 1849 // Check for being acquired after stop has been issued and before start 1850 1851 if (fTerminate || fStopping) 1852 { 1853 XTRACE(this, 0, 0, "acquirePort - Offline"); 1854 return kIOReturnOffline; 1855 } 1856 1857 // Make sure we have a valid workloop 1858 1859 if (!fWorkLoop) 1860 { 1861 XTRACE(this, 0, 0, "acquirePort - No workLoop"); 1862 return kIOReturnOffline; 1863 } 1864 1865 // Make sure start has finished (could be different threads) 1866 1867 if (!fReady) 1868 { 1869 XTRACE(this, 0, 0, "acquirePort - Not ready"); 1870 return kIOReturnNotReady; 1871 } 1872 1873 // Find the matching control driver first (we're obviously not ready if he hasn't arrived) 1874 1875 if (!fControlDriver) 1876 { 1877 fControlDriver = findControlDriverAD(this); 1878 if (fControlDriver == NULL) 1879 { 1880 XTRACE(this, 0, 0, "acquirePort - Cannot find control driver"); 1881 return kIOReturnNotReady; 1882 } 1883 } 1884 1885 retain(); 1886 ret = fCommandGate->runAction(acquirePortAction, (void *)sleep); 1887 release(); 1888 1889 return ret; 1890 1891}/* end acquirePort */ 1892 1893/****************************************************************************************************/ 1894// 1895// Method: AppleUSBCDCACMData::acquirePortAction 1896// 1897// Desc: Dummy pass through for acquirePortGated. 1898// 1899/****************************************************************************************************/ 1900 1901IOReturn AppleUSBCDCACMData::acquirePortAction(OSObject *owner, void *arg0, void *, void *, void *) 1902{ 1903 1904 return ((AppleUSBCDCACMData *)owner)->acquirePortGated((bool)arg0); 1905 1906}/* end acquirePortAction */ 1907 1908/****************************************************************************************************/ 1909// 1910// Method: AppleUSBCDCACMData::acquirePortGated 1911// 1912// Inputs: sleep - true (wait for it), false (don't) 1913// 1914// Outputs: Return Code - kIOReturnSuccess, kIOReturnExclusiveAccess, kIOReturnIOError and various others 1915// 1916// Desc: acquirePort tests and sets the state of the port object. If the port was 1917// available, then the state is set to busy, and kIOReturnSuccess is returned. 1918// If the port was already busy and sleep is YES, then the thread will sleep 1919// until the port is freed, then re-attempts the acquire. If the port was 1920// already busy and sleep is NO, then kIOReturnExclusiveAccess is returned. 1921// 1922/****************************************************************************************************/ 1923 1924IOReturn AppleUSBCDCACMData::acquirePortGated(bool sleep) 1925{ 1926 UInt32 busyState = 0; 1927 IOReturn rtn = kIOReturnSuccess; 1928 UInt16 i; 1929 UInt32 state; 1930 UInt32 mask; 1931 1932 XTRACE(this, 0, sleep, "acquirePortGated"); 1933 1934 retain(); // Hold reference till releasePortGated, unless we fail to acquire 1935 while (true) 1936 { 1937 busyState = fPort.State & PD_S_ACQUIRED; 1938 if (!busyState) 1939 { 1940 // Set busy bit (acquired), and clear everything else 1941 1942 state = PD_S_ACQUIRED | DEFAULT_STATE; 1943 mask = STATE_ALL; 1944 setStateGated(&state, &mask); 1945 break; 1946 } else { 1947 if (!sleep) 1948 { 1949 XTRACE(this, 0, 0, "acquirePortGated - Busy exclusive access"); 1950 release(); 1951 return kIOReturnExclusiveAccess; 1952 } else { 1953 busyState = 0; 1954 mask = PD_S_ACQUIRED; 1955 rtn = watchStateGated(&busyState, &mask); 1956 if ((rtn == kIOReturnIOError) || (rtn == kIOReturnSuccess)) 1957 { 1958 continue; 1959 } else { 1960 XTRACE(this, 0, 0, "acquirePortGated - Interrupted!"); 1961 release(); 1962 return rtn; 1963 } 1964 } 1965 } 1966 } 1967 1968 do 1969 { 1970 setStructureDefaults(); // Set the default values 1971 1972 1973 if (!createSerialRingBuffers()) 1974 { 1975 XTRACE(this, 0, 0, "acquirePortGated failed to createSerialRingBuffers"); 1976 rtn = kIOReturnNoMemory; 1977 break; 1978 } 1979 1980 // Set up and read the data-in bulk pipe 1981 1982 for (i=0; i<fInBufPool; i++) 1983 { 1984 if (fPort.inPool[i].pipeMDP) 1985 { 1986 fPort.inPool[i].completionInfo.target = this; 1987 fPort.inPool[i].completionInfo.action = dataReadComplete; 1988 fPort.inPool[i].completionInfo.parameter = (void *)&fPort.inPool[i]; 1989 rtn = fPort.InPipe->Read(fPort.inPool[i].pipeMDP, &fPort.inPool[i].completionInfo, NULL); 1990 if (rtn != kIOReturnSuccess) 1991 { 1992 XTRACE(this, i, rtn, "acquirePortGated - Read for bulk-in pipe failed"); 1993 fPort.inPool[i].dead = true; 1994 break; 1995 } 1996 XTRACEP(this, &fPort.inPool[i], fPort.InPipe, "acquirePortGated - Read posted"); 1997 } 1998 } 1999 if (rtn == kIOReturnSuccess) 2000 { 2001 2002 // Set up the data-out bulk pipe 2003 2004 for (i=0; i<fOutBufPool; i++) 2005 { 2006 if (fPort.outPool[i].pipeMDP) 2007 { 2008 fPort.outPool[i].completionInfo.target = this; 2009 fPort.outPool[i].completionInfo.action = dataWriteComplete; 2010 fPort.outPool[i].completionInfo.parameter = (void *)&fPort.outPool[i]; 2011 } 2012 } 2013 } else { 2014 break; 2015 } 2016 2017 fSessions++; // Bump number of active sessions and turn on clear to send 2018 state = PD_RS232_S_CTS; 2019 mask = PD_RS232_S_CTS; 2020 setStateGated(&state, &mask); 2021 2022 // Tell the Control driver we're good to go 2023 2024 if (fControlDriver) 2025 { 2026 if (!fControlDriver->dataAcquired()) 2027 { 2028 XTRACE(this, 0, 0, "acquirePortGated - dataAcquired to Control failed"); 2029 break; 2030 } 2031 } 2032 2033 return kIOReturnSuccess; 2034 2035 } while (0); 2036 2037 // We failed for some reason 2038 2039 state = 0; 2040 mask = STATE_ALL; 2041 setStateGated(&state, &mask); // Clear the entire state 2042 2043 release(); 2044 2045 return rtn; 2046 2047}/* end acquirePortGated */ 2048 2049/****************************************************************************************************/ 2050// 2051// Method: AppleUSBCDCACMData::releasePort 2052// 2053// Inputs: refCon - unused 2054// 2055// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 2056// 2057// Desc: Set up for gated releasePort call. 2058// 2059/****************************************************************************************************/ 2060 2061IOReturn AppleUSBCDCACMData::releasePort(void *refCon) 2062{ 2063 IOReturn ret = kIOReturnSuccess; 2064 2065 XTRACE(this, 0, 0, "releasePort"); 2066 2067 // Abort any outstanding I/O (only if we're not terminated) 2068 2069 if (!fTerminate) 2070 { 2071 if (fPort.InPipe) 2072 fPort.InPipe->Abort(); 2073 if (fPort.OutPipe) 2074 fPort.OutPipe->Abort(); 2075 } 2076 2077// IOSleep(10); 2078 2079 retain(); 2080 ret = fCommandGate->runAction(releasePortAction); 2081 release(); 2082 2083 // Check the pipes before we leave (only if we're not terminated) 2084 // and Reset on Close is true. This resets the data toggle on both ends 2085 2086 if (!fTerminate) 2087 { 2088 if (fResetOnClose) 2089 { 2090 if (fPort.InPipe) 2091 checkPipe(fPort.InPipe, true); 2092 2093 if (fPort.OutPipe) 2094 checkPipe(fPort.OutPipe, true); 2095 2096 if (fDataInterface) 2097 { 2098 ret = fDataInterface->GetDevice()->ResetDevice(); 2099 if (ret != kIOReturnSuccess) 2100 { 2101 XTRACE(this, 0, ret, "releasePort - ResetDevice failed"); 2102 } 2103 } 2104 } 2105 } else { 2106 clearSleepingThreads(); 2107 } 2108 2109 return ret; 2110 2111}/* end releasePort */ 2112 2113/****************************************************************************************************/ 2114// 2115// Method: AppleUSBCDCACMData::releasePortAction 2116// 2117// Desc: Dummy pass through for releasePortGated. 2118// 2119/****************************************************************************************************/ 2120 2121IOReturn AppleUSBCDCACMData::releasePortAction(OSObject *owner, void *, void *, void *, void *) 2122{ 2123 2124 return ((AppleUSBCDCACMData *)owner)->releasePortGated(); 2125 2126}/* end releasePortAction */ 2127 2128/****************************************************************************************************/ 2129// 2130// Method: AppleUSBCDCACMData::releasePortGated 2131// 2132// Inputs: 2133// 2134// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 2135// 2136// Desc: releasePort returns all the resources and does clean up. 2137// 2138/****************************************************************************************************/ 2139 2140IOReturn AppleUSBCDCACMData::releasePortGated() 2141{ 2142 UInt32 busyState; 2143 UInt32 state; 2144 UInt32 mask; 2145 2146 XTRACE(this, 0, 0, "releasePortGated"); 2147 2148 busyState = (fPort.State & PD_S_ACQUIRED); 2149 if (!busyState) 2150 { 2151 if (fTerminate || fStopping) 2152 { 2153 XTRACE(this, 0, 0, "releasePortGated - Offline"); 2154 return kIOReturnOffline; 2155 } 2156 2157 XTRACE(this, 0, 0, "releasePortGated - Not open"); 2158 return kIOReturnNotOpen; 2159 } 2160 2161 if (!fTerminate) 2162 setControlLineState(false, false); // clear RTS and clear DTR only if not terminated 2163 2164 state = 0; 2165 mask = STATE_ALL; 2166 setStateGated(&state, &mask); // Clear the entire state word - which also deactivates the port 2167 2168#if 0 2169 // Abort any outstanding I/O 2170 2171 if (fPort.InPipe) 2172 fPort.InPipe->Abort(); 2173 if (fPort.OutPipe) 2174 fPort.OutPipe->Abort(); 2175#endif 2176 2177 // Tell the Control driver the port's been released, only when not terminated (control driver may already be gone) 2178 2179 if (!fTerminate) 2180 { 2181 if (fControlDriver) 2182 { 2183 fControlDriver->dataReleased(); 2184 } 2185 } 2186 2187 fSessions--; // reduce number of active sessions 2188 2189 2190 if (fPort.ringsAllocated == true) 2191 { 2192 XTRACE(this, 0, 0, "releasePortGated - freeing rings"); 2193 freeRingBuffer(&fPort.TX); 2194 freeRingBuffer(&fPort.RX); 2195 fPort.ringsAllocated = false; 2196 } 2197 2198 release(); // Dispose of the self-reference we took in acquirePortGated() 2199 2200 XTRACE(this, 0, 0, "releasePort - Exit"); 2201 2202 return kIOReturnSuccess; 2203 2204}/* end releasePortGated */ 2205 2206/****************************************************************************************************/ 2207// 2208// Method: AppleUSBCDCACMData::getState 2209// 2210// Inputs: refCon - unused 2211// 2212// Outputs: Return value - port state 2213// 2214// Desc: Set up for gated getState call. 2215// 2216/****************************************************************************************************/ 2217 2218UInt32 AppleUSBCDCACMData::getState(void *refCon) 2219{ 2220 UInt32 currState; 2221 2222 XTRACE(this, 0, 0, "getState"); 2223 2224 if (fTerminate || fStopping) 2225 { 2226 XTRACE(this, 0, kIOReturnOffline, "getState - Offline"); 2227 return 0; 2228 } 2229 2230 retain(); 2231 currState = fCommandGate->runAction(getStateAction); 2232 release(); 2233 2234 return currState; 2235 2236}/* end getState */ 2237 2238/****************************************************************************************************/ 2239// 2240// Method: AppleUSBCDCACMData::getStateAction 2241// 2242// Desc: Dummy pass through for getStateGated. 2243// 2244/****************************************************************************************************/ 2245 2246IOReturn AppleUSBCDCACMData::getStateAction(OSObject *owner, void *, void *, void *, void *) 2247{ 2248 UInt32 newState; 2249 2250 newState = ((AppleUSBCDCACMData *)owner)->getStateGated(); 2251 2252 return newState; 2253 2254}/* end getStateAction */ 2255 2256/****************************************************************************************************/ 2257// 2258// Method: AppleUSBCDCACMData::getStateGated 2259// 2260// Inputs: port - unused 2261// 2262// Outputs: return value - port state 2263// 2264// Desc: Get the state for the port. 2265// 2266/****************************************************************************************************/ 2267 2268UInt32 AppleUSBCDCACMData::getStateGated() 2269{ 2270 UInt32 state; 2271 2272 XTRACE(this, 0, 0, "getStateGated"); 2273 2274 if (fTerminate || fStopping) 2275 return 0; 2276 2277 CheckQueues(); 2278 2279 state = fPort.State & EXTERNAL_MASK; 2280 2281 XTRACE(this, state, EXTERNAL_MASK, "getStateGated - Exit"); 2282 2283 return state; 2284 2285}/* end getStateGated */ 2286 2287/****************************************************************************************************/ 2288// 2289// Method: AppleUSBCDCACMData::setState 2290// 2291// Inputs: state - the state 2292// mask - the mask 2293// refCon - unused 2294// 2295// Outputs: Return code - kIOReturnSuccess or kIOReturnBadArgument 2296// 2297// Desc: Set up for gated setState call. 2298// 2299/****************************************************************************************************/ 2300 2301IOReturn AppleUSBCDCACMData::setState(UInt32 state, UInt32 mask, void *refCon) 2302{ 2303 IOReturn ret = kIOReturnSuccess; 2304 2305 XTRACE(this, 0, 0, "setState"); 2306 2307 if (fTerminate || fStopping) 2308 { 2309 XTRACE(this, 0, kIOReturnOffline, "setState - Offline"); 2310 return 0; 2311 } 2312 2313 // Cannot acquire or activate via setState 2314 2315 if (mask & (PD_S_ACQUIRED | PD_S_ACTIVE | (~EXTERNAL_MASK))) 2316 { 2317 ret = kIOReturnBadArgument; 2318 } else { 2319 2320 // ignore any bits that are read-only 2321 2322 mask &= (~fPort.FlowControl & PD_RS232_A_MASK) | PD_S_MASK; 2323 if (mask) 2324 { 2325 retain(); 2326 ret = fCommandGate->runAction(setStateAction, (void *)&state, (void *)&mask); 2327 release(); 2328 } 2329 } 2330 2331 return ret; 2332 2333}/* end setState */ 2334 2335/****************************************************************************************************/ 2336// 2337// Method: AppleUSBCDCACMData::setStateAction 2338// 2339// Desc: Dummy pass through for setStateGated. 2340// 2341/****************************************************************************************************/ 2342 2343IOReturn AppleUSBCDCACMData::setStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *) 2344{ 2345 2346 return ((AppleUSBCDCACMData *)owner)->setStateGated((UInt32 *)arg0, (UInt32 *)arg1); 2347 2348}/* end setStateAction */ 2349 2350/****************************************************************************************************/ 2351// 2352// Method: AppleUSBCDCACMData::setStateGated 2353// 2354// Inputs: state - state to set 2355// mask - state mask 2356// 2357// Outputs: Return Code - kIOReturnSuccess or kIOReturnBadArgument 2358// 2359// Desc: Set the state for the port device. The lower 16 bits are used to set the 2360// state of various flow control bits (this can also be done by enqueueing a 2361// PD_E_FLOW_CONTROL event). If any of the flow control bits have been set 2362// for automatic control, then they can't be changed by setState. For flow 2363// control bits set to manual (that are implemented in hardware), the lines 2364// will be changed before this method returns. The one weird case is if RXO 2365// is set for manual, then an XON or XOFF character may be placed at the end 2366// of the TXQ and transmitted later. 2367// 2368/****************************************************************************************************/ 2369 2370IOReturn AppleUSBCDCACMData::setStateGated(UInt32 *pState, UInt32 *pMask) 2371{ 2372 UInt32 state = *pState; 2373 UInt32 mask = *pMask; 2374 UInt32 delta; 2375 bool controlUpdate = false; 2376 UInt32 DTRstate; 2377 UInt32 RTSstate; 2378 bool DTRnew = false; 2379 bool RTSnew = false; 2380 2381 XTRACE(this, state, mask, "setStateGated"); 2382 2383 if (fStopping) 2384 return kIOReturnOffline; 2385 2386 // Check if it's being acquired or already acquired 2387 2388 if ((state & PD_S_ACQUIRED) || (fPort.State & PD_S_ACQUIRED)) 2389 { 2390 XTRACE(this, state, mask, "setState - Requested state and mask"); 2391 XTRACE(this, 0, fPort.State, "setState - Current state"); 2392 DTRstate = fPort.State & PD_RS232_S_DTR; 2393 RTSstate = fPort.State & PD_RS232_S_RTS; 2394 XTRACE(this, DTRstate, RTSstate, "setState - DTRstate and RTSstate"); 2395 2396 // Set the new state based on the current setting 2397 2398 if (fPort.State & PD_RS232_S_DTR) 2399 { 2400 DTRnew = true; 2401 } 2402 if (fPort.State & PD_RS232_S_RTS) 2403 { 2404 RTSnew = true; 2405 } 2406 XTRACE(this, DTRnew, RTSnew, "setState - DTRstate and RTSstate"); 2407 2408 // Handle DTR and RTS changes for the modem 2409 2410 if (mask & PD_RS232_S_DTR) 2411 { 2412 if ((state & PD_RS232_S_DTR) != (fPort.State & PD_RS232_S_DTR)) 2413 { 2414 controlUpdate = true; 2415 if (state & PD_RS232_S_DTR) 2416 { 2417 XTRACE(this, 0, 0, "setState - Changing DTR to ON"); 2418 DTRnew = true; 2419 } else { 2420 XTRACE(this, 0, 0, "setState - Changing DTR to OFF"); 2421 DTRnew = false; 2422 } 2423 } else { 2424 XTRACE(this, 0, DTRstate, "setState - DTR state unchanged"); 2425 } 2426 } 2427 if (mask & PD_RS232_S_RTS) 2428 { 2429 if ((state & PD_RS232_S_RTS) != (fPort.State & PD_RS232_S_RTS)) 2430 { 2431 controlUpdate = true; 2432 if (state & PD_RS232_S_RTS) 2433 { 2434 XTRACE(this, 0, 0, "setState - Changing RTS to ON"); 2435 RTSnew = true; 2436 } else { 2437 XTRACE(this, 0, 0, "setState - Changing RTS to OFF"); 2438 RTSnew = false; 2439 } 2440 } else { 2441 XTRACE(this, 0, RTSstate, "setState - RTS state unchanged"); 2442 } 2443 } 2444 2445 XTRACE(this, DTRnew, RTSnew, "setState - DTRnew and RTSnew"); 2446 2447 if ((!fTerminate) && (controlUpdate)) 2448 { 2449 setControlLineState(RTSnew, DTRnew); 2450 } 2451 2452 state = (fPort.State & ~mask) | (state & mask); // compute the new state 2453 delta = state ^ fPort.State; // keep a copy of the diffs 2454 fPort.State = state; 2455 2456 // Wake up all threads asleep on WatchStateMask 2457 2458 if (delta & fPort.WatchStateMask) 2459 { 2460 fCommandGate->commandWakeup((void *)&fPort.State); 2461 } 2462 2463 return kIOReturnSuccess; 2464 2465 } else { 2466 XTRACE(this, fPort.State, 0, "setStateGated - Not Acquired"); 2467 } 2468 2469 return kIOReturnNotOpen; 2470 2471}/* end setStateGated */ 2472 2473/****************************************************************************************************/ 2474// 2475// Method: AppleUSBCDCACMData::watchState 2476// 2477// Inputs: state - state to watch for 2478// mask - state mask bits 2479// refCon - unused 2480// 2481// Outputs: Return Code - kIOReturnSuccess or value returned from ::watchState 2482// 2483// Desc: Set up for gated watchState call. 2484// 2485/****************************************************************************************************/ 2486 2487IOReturn AppleUSBCDCACMData::watchState(UInt32 *state, UInt32 mask, void *refCon) 2488{ 2489 IOReturn ret; 2490 2491 XTRACE(this, *state, mask, "watchState"); 2492 2493 if (fTerminate || fStopping) 2494 { 2495 XTRACE(this, 0, kIOReturnOffline, "watchState - Offline"); 2496 return kIOReturnOffline; 2497 } 2498 2499 if (!state) 2500 return kIOReturnBadArgument; 2501 2502 if (!mask) 2503 return kIOReturnSuccess; 2504 2505 retain(); 2506 ret = fCommandGate->runAction(watchStateAction, (void *)state, (void *)&mask); 2507 release(); 2508 2509 return ret; 2510 2511}/* end watchState */ 2512 2513/****************************************************************************************************/ 2514// 2515// Method: AppleUSBCDCACMData::watchStateAction 2516// 2517// Desc: Dummy pass through for watchStateGated. 2518// 2519/****************************************************************************************************/ 2520 2521IOReturn AppleUSBCDCACMData::watchStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *) 2522{ 2523 2524 return ((AppleUSBCDCACMData *)owner)->watchStateGated((UInt32 *)arg0, (UInt32 *)arg1); 2525 2526}/* end watchStateAction */ 2527 2528/****************************************************************************************************/ 2529// 2530// Method: AppleUSBCDCACMData::watchStateGated 2531// 2532// Inputs: state - state to watch for 2533// mask - state mask bits 2534// 2535// Outputs: Return Code - kIOReturnSuccess or value returned from privateWatchState 2536// 2537// Desc: Wait for the at least one of the state bits defined in mask to be equal 2538// to the value defined in state. Check on entry then sleep until necessary, 2539// A return value of kIOReturnSuccess means that at least one of the port state 2540// bits specified by mask is equal to the value passed in by state. A return 2541// value of kIOReturnIOError indicates that the port went inactive. A return 2542// value of kIOReturnIPCError indicates sleep was interrupted by a signal. 2543// 2544/****************************************************************************************************/ 2545 2546IOReturn AppleUSBCDCACMData::watchStateGated(UInt32 *pState, UInt32 *pMask) 2547{ 2548 UInt32 mask = *pMask; 2549 UInt32 watchState, foundStates; 2550 bool autoActiveBit = false; 2551 IOReturn ret = kIOReturnNotOpen; 2552 2553 XTRACE(this, *pState, mask, "watchStateGated"); 2554 2555 if (fTerminate || fStopping) 2556 return kIOReturnOffline; 2557 2558 if (fPort.State & PD_S_ACQUIRED) 2559 { 2560 ret = kIOReturnSuccess; 2561 mask &= EXTERNAL_MASK; 2562 2563 watchState = *pState; 2564 if (!(mask & (PD_S_ACQUIRED | PD_S_ACTIVE))) 2565 { 2566 watchState &= ~PD_S_ACTIVE; // Check for low PD_S_ACTIVE 2567 mask |= PD_S_ACTIVE; // Register interest in PD_S_ACTIVE bit 2568 autoActiveBit = true; 2569 } 2570 2571 while (true) 2572 { 2573 // Check port state for any interesting bits with watchState value 2574 // NB. the '^ ~' is a XNOR and tests for equality of bits. 2575 2576 foundStates = (watchState ^ ~fPort.State) & mask; 2577 2578 if (foundStates) 2579 { 2580 *pState = fPort.State; 2581 if (autoActiveBit && (foundStates & PD_S_ACTIVE)) 2582 { 2583 ret = kIOReturnIOError; 2584 } else { 2585 ret = kIOReturnSuccess; 2586 } 2587 break; 2588 } 2589 2590 // Everytime we go around the loop we have to reset the watch mask. 2591 // This means any event that could affect the WatchStateMask must 2592 // wakeup all watch state threads. The two events are an interrupt 2593 // or one of the bits in the WatchStateMask changing. 2594 2595 fPort.WatchStateMask |= mask; 2596 2597 XTRACE(this, fPort.State, fPort.WatchStateMask, "watchStateGated - Thread sleeping"); 2598 2599 retain(); // Just to make sure all threads are awake 2600 fCommandGate->retain(); // before we're released 2601 2602 fThreadSleepCount++; 2603 2604 ret = fCommandGate->commandSleep((void *)&fPort.State); 2605 2606 fThreadSleepCount--; 2607 2608 fCommandGate->release(); 2609 2610 XTRACE(this, fPort.State, ret, "watchStateGated - Thread restart"); 2611 2612 if (ret == THREAD_TIMED_OUT) 2613 { 2614 ret = kIOReturnTimeout; 2615 release(); 2616 break; 2617 } else { 2618 if (ret == THREAD_INTERRUPTED) 2619 { 2620 ret = kIOReturnAborted; 2621 release(); 2622 break; 2623 } else { 2624 if (fTerminate || fStopping) // Make sure we not terminated or stopping 2625 { 2626 ret = kIOReturnOffline; 2627 release(); 2628 break; 2629 } 2630 } 2631 } 2632 release(); 2633 } 2634 2635 // As it is impossible to undo the masking used by this 2636 // thread, we clear down the watch state mask and wakeup 2637 // every sleeping thread to reinitialize the mask before exiting. 2638 2639 fPort.WatchStateMask = 0; 2640 XTRACE(this, *pState, 0, "watchStateGated - Thread wakeing others"); 2641 fCommandGate->commandWakeup((void *)&fPort.State); 2642 2643 *pState &= EXTERNAL_MASK; 2644 } 2645 2646 XTRACE(this, ret, 0, "watchState - Exit"); 2647 2648 return ret; 2649 2650}/* end watchStateGated */ 2651 2652/****************************************************************************************************/ 2653// 2654// Method: AppleUSBCDCACMData::nextEvent 2655// 2656// Inputs: refCon - unused 2657// 2658// Outputs: Return Code - kIOReturnSuccess or kIOReturnOffline 2659// 2660// Desc: Not used by this driver. 2661// 2662/****************************************************************************************************/ 2663 2664UInt32 AppleUSBCDCACMData::nextEvent(void *refCon) 2665{ 2666 2667 XTRACE(this, 0, 0, "nextEvent"); 2668 2669 if (fTerminate || fStopping) 2670 return kIOReturnOffline; 2671 2672 if (getState(&fPort) & PD_S_ACTIVE) 2673 { 2674 return kIOReturnSuccess; 2675 } 2676 2677 return kIOReturnNotOpen; 2678 2679}/* end nextEvent */ 2680 2681/****************************************************************************************************/ 2682// 2683// Method: AppleUSBCDCACMData::executeEvent 2684// 2685// Inputs: event - The event 2686// data - any data associated with the event 2687// refCon - unused 2688// 2689// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen or kIOReturnBadArgument 2690// 2691// Desc: Set up for gated executeEvent call. 2692// 2693/****************************************************************************************************/ 2694 2695IOReturn AppleUSBCDCACMData::executeEvent(UInt32 event, UInt32 data, void *refCon) 2696{ 2697 IOReturn ret; 2698 2699 XTRACE(this, data, event, "executeEvent"); 2700 2701 if (fTerminate || fStopping) 2702 { 2703 XTRACE(this, 0, kIOReturnOffline, "executeEvent - Offline"); 2704 return kIOReturnOffline; 2705 } 2706 2707 retain(); 2708 ret = fCommandGate->runAction(executeEventAction, (void *)&event, (void *)&data); 2709 release(); 2710 2711 return ret; 2712 2713}/* end executeEvent */ 2714 2715/****************************************************************************************************/ 2716// 2717// Method: AppleUSBCDCACMData::executeEventAction 2718// 2719// Desc: Dummy pass through for executeEventGated. 2720// 2721/****************************************************************************************************/ 2722 2723IOReturn AppleUSBCDCACMData::executeEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *) 2724{ 2725 2726 return ((AppleUSBCDCACMData *)owner)->executeEventGated((UInt32 *)arg0, (UInt32 *)arg1); 2727 2728}/* end executeEventAction */ 2729 2730/****************************************************************************************************/ 2731// 2732// Method: AppleUSBCDCACMData::executeEventGated 2733// 2734// Inputs: event - The event 2735// data - any data associated with the event 2736// 2737// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen or kIOReturnBadArgument 2738// 2739// Desc: executeEvent causes the specified event to be processed immediately. 2740// This is primarily used for channel control commands like START & STOP 2741// 2742/****************************************************************************************************/ 2743 2744IOReturn AppleUSBCDCACMData::executeEventGated(UInt32 *pEvent, UInt32 *pData) 2745{ 2746 UInt32 event = *pEvent; 2747 UInt32 data = *pData; 2748 IOReturn ret = kIOReturnSuccess; 2749 UInt32 state, delta; 2750 UInt32 nState; 2751 UInt32 mask; 2752 2753 if (fTerminate || fStopping) 2754 return kIOReturnOffline; 2755 2756 delta = 0; 2757 state = fPort.State; 2758 XTRACE(this, state, event, "executeEventGated"); 2759 2760 if ((state & PD_S_ACQUIRED) == 0) 2761 return kIOReturnNotOpen; 2762 2763 switch (event) 2764 { 2765 case PD_RS232_E_XON_BYTE: 2766 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_XON_BYTE"); 2767 fPort.XONchar = data; 2768 break; 2769 case PD_RS232_E_XOFF_BYTE: 2770 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_XOFF_BYTE"); 2771 fPort.XOFFchar = data; 2772 break; 2773 case PD_E_SPECIAL_BYTE: 2774 XTRACE(this, data, event, "executeEventGated - PD_E_SPECIAL_BYTE"); 2775 fPort.SWspecial[ data >> SPECIAL_SHIFT ] |= (1 << (data & SPECIAL_MASK)); 2776 break; 2777 case PD_E_VALID_DATA_BYTE: 2778 XTRACE(this, data, event, "executeEventGated - PD_E_VALID_DATA_BYTE"); 2779 fPort.SWspecial[ data >> SPECIAL_SHIFT ] &= ~(1 << (data & SPECIAL_MASK)); 2780 break; 2781 case PD_E_FLOW_CONTROL: 2782 XTRACE(this, data, event, "executeEventGated - PD_E_FLOW_CONTROL"); 2783 break; 2784 case PD_E_ACTIVE: 2785 XTRACE(this, data, event, "executeEventGated - PD_E_ACTIVE"); 2786 if ((bool)data) 2787 { 2788 if (!(state & PD_S_ACTIVE)) 2789 { 2790 setStructureDefaults(); 2791 nState = PD_S_ACTIVE; 2792 mask = PD_S_ACTIVE; 2793 setStateGated(&nState, &mask); // activate port 2794 2795 nState = PD_RS232_S_RTS; 2796 mask = PD_RS232_S_RTS; 2797 setStateGated(&nState, &mask); 2798 2799 nState = PD_RS232_S_DTR; 2800 mask = PD_RS232_S_DTR; 2801 setStateGated(&nState, &mask); 2802 2803 // setControlLineState(true, true); // set RTS and set DTR 2804 } 2805 } else { 2806 if ((state & PD_S_ACTIVE)) 2807 { 2808 nState = 0; 2809 mask = PD_S_ACTIVE; 2810 setStateGated(&nState, &mask); // deactivate port 2811 2812 setControlLineState(false, false); // clear RTS and clear DTR 2813 } 2814 } 2815 break; 2816 case PD_E_DATA_LATENCY: 2817 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_LATENCY"); 2818 fPort.DataLatInterval = long2tval(data * 1000); 2819 break; 2820 case PD_RS232_E_MIN_LATENCY: 2821 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_MIN_LATENCY"); 2822 fPort.MinLatency = bool(data); 2823 break; 2824 case PD_E_DATA_INTEGRITY: 2825 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_INTEGRITY"); 2826 if ((data < PD_RS232_PARITY_NONE) || (data > PD_RS232_PARITY_SPACE)) 2827 { 2828 ret = kIOReturnBadArgument; 2829 } else { 2830 fPort.TX_Parity = data; 2831 fPort.RX_Parity = PD_RS232_PARITY_DEFAULT; 2832 2833 setLineCoding(); 2834 } 2835 break; 2836 case PD_E_DATA_RATE: 2837 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_RATE"); 2838 2839 // For API compatiblilty with Intel. 2840 2841 data >>= 1; 2842 XTRACE(this, data, 0, "executeEventGated - actual data rate"); 2843 if ((data < MIN_BAUD) || (data > kMaxBaudRate)) 2844 { 2845 ret = kIOReturnBadArgument; 2846 } else { 2847 fPort.BaudRate = data; 2848 2849 setLineCoding(); 2850 } 2851 break; 2852 case PD_E_DATA_SIZE: 2853 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_SIZE"); 2854 2855 // For API compatiblilty with Intel. 2856 2857 data >>= 1; 2858 XTRACE(this, data, 0, "executeEventGated - actual data size"); 2859 if ((data < 5) || (data > 8)) 2860 { 2861 ret = kIOReturnBadArgument; 2862 } else { 2863 fPort.CharLength = data; 2864 2865 setLineCoding(); 2866 } 2867 break; 2868 case PD_RS232_E_STOP_BITS: 2869 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_STOP_BITS"); 2870 if ((data < 0) || (data > 20)) 2871 { 2872 ret = kIOReturnBadArgument; 2873 } else { 2874 fPort.StopBits = data; 2875 2876 setLineCoding(); 2877 } 2878 break; 2879 case PD_E_RXQ_FLUSH: 2880 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_FLUSH"); 2881 break; 2882 case PD_E_RX_DATA_INTEGRITY: 2883 XTRACE(this, data, event, "executeEventGated - PD_E_RX_DATA_INTEGRITY"); 2884 if ((data != PD_RS232_PARITY_DEFAULT) && (data != PD_RS232_PARITY_ANY)) 2885 { 2886 ret = kIOReturnBadArgument; 2887 } else { 2888 fPort.RX_Parity = data; 2889 } 2890 break; 2891 case PD_E_RX_DATA_RATE: 2892 XTRACE(this, data, event, "executeEventGated - PD_E_RX_DATA_RATE"); 2893 if (data) 2894 { 2895 ret = kIOReturnBadArgument; 2896 } 2897 break; 2898 case PD_E_RX_DATA_SIZE: 2899 XTRACE(this, data, event, "executeEventGated - PD_E_RX_DATA_SIZE"); 2900 if (data) 2901 { 2902 ret = kIOReturnBadArgument; 2903 } 2904 break; 2905 case PD_RS232_E_RX_STOP_BITS: 2906 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_RX_STOP_BITS"); 2907 if (data) 2908 { 2909 ret = kIOReturnBadArgument; 2910 } 2911 break; 2912 case PD_E_TXQ_FLUSH: 2913 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_FLUSH"); 2914 break; 2915 case PD_RS232_E_LINE_BREAK: 2916 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_LINE_BREAK"); 2917 state &= ~PD_RS232_S_BRK; 2918 delta |= PD_RS232_S_BRK; 2919 setStateGated(&state, &delta); 2920 if (!fTerminate) 2921 { 2922 sendBreak((bool)data); 2923 } 2924 break; 2925 case PD_E_DELAY: 2926 XTRACE(this, data, event, "executeEventGated - PD_E_DELAY"); 2927 fPort.CharLatInterval = long2tval(data * 1000); 2928 break; 2929 case PD_E_RXQ_SIZE: 2930 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_SIZE"); 2931 break; 2932 case PD_E_TXQ_SIZE: 2933 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_SIZE"); 2934 break; 2935 case PD_E_RXQ_HIGH_WATER: 2936 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_HIGH_WATER"); 2937 break; 2938 case PD_E_RXQ_LOW_WATER: 2939 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_LOW_WATER"); 2940 break; 2941 case PD_E_TXQ_HIGH_WATER: 2942 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_HIGH_WATER"); 2943 break; 2944 case PD_E_TXQ_LOW_WATER: 2945 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_LOW_WATER"); 2946 break; 2947 default: 2948 XTRACE(this, data, event, "executeEventGated - unrecognized event"); 2949 ret = kIOReturnBadArgument; 2950 break; 2951 } 2952 2953 return ret; 2954 2955}/* end executeEventGated */ 2956 2957/****************************************************************************************************/ 2958// 2959// Method: AppleUSBCDCACMData::requestEvent 2960// 2961// Inputs: event - The event 2962// refCon - unused 2963// 2964// Outputs: Return Code - kIOReturnSuccess, kIOReturnBadArgument 2965// data - any data associated with the event 2966// 2967// Desc: requestEvent processes the specified event as an immediate request and 2968// returns the results in data. This is primarily used for getting link 2969// status information and verifying baud rate etc. 2970// For the most part this can be done immediately without being gated. 2971// 2972/****************************************************************************************************/ 2973 2974IOReturn AppleUSBCDCACMData::requestEvent(UInt32 event, UInt32 *data, void *refCon) 2975{ 2976 IOReturn returnValue = kIOReturnSuccess; 2977 2978 XTRACE(this, 0, event, "requestEvent"); 2979 2980 if (fTerminate || fStopping) 2981 { 2982 XTRACE(this, 0, kIOReturnOffline, "requestEvent - Offline"); 2983 return kIOReturnOffline; 2984 } 2985 2986 if (data == NULL) 2987 { 2988 XTRACE(this, 0, event, "requestEvent - data is null"); 2989 returnValue = kIOReturnBadArgument; 2990 } else { 2991 switch (event) 2992 { 2993 case PD_E_ACTIVE: 2994 XTRACE(this, 0, event, "requestEvent - PD_E_ACTIVE"); 2995 *data = bool(getState(&fPort) & PD_S_ACTIVE); // Just to be safe put this through the gate 2996 break; 2997 case PD_E_FLOW_CONTROL: 2998 XTRACE(this, fPort.FlowControl, event, "requestEvent - PD_E_FLOW_CONTROL"); 2999 *data = fPort.FlowControl; 3000 break; 3001 case PD_E_DELAY: 3002 XTRACE(this, 0, event, "requestEvent - PD_E_DELAY"); 3003 *data = tval2long(fPort.CharLatInterval)/ 1000; 3004 break; 3005 case PD_E_DATA_LATENCY: 3006 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_LATENCY"); 3007 *data = tval2long(fPort.DataLatInterval)/ 1000; 3008 break; 3009 case PD_E_TXQ_SIZE: 3010 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_SIZE"); 3011 *data = GetQueueSize(&fPort.TX); 3012 break; 3013 case PD_E_RXQ_SIZE: 3014 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_SIZE"); 3015 *data = GetQueueSize(&fPort.RX); 3016 break; 3017 case PD_E_TXQ_LOW_WATER: 3018 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_LOW_WATER"); 3019 *data = 0; 3020 returnValue = kIOReturnBadArgument; 3021 break; 3022 case PD_E_RXQ_LOW_WATER: 3023 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_LOW_WATER"); 3024 *data = 0; 3025 returnValue = kIOReturnBadArgument; 3026 break; 3027 case PD_E_TXQ_HIGH_WATER: 3028 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_HIGH_WATER"); 3029 *data = 0; 3030 returnValue = kIOReturnBadArgument; 3031 break; 3032 case PD_E_RXQ_HIGH_WATER: 3033 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_HIGH_WATER"); 3034 *data = 0; 3035 returnValue = kIOReturnBadArgument; 3036 break; 3037 case PD_E_TXQ_AVAILABLE: 3038 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_AVAILABLE"); 3039 *data = FreeSpaceinQueue(&fPort.TX); 3040 break; 3041 case PD_E_RXQ_AVAILABLE: 3042 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_AVAILABLE"); 3043 *data = UsedSpaceinQueue(&fPort.RX); 3044 break; 3045 case PD_E_DATA_RATE: 3046 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_RATE"); 3047 *data = fPort.BaudRate << 1; 3048 break; 3049 case PD_E_RX_DATA_RATE: 3050 XTRACE(this, 0, event, "requestEvent - PD_E_RX_DATA_RATE"); 3051 *data = 0x00; 3052 break; 3053 case PD_E_DATA_SIZE: 3054 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_SIZE"); 3055 *data = fPort.CharLength << 1; 3056 break; 3057 case PD_E_RX_DATA_SIZE: 3058 XTRACE(this, 0, event, "requestEvent - PD_E_RX_DATA_SIZE"); 3059 *data = 0x00; 3060 break; 3061 case PD_E_DATA_INTEGRITY: 3062 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_INTEGRITY"); 3063 *data = fPort.TX_Parity; 3064 break; 3065 case PD_E_RX_DATA_INTEGRITY: 3066 XTRACE(this, 0, event, "requestEvent - PD_E_RX_DATA_INTEGRITY"); 3067 *data = fPort.RX_Parity; 3068 break; 3069 case PD_RS232_E_STOP_BITS: 3070 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_STOP_BITS"); 3071 *data = fPort.StopBits << 1; 3072 break; 3073 case PD_RS232_E_RX_STOP_BITS: 3074 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_RX_STOP_BITS"); 3075 *data = 0x00; 3076 break; 3077 case PD_RS232_E_XON_BYTE: 3078 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_XON_BYTE"); 3079 *data = fPort.XONchar; 3080 break; 3081 case PD_RS232_E_XOFF_BYTE: 3082 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_XOFF_BYTE"); 3083 *data = fPort.XOFFchar; 3084 break; 3085 case PD_RS232_E_LINE_BREAK: 3086 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_LINE_BREAK"); 3087 *data = bool(getState(&fPort) & PD_RS232_S_BRK); // This should be gated too 3088 break; 3089 case PD_RS232_E_MIN_LATENCY: 3090 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_MIN_LATENCY"); 3091 *data = bool(fPort.MinLatency); 3092 break; 3093 default: 3094 XTRACE(this, 0, event, "requestEvent - unrecognized event"); 3095 returnValue = kIOReturnBadArgument; 3096 break; 3097 } 3098 } 3099 3100 return kIOReturnSuccess; 3101 3102}/* end requestEvent */ 3103 3104/****************************************************************************************************/ 3105// 3106// Method: AppleUSBCDCACMData::enqueueEvent 3107// 3108// Inputs: event - The event 3109// data - any data associated with the event, 3110// sleep - true (wait for it), false (don't) 3111// refCon - unused 3112// 3113// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 3114// 3115// Desc: Not used by this driver. 3116// Events are passed on to executeEvent for immediate action. 3117// 3118/****************************************************************************************************/ 3119 3120IOReturn AppleUSBCDCACMData::enqueueEvent(UInt32 event, UInt32 data, bool sleep, void *refCon) 3121{ 3122 IOReturn ret; 3123 3124 XTRACE(this, data, event, "enqueueEvent"); 3125 3126 if (fTerminate || fStopping) 3127 { 3128 XTRACE(this, 0, kIOReturnOffline, "enqueueEvent - Offline"); 3129 return kIOReturnOffline; 3130 } 3131 3132 retain(); 3133 ret = fCommandGate->runAction(executeEventAction, (void *)&event, (void *)&data); 3134 release(); 3135 3136 return ret; 3137 3138}/* end enqueueEvent */ 3139 3140/****************************************************************************************************/ 3141// 3142// Method: AppleUSBCDCACMData::dequeueEvent 3143// 3144// Inputs: sleep - true (wait for it), false (don't) 3145// refCon - unused 3146// 3147// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen 3148// 3149// Desc: Not used by this driver. 3150// 3151/****************************************************************************************************/ 3152 3153IOReturn AppleUSBCDCACMData::dequeueEvent(UInt32 *event, UInt32 *data, bool sleep, void *refCon) 3154{ 3155 3156 XTRACE(this, 0, 0, "dequeueEvent"); 3157 3158 if (fTerminate || fStopping) 3159 { 3160 XTRACE(this, 0, kIOReturnOffline, "dequeueEvent - Offline"); 3161 return kIOReturnOffline; 3162 } 3163 3164 if ((event == NULL) || (data == NULL)) 3165 return kIOReturnBadArgument; 3166 3167 if (getState(&fPort) & PD_S_ACTIVE) 3168 { 3169 return kIOReturnSuccess; 3170 } 3171 3172 return kIOReturnNotOpen; 3173 3174}/* end dequeueEvent */ 3175 3176/****************************************************************************************************/ 3177// 3178// Method: AppleUSBCDCACMData::enqueueData 3179// 3180// Inputs: buffer - the data 3181// size - number of bytes 3182// sleep - true (wait for it), false (don't) 3183// refCon - unused 3184// 3185// Outputs: Return Code - kIOReturnSuccess, kIOReturnBadArgument or value returned from watchState 3186// count - bytes transferred 3187// 3188// Desc: set up for enqueueDataGated call. 3189// 3190/****************************************************************************************************/ 3191 3192IOReturn AppleUSBCDCACMData::enqueueData(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep, void *refCon) 3193{ 3194 IOReturn ret; 3195 3196 XTRACE(this, size, sleep, "enqueueData"); 3197 3198 if (fTerminate || fStopping) 3199 { 3200 XTRACE(this, 0, kIOReturnOffline, "enqueueData - Offline"); 3201 return kIOReturnOffline; 3202 } 3203 3204 if (count == NULL || buffer == NULL) 3205 return kIOReturnBadArgument; 3206 3207 retain(); 3208 ret = fCommandGate->runAction(enqueueDataAction, (void *)buffer, (void *)&size, (void *)count, (void *)&sleep); 3209 release(); 3210 3211 return ret; 3212 3213}/* end enqueueData */ 3214 3215/****************************************************************************************************/ 3216// 3217// Method: AppleUSBCDCACMData::enqueueDatatAction 3218// 3219// Desc: Dummy pass through for enqueueDataGated. 3220// 3221/****************************************************************************************************/ 3222 3223IOReturn AppleUSBCDCACMData::enqueueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3) 3224{ 3225 3226 return ((AppleUSBCDCACMData *)owner)->enqueueDataGated((UInt8 *)arg0, (UInt32 *)arg1, (UInt32 *)arg2, (bool *)arg3); 3227 3228}/* end enqueueDataAction */ 3229 3230/****************************************************************************************************/ 3231// 3232// Method: AppleUSBCDCACMData::enqueueDataGated 3233// 3234// Inputs: buffer - the data 3235// size - number of bytes 3236// sleep - true (wait for it), false (don't) 3237// 3238// Outputs: Return Code - kIOReturnSuccess or value returned from watchState 3239// count - bytes transferred, 3240// 3241// Desc: enqueueData will attempt to copy data from the specified buffer to 3242// the TX queue as a sequence of VALID_DATA events. The argument 3243// bufferSize specifies the number of bytes to be sent. The actual 3244// number of bytes transferred is returned in count. 3245// If sleep is true, then this method will sleep until all bytes can be 3246// transferred. If sleep is false, then as many bytes as possible 3247// will be copied to the TX queue. 3248// Note that the caller should ALWAYS check the transferCount unless 3249// the return value was kIOReturnBadArgument, indicating one or more 3250// arguments were not valid. Other possible return values are 3251// kIOReturnSuccess if all requirements were met or kIOReturnOffline 3252// if the device was unplugged. 3253// 3254/****************************************************************************************************/ 3255 3256IOReturn AppleUSBCDCACMData::enqueueDataGated(UInt8 *buffer, UInt32 *pSize, UInt32 *count, bool *pSleep) 3257{ 3258 UInt32 size = *pSize; 3259 bool sleep = *pSleep; 3260 UInt32 state = PD_S_TXQ_LOW_WATER; 3261 UInt32 mask; 3262 IOReturn rtn = kIOReturnSuccess; 3263 3264 XTRACE(this, size, sleep, "enqueueDataGated"); 3265 3266 if (fTerminate || fStopping) 3267 return kIOReturnOffline; 3268 3269 *count = 0; 3270 3271 if (!(fPort.State & PD_S_ACTIVE)) 3272 return kIOReturnNotOpen; 3273 3274 XTRACE(this, fPort.State, size, "enqueueDataGated - current State"); 3275// LogData(kDataOther, size, buffer); 3276 3277 // Go ahead and try to add something to the buffer 3278 3279 *count = AddtoQueue(&fPort.TX, buffer, size); 3280 CheckQueues(); 3281 3282 // Let the tranmitter know that we have something ready to go 3283 3284 setUpTransmit(); 3285 3286 // If we could not queue up all of the data on the first pass and 3287 // the user wants us to sleep until it's all out then sleep 3288 3289 while ((*count < size) && sleep) 3290 { 3291 state = PD_S_TXQ_LOW_WATER; 3292 mask = PD_S_TXQ_LOW_WATER; 3293 rtn = watchStateGated(&state, &mask); 3294 if (rtn != kIOReturnSuccess) 3295 { 3296 XTRACE(this, 0, rtn, "enqueueDataGated - interrupted"); 3297 return rtn; 3298 } 3299 3300 *count += AddtoQueue(&fPort.TX, buffer + *count, size - *count); 3301 CheckQueues(); 3302 3303 // Let the tranmitter know that we have something ready to go. 3304 3305 setUpTransmit(); 3306 } 3307 3308 XTRACE(this, *count, size, "enqueueDataGated - Exit"); 3309 3310 return kIOReturnSuccess; 3311 3312}/* end enqueueDataGated */ 3313 3314/****************************************************************************************************/ 3315// 3316// Method: AppleUSBCDCACMData::dequeueData 3317// 3318// Inputs: size - buffer size 3319// min - minimum bytes required 3320// refCon - the Port 3321// 3322// Outputs: buffer - data returned 3323// min - number of bytes 3324// Return Code - kIOReturnSuccess, kIOReturnBadArgument, kIOReturnNotOpen, or value returned from watchState 3325// 3326// Desc: set up for dequeueDataGated call. 3327// 3328/****************************************************************************************************/ 3329 3330IOReturn AppleUSBCDCACMData::dequeueData(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, void *refCon) 3331{ 3332 IOReturn ret; 3333 3334 XTRACE(this, size, min, "dequeueData"); 3335 3336 if (fTerminate || fStopping) 3337 { 3338 XTRACE(this, 0, kIOReturnOffline, "dequeueData - Offline"); 3339 return kIOReturnOffline; 3340 } 3341 3342 if ((count == NULL) || (buffer == NULL) || (min > size)) 3343 return kIOReturnBadArgument; 3344 3345 retain(); 3346 ret = fCommandGate->runAction(dequeueDataAction, (void *)buffer, (void *)&size, (void *)count, (void *)&min); 3347 release(); 3348 3349 return ret; 3350 3351}/* end dequeueData */ 3352 3353/****************************************************************************************************/ 3354// 3355// Method: AppleUSBCDCACMData::dequeueDatatAction 3356// 3357// Desc: Dummy pass through for dequeueDataGated. 3358// 3359/****************************************************************************************************/ 3360 3361IOReturn AppleUSBCDCACMData::dequeueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3) 3362{ 3363 3364 return ((AppleUSBCDCACMData *)owner)->dequeueDataGated((UInt8 *)arg0, (UInt32 *)arg1, (UInt32 *)arg2, (UInt32 *)arg3); 3365 3366}/* end dequeueDataAction */ 3367 3368/****************************************************************************************************/ 3369// 3370// Method: AppleUSBCDCACMData::dequeueDataGated 3371// 3372// Inputs: size - buffer size 3373// min - minimum bytes required 3374// 3375// Outputs: buffer - data returned 3376// min - number of bytes 3377// Return Code - kIOReturnSuccess, kIOReturnBadArgument, kIOReturnNotOpen, or value returned from watchState 3378// 3379// Desc: dequeueData will attempt to copy data from the RX queue to the 3380// specified buffer. No more than bufferSize VALID_DATA events 3381// will be transferred. In other words, copying will continue until 3382// either a non-data event is encountered or the transfer buffer 3383// is full. The actual number of bytes transferred is returned 3384// in count. 3385// The sleep semantics of this method are slightly more complicated 3386// than other methods in this API. Basically, this method will 3387// continue to sleep until either min characters have been 3388// received or a non data event is next in the RX queue. If 3389// min is zero, then this method never sleeps and will return 3390// immediately if the queue is empty. 3391// Note that the caller should ALWAYS check the transferCount 3392// unless the return value was kIOReturnBadArgument, indicating one or 3393// more arguments were not valid. 3394// 3395/****************************************************************************************************/ 3396 3397IOReturn AppleUSBCDCACMData::dequeueDataGated(UInt8 *buffer, UInt32 *pSize, UInt32 *count, UInt32 *pMin) 3398{ 3399 UInt32 size = *pSize; 3400 UInt32 min = *pMin; 3401 IOReturn rtn = kIOReturnSuccess; 3402 UInt32 state = 0; 3403 UInt32 mask; 3404 bool goXOIdle; 3405 UInt32 savCount; 3406 uintptr_t addr; 3407 3408 XTRACE(this, size, min, "dequeueDataGated"); 3409 3410 if (fTerminate || fStopping) 3411 return kIOReturnOffline; 3412 3413 // If the port is not active then there should not be any chars. 3414 3415 *count = 0; 3416 if (!(fPort.State & PD_S_ACTIVE)) 3417 return kIOReturnNotOpen; 3418 3419 // Get any data living in the queue. 3420 3421 *count = RemovefromQueue(&fPort.RX, buffer, size); 3422 if (*count > 0) 3423 { 3424 addr = (uintptr_t)buffer; 3425 XTRACE(this, size, addr, "dequeueDataGated - Removed from Queue (first)"); 3426 LogData(kDataOther, *count, buffer); 3427 CheckHold(); 3428 } 3429 CheckQueues(); 3430 3431 while ((min > 0) && (*count < min)) 3432 { 3433 // Figure out how many bytes we have left to queue up 3434 3435 state = 0; 3436 mask = PD_S_RXQ_EMPTY; 3437 rtn = watchStateGated(&state, &mask); 3438 3439 if (rtn != kIOReturnSuccess) 3440 { 3441 XTRACE(this, 0, rtn, "dequeueDataGated - Interrupted!"); 3442 return rtn; 3443 } 3444 3445 // Try and get more data starting from where we left off 3446 3447// *count += RemovefromQueue(&fPort.RX, buffer + *count, (size - *count)); 3448 3449 savCount = *count; 3450 *count += RemovefromQueue(&fPort.RX, &buffer[*count], (size - *count)); 3451 addr = (uintptr_t)buffer; 3452 XTRACE(this, *count, addr, "dequeueDataGated - Removed from Queue (next)"); 3453 LogData(kDataOther, *count, &buffer[savCount]); 3454 if (*count > 0) 3455 { 3456 CheckHold(); 3457 } 3458 CheckQueues(); 3459 } 3460 3461 // Now let's check our receive buffer to see if we need to stop 3462 3463 goXOIdle = (UsedSpaceinQueue(&fPort.RX) < fPort.RXStats.LowWater) && (fPort.RXOstate == SENT_XOFF); 3464 3465 if (goXOIdle) 3466 { 3467 fPort.RXOstate = IDLE_XO; 3468 AddBytetoQueue(&fPort.TX, fPort.XOFFchar); 3469 setUpTransmit(); 3470 } 3471 3472 XTRACE(this, *count, size, "dequeueData - Exit"); 3473 3474 return rtn; 3475 3476}/* end dequeueDataGated */ 3477 3478/****************************************************************************************************/ 3479// 3480// Method: AppleUSBCDCACMData::setUpTransmit 3481// 3482// Inputs: 3483// 3484// Outputs: return code - true (transmit started), false (transmission already in progress) 3485// 3486// Desc: Setup and then start transmisson 3487// 3488/****************************************************************************************************/ 3489 3490bool AppleUSBCDCACMData::setUpTransmit() 3491{ 3492 3493 XTRACE(this, 0, 0, "setUpTransmit"); 3494 3495 // As a precaution just check we've not been terminated (maybe a woken thread) 3496 3497 if (fTerminate || fStopping) 3498 { 3499 XTRACE(this, 0, 0, "setUpTransmit - terminated"); 3500 return false; 3501 } 3502 3503 if (UsedSpaceinQueue(&fPort.TX) > 0) 3504 { 3505 startTransmission(); 3506 } 3507 3508 return TRUE; 3509 3510}/* end setUpTransmit */ 3511 3512/****************************************************************************************************/ 3513// 3514// Method: AppleUSBCDCACMData::startTransmission 3515// 3516// Inputs: 3517// 3518// Outputs: 3519// 3520// Desc: Start the transmisson 3521// Must be called from a gated method 3522// 3523/****************************************************************************************************/ 3524 3525void AppleUSBCDCACMData::startTransmission() 3526{ 3527 size_t count; 3528 IOReturn ior; 3529 UInt16 indx; 3530 bool gotBuffer = false; 3531 UInt32 state; 3532 UInt32 mask; 3533 3534 XTRACE(this, 0, 0, "startTransmission"); 3535 3536 // Get an output buffer 3537 3538 indx = fPort.outPoolIndex; 3539 if (!fPort.outPool[indx].avail) 3540 { 3541 for (indx=0; indx<fPort.outPoolIndex; indx++) 3542 { 3543 if (fPort.outPool[indx].avail) 3544 { 3545 fPort.outPoolIndex = indx; 3546 gotBuffer = true; 3547 break; 3548 } 3549 } 3550 } else { 3551 gotBuffer = true; 3552 } 3553 if (gotBuffer) 3554 { 3555 fPort.outPool[indx].avail = false; 3556 fPort.outPoolIndex++; 3557 if (fPort.outPoolIndex >= fOutBufPool) 3558 { 3559 fPort.outPoolIndex = 0; 3560 } 3561 } else { 3562 XTRACE(this, fOutBufPool, indx, "startTransmission - Output buffer unavailable"); 3563 return; 3564 } 3565 3566 // Fill up the buffer with characters from the queue 3567 3568 count = RemovefromQueue(&fPort.TX, fPort.outPool[indx].pipeBuffer, MAX_BLOCK_SIZE); 3569 3570 // If there are no bytes to send just exit: 3571 3572 if (count <= 0) 3573 { 3574 // Updates all the status flags: 3575 3576 CheckQueues(); 3577 fPort.outPool[indx].avail = true; 3578 return; 3579 } 3580 3581 state = PD_S_TX_BUSY; 3582 mask = PD_S_TX_BUSY; 3583 setStateGated(&state, &mask); 3584 3585 XTRACE(this, fPort.State, count, "startTransmission - Bytes to write"); 3586 LogData(kDataOut, count, fPort.outPool[indx].pipeBuffer); 3587 3588 fPort.outPool[indx].count = count; 3589 fPort.outPool[indx].completionInfo.parameter = (void *)&fPort.outPool[indx]; 3590 fPort.outPool[indx].pipeMDP->setLength(count); 3591 3592 ior = fPort.OutPipe->Write(fPort.outPool[indx].pipeMDP, &fPort.outPool[indx].completionInfo); 3593 if (ior != kIOReturnSuccess) 3594 { 3595 XTRACE(this, 0, ior, "startTransmission - Write failed"); 3596 } 3597 3598 // We just removed a bunch of stuff from the 3599 // queue, so see if we can free some thread(s) 3600 // to enqueue more stuff. 3601 3602 CheckQueues(); 3603 3604}/* end startTransmission */ 3605 3606/****************************************************************************************************/ 3607// 3608// Method: AppleUSBCDCACMData::setLineCoding 3609// 3610// Inputs: 3611// 3612// Outputs: 3613// 3614// Desc: Set up and send SetLineCoding Management Element Request(MER) for all settings. 3615// 3616/****************************************************************************************************/ 3617 3618void AppleUSBCDCACMData::setLineCoding() 3619{ 3620 3621 XTRACE(this, 0, 0, "setLineCoding"); 3622 3623 // Check for changes and only do it if something's changed 3624 3625 if ((fPort.BaudRate == fPort.LastBaudRate) && (fPort.StopBits == fPort.LastStopBits) && 3626 (fPort.TX_Parity == fPort.LastTX_Parity) && (fPort.CharLength == fPort.LastCharLength)) 3627 { 3628 return; 3629 } 3630 3631 // Now send it to the control driver 3632 3633 if (fControlDriver) 3634 { 3635 fControlDriver->USBSendSetLineCoding(fPort.BaudRate, fPort.StopBits, fPort.TX_Parity, fPort.CharLength); 3636 } 3637 3638 fPort.LastBaudRate = fPort.BaudRate; 3639 fPort.LastStopBits = fPort.StopBits; 3640 fPort.LastTX_Parity = fPort.TX_Parity; 3641 fPort.LastCharLength = fPort.CharLength; 3642 3643}/* end setLineCoding */ 3644 3645/****************************************************************************************************/ 3646// 3647// Method: AppleUSBCDCACMData::setControlLineState 3648// 3649// Inputs: RTS - true(set RTS), false(clear RTS) 3650// DTR - true(set DTR), false(clear DTR) 3651// 3652// Outputs: 3653// 3654// Desc: Set up and send SetControlLineState Management Element Request(MER). 3655// 3656/****************************************************************************************************/ 3657 3658void AppleUSBCDCACMData::setControlLineState(bool RTS, bool DTR) 3659{ 3660 3661 XTRACE(this, 0, 0, "setControlLineState"); 3662 3663 if (fControlDriver) 3664 { 3665 fControlDriver->USBSendSetControlLineState(RTS, DTR); 3666 } 3667 3668}/* end setControlLineState */ 3669 3670/****************************************************************************************************/ 3671// 3672// Method: AppleUSBCDCACMData::sendBreak 3673// 3674// Inputs: sBreak - true(set Break), false(clear Break) 3675// 3676// Outputs: 3677// 3678// Desc: Set up and send SendBreak Management Element Request(MER). 3679// 3680/****************************************************************************************************/ 3681 3682void AppleUSBCDCACMData::sendBreak(bool sBreak) 3683{ 3684 3685 XTRACE(this, 0, 0, "sendBreak"); 3686 3687 if (fControlDriver) 3688 { 3689 fControlDriver->USBSendBreak(sBreak); 3690 } 3691 3692}/* end sendBreak */ 3693 3694/****************************************************************************************************/ 3695// 3696// Method: AppleUSBCDCACMData::checkPipe 3697// 3698// Inputs: thePipe - the pipe 3699// devReq - true(send CLEAR_FEATURE), false(only if status returns stalled) 3700// 3701// Outputs: 3702// 3703// Desc: Clear a stall on the specified pipe. If ClearPipeStall is issued 3704// all outstanding I/O is returned with kIOUSBTransactionReturned and 3705// a CLEAR_FEATURE Endpoint stall is sent. 3706// 3707/****************************************************************************************************/ 3708 3709IOReturn AppleUSBCDCACMData::checkPipe(IOUSBPipe *thePipe, bool devReq) 3710{ 3711 IOReturn rtn = kIOReturnSuccess; 3712 3713 XTRACEP(this, 0, thePipe, "checkPipe"); 3714 3715 if (!devReq) 3716 { 3717 rtn = thePipe->GetPipeStatus(); 3718 if (rtn != kIOUSBPipeStalled) 3719 { 3720 XTRACE(this, 0, rtn, "checkPipe - Pipe not stalled"); 3721 return rtn; 3722 } 3723 } 3724 3725 rtn = thePipe->ClearPipeStall(true); 3726 if (rtn == kIOReturnSuccess) 3727 { 3728 XTRACE(this, 0, 0, "checkPipe - ClearPipeStall Successful"); 3729 } else { 3730 XTRACE(this, 0, rtn, "checkPipe - ClearPipeStall Failed"); 3731 } 3732 3733 return rtn; 3734 3735}/* end checkPipe */ 3736 3737/****************************************************************************************************/ 3738// 3739// Method: AppleUSBCDCACMData::initStructure 3740// 3741// Inputs: 3742// 3743// Outputs: 3744// 3745// Desc: Initialize the port structure 3746// 3747/****************************************************************************************************/ 3748 3749void AppleUSBCDCACMData::initStructure() 3750{ 3751 UInt16 i; 3752 3753 XTRACE(this, 0, 0, "initStructure"); 3754 3755 // These are set up at start and should not be reset during execution. 3756 3757 fPort.FCRimage = 0x00; 3758 fPort.IERmask = 0x00; 3759 3760 fPort.State = (PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER); 3761 fPort.WatchStateMask = 0x00000000; 3762 fPort.InPipe = NULL; 3763 fPort.OutPipe = NULL; 3764 for (i=0; i<kMaxInBufPool; i++) 3765 { 3766 fPort.inPool[i].pipeMDP = NULL; 3767 fPort.inPool[i].pipeBuffer = NULL; 3768 fPort.inPool[i].dead = false; 3769 fPort.inPool[i].count = -1; 3770 fPort.inPool[i].held = false; 3771 3772 fPort.holdQueue[i] = 0; 3773 } 3774 fPort.holdQueueIndxIn = 0; 3775 fPort.holdQueueIndxOut = 0; 3776 3777 for (i=0; i<kMaxOutBufPool; i++) 3778 { 3779 fPort.outPool[i].pipeMDP = NULL; 3780 fPort.outPool[i].pipeBuffer = NULL; 3781 fPort.outPool[i].count = -1; 3782 fPort.outPool[i].avail = false; 3783 } 3784 fPort.outPoolIndex = 0; 3785 3786}/* end initStructure */ 3787 3788/****************************************************************************************************/ 3789// 3790// Method: AppleUSBCDCACMData::setStructureDefaults 3791// 3792// Inputs: 3793// 3794// Outputs: 3795// 3796// Desc: Sets the defaults for the specified port structure 3797// 3798/****************************************************************************************************/ 3799 3800void AppleUSBCDCACMData::setStructureDefaults() 3801{ 3802 UInt32 tmp; 3803 3804 XTRACE(this, 0, 0, "setStructureDefaults"); 3805 3806 fPort.BaudRate = kDefaultBaudRate; // 9600 bps 3807 fPort.LastBaudRate = 0; 3808 fPort.CharLength = 8; // 8 Data bits 3809 fPort.LastCharLength = 0; 3810 fPort.StopBits = 2; // 1 Stop bit 3811 fPort.LastStopBits = 0; 3812 fPort.TX_Parity = 1; // No Parity 3813 fPort.LastTX_Parity = 0; 3814 fPort.RX_Parity = 1; // --ditto-- 3815 fPort.MinLatency = false; 3816 fPort.XONchar = '\x11'; 3817 fPort.XOFFchar = '\x13'; 3818 fPort.FlowControl = 0x00000000; 3819 fPort.RXOstate = IDLE_XO; 3820 fPort.TXOstate = IDLE_XO; 3821 fPort.FrameTOEntry = NULL; 3822 3823 fPort.RXStats.BufferSize = kMaxCirBufferSize; 3824 fPort.RXStats.HighWater = (fPort.RXStats.BufferSize << 1) / 3; 3825 fPort.RXStats.LowWater = fPort.RXStats.HighWater >> 1; 3826 fPort.TXStats.BufferSize = kMaxCirBufferSize; 3827 fPort.TXStats.HighWater = (fPort.RXStats.BufferSize << 1) / 3; 3828 fPort.TXStats.LowWater = fPort.RXStats.HighWater >> 1; 3829 3830 fPort.FlowControl = (DEFAULT_AUTO | DEFAULT_NOTIFY); 3831 3832 for (tmp=0; tmp < (256 >> SPECIAL_SHIFT); tmp++) 3833 fPort.SWspecial[ tmp ] = 0; 3834 3835}/* end setStructureDefaults */ 3836 3837/****************************************************************************************************/ 3838// 3839// Method: AppleUSBCDCACMData::allocateResources 3840// 3841// Inputs: 3842// 3843// Outputs: return code - true (allocate was successful), false (it failed) 3844// 3845// Desc: Finishes up the rest of the configuration and gets all the endpoints open etc. 3846// 3847/****************************************************************************************************/ 3848 3849bool AppleUSBCDCACMData::allocateResources() 3850{ 3851 IOUSBFindEndpointRequest epReq; 3852 UInt16 i; 3853 3854 XTRACE(this, 0, 0, "allocateResources."); 3855 3856 // Open all the end points and get the buffers 3857 3858 if (!fDataInterface->open(this)) 3859 { 3860 XTRACE(this, 0, 0, "allocateResources - open data interface failed."); 3861 return false; 3862 } 3863 3864 // Bulk In pipe 3865 3866 epReq.type = kUSBBulk; 3867 epReq.direction = kUSBIn; 3868 epReq.maxPacketSize = 0; 3869 epReq.interval = 0; 3870 fPort.InPipe = fDataInterface->FindNextPipe(0, &epReq); 3871 if (!fPort.InPipe) 3872 { 3873 XTRACE(this, 0, 0, "allocateResources - no bulk input pipe."); 3874 return false; 3875 } 3876 fPort.InPacketSize = epReq.maxPacketSize; 3877 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk input pipe."); 3878 3879 // Allocate Memory Descriptor Pointer with memory for the bulk in pipe 3880 3881 for (i=0; i<fInBufPool; i++) 3882 { 3883// fPort.inPool[i].pipeMDP = IOBufferMemoryDescriptor::withCapacity(DATA_BUFF_SIZE, kIODirectionIn); 3884 fPort.inPool[i].pipeMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionIn | kIOMemoryPhysicallyContiguous, DATA_BUFF_SIZE, PAGE_SIZE); 3885 if (!fPort.inPool[i].pipeMDP) 3886 { 3887 XTRACE(this, 0, i, "allocateResources - Allocate input MDP failed"); 3888 return false; 3889 } 3890 fPort.inPool[i].pipeBuffer = (UInt8*)fPort.inPool[i].pipeMDP->getBytesNoCopy(); 3891 XTRACEP(this, fPort.inPool[i].pipeMDP, fPort.inPool[i].pipeBuffer, "allocateResources - input buffer"); 3892 fPort.inPool[i].dead = false; 3893 } 3894 3895 // Bulk Out pipe 3896 3897 epReq.direction = kUSBOut; 3898 fPort.OutPipe = fDataInterface->FindNextPipe(0, &epReq); 3899 if (!fPort.OutPipe) 3900 { 3901 XTRACE(this, 0, 0, "allocateResources - no bulk output pipe."); 3902 return false; 3903 } 3904 fPort.OutPacketSize = epReq.maxPacketSize; 3905 XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk output pipe."); 3906 3907 // Allocate Memory Descriptor Pointer with memory for the bulk out pipe 3908 3909 for (i=0; i<fOutBufPool; i++) 3910 { 3911// fPort.outPool[i].pipeMDP = IOBufferMemoryDescriptor::withCapacity(MAX_BLOCK_SIZE, kIODirectionOut); 3912 fPort.outPool[i].pipeMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionOut | kIOMemoryPhysicallyContiguous, MAX_BLOCK_SIZE, PAGE_SIZE); 3913 if (!fPort.outPool[i].pipeMDP) 3914 { 3915 XTRACE(this, 0, i, "allocateResources - Allocate output MDP failed"); 3916 return false; 3917 } 3918 fPort.outPool[i].pipeBuffer = (UInt8*)fPort.outPool[i].pipeMDP->getBytesNoCopy(); 3919 XTRACEP(this, fPort.outPool[i].pipeMDP, fPort.outPool[i].pipeBuffer, "allocateResources - output buffer"); 3920 fPort.outPool[i].avail = true; 3921 } 3922 3923 XTRACEP(this, 0, fPort.RX.Start, "allocateResources - RX ring buffer"); 3924 3925 return true; 3926 3927}/* end allocateResources */ 3928 3929/****************************************************************************************************/ 3930// 3931// Method: AppleUSBCDCACMData::releaseResources 3932// 3933// Inputs: 3934// 3935// Outputs: 3936// 3937// Desc: Frees up the resources allocated in allocateResources 3938// 3939/****************************************************************************************************/ 3940 3941void AppleUSBCDCACMData::releaseResources() 3942{ 3943 UInt16 i; 3944 3945 XTRACE(this, 0, 0, "releaseResources"); 3946 3947 if (fDataInterface) 3948 { 3949 fDataInterface->close(this); 3950 fDataInterface->release(); 3951 fDataInterface = NULL; 3952 } 3953 3954 for (i=0; i<fInBufPool; i++) 3955 { 3956 if (fPort.inPool[i].pipeMDP) 3957 { 3958 fPort.inPool[i].pipeMDP->release(); 3959 fPort.inPool[i].pipeMDP = NULL; 3960 fPort.inPool[i].dead = false; 3961 } 3962 } 3963 3964 for (i=0; i<fOutBufPool; i++) 3965 { 3966 if (fPort.outPool[i].pipeMDP) 3967 { 3968 fPort.outPool[i].pipeMDP->release(); 3969 fPort.outPool[i].pipeMDP = NULL; 3970 fPort.outPool[i].count = -1; 3971 fPort.outPool[i].avail = false; 3972 } 3973 } 3974 fPort.outPoolIndex = 0; 3975 3976 if (fWorkLoop) 3977 { 3978 fWorkLoop->release(); 3979 fWorkLoop = NULL; 3980 } 3981 3982 freeRingBuffer(&fPort.TX); 3983 freeRingBuffer(&fPort.RX); 3984 3985}/* end releaseResources */ 3986 3987/****************************************************************************************************/ 3988// 3989// Method: AppleUSBCDCACMData::freeRingBuffer 3990// 3991// Inputs: Queue - the specified queue to free 3992// 3993// Outputs: 3994// 3995// Desc: Frees all resources assocated with the queue, then sets all queue parameters 3996// to safe values. 3997// 3998/****************************************************************************************************/ 3999 4000void AppleUSBCDCACMData::freeRingBuffer(CirQueue *Queue) 4001{ 4002 XTRACEP(this, 0, Queue, "freeRingBuffer"); 4003 4004 if (Queue) 4005 { 4006 if (Queue->Start) 4007 { 4008 IOFree(Queue->Start, Queue->Size); 4009 } 4010 CloseQueue(Queue); 4011 } 4012 4013}/* end freeRingBuffer */ 4014 4015 4016/****************************************************************************************************/ 4017// 4018// Method: AppleUSBCDCACMData::createSerialRingBuffers 4019// 4020// Inputs: Queue - the specified queue to allocate 4021// BufferSize - size to allocate 4022// 4023// Outputs: return Code - true (ring buffers allocated), false (it failed) 4024// 4025// Desc: Allocates serialRingBuffers . Moved this so this can be called at AquirePort time. 4026// 4027/****************************************************************************************************/ 4028 4029bool AppleUSBCDCACMData::createSerialRingBuffers() 4030{ 4031 4032 if (fPort.ringsAllocated == true) 4033 { 4034 XTRACE(this, 0, 0, "createSerialRingBuffers - rings already allocated"); 4035 return true; 4036 } 4037 4038 // Now the ring buffers 4039 if (!allocateRingBuffer(&fPort.TX, fPort.TXStats.BufferSize)) 4040 { 4041 XTRACE(this, 0, 0, "createSerialRingBuffers - Couldn't allocate TX ring buffer"); 4042 return false; 4043 } 4044 4045 XTRACEP(this, 0, fPort.TX.Start, "createSerialRingBuffers - TX ring buffer"); 4046 4047 if (!allocateRingBuffer(&fPort.RX, fPort.RXStats.BufferSize)) 4048 { 4049 XTRACE(this, 0, 0, "createSerialRingBuffers - Couldn't allocate RX ring buffer"); 4050 return false; 4051 } 4052 4053 fPort.ringsAllocated = true; 4054 4055 return true; 4056} 4057 4058 4059/****************************************************************************************************/ 4060// 4061// Method: AppleUSBCDCACMData::allocateRingBuffer 4062// 4063// Inputs: Queue - the specified queue to allocate 4064// BufferSize - size to allocate 4065// 4066// Outputs: return Code - true (buffer allocated), false (it failed) 4067// 4068// Desc: Allocates resources needed by the queue, then sets up all queue parameters. 4069// 4070/****************************************************************************************************/ 4071 4072bool AppleUSBCDCACMData::allocateRingBuffer(CirQueue *Queue, size_t BufferSize) 4073{ 4074 UInt8 *Buffer; 4075 4076 // Size is ignored and kMaxCirBufferSize, which is 4096, is used. 4077 4078 XTRACE(this, 0, BufferSize, "allocateRingBuffer"); 4079 Buffer = (UInt8*)IOMalloc(kMaxCirBufferSize); 4080 4081 InitQueue(Queue, Buffer, kMaxCirBufferSize); 4082 4083 if (Buffer) 4084 return true; 4085 4086 XTRACE(this, BufferSize, kMaxCirBufferSize, "allocateRingBuffer <<<"); 4087 return false; 4088 4089}/* end allocateRingBuffer */ 4090 4091/****************************************************************************************************/ 4092// 4093// Function: AppleUSBCDCACMData::handleSettingCallback 4094// 4095// Inputs: 4096// 4097// Outputs: none 4098// 4099// Desc: Handles the async Wake on Ring setting 4100// 4101/****************************************************************************************************/ 4102 4103void AppleUSBCDCACMData::handleSettingCallback(const OSSymbol *arg_type, OSObject *arg_val, uintptr_t refcon) 4104{ 4105 UInt32 WoR; 4106 4107 XTRACE(this, 0, 0, "handleSettingCallback"); 4108 4109 WoR = ((OSNumber *)arg_val)->unsigned32BitValue(); 4110 4111 if (arg_type == gPMWakeOnRingSymbol) 4112 { 4113 if (WoR != fWoR) 4114 { 4115 fWoR = WoR; 4116 if (fTerminate || fStopping) 4117 { 4118 XTRACE(this, 0, 0, "handleSettingCallback - Offline"); 4119 return; 4120 } 4121 setWakeFeature(); 4122 } else { 4123 XTRACE(this, 0, 0, "handleSettingCallback - Wake on Ring unchanged"); 4124 } 4125 } 4126 4127}/* end handleSettingCallback */ 4128 4129/****************************************************************************************************/ 4130// 4131// Function: AppleUSBCDCACMData::setupWakeOnRingPMCallback 4132// 4133// Inputs: none 4134// 4135// Outputs: return code - true( callback enabled), false(disabled) 4136// 4137// Desc: Set up the PM callback for Wake on Ring 4138// 4139/****************************************************************************************************/ 4140 4141bool AppleUSBCDCACMData::setupWakeOnRingPMCallback() 4142{ 4143 IOReturn ior; 4144 bool worOK = false; 4145 const OSSymbol *settings_arr[] = {gPMWakeOnRingSymbol, (const OSSymbol *)NULL}; 4146 4147 XTRACE(this, 0, 0, "setupWakeOnRingPMCallback"); 4148 4149 if (fPMRootDomain) 4150 { 4151 fPMRootDomain->publishFeature("WakeOnRing"); 4152 4153 ior = fPMRootDomain->registerPMSettingController(settings_arr, 4154 OSMemberFunctionCast(IOPMSettingControllerCallback, 4155 (OSObject*)this, 4156 &AppleUSBCDCACMData::handleSettingCallback), 4157 (OSObject *)this, 4158 (uintptr_t)NULL, 4159 (OSObject **)&fWakeSettingControllerHandle); 4160 if (ior == kIOReturnSuccess) 4161 { 4162 XTRACE(this, 0, 0, "setupWakeOnRingPMCallback - Setting PM callback successful"); 4163 worOK = true; 4164 } else { 4165 XTRACE(this, 0, 0, "setupWakeOnRingPMCallback - Setting PM callback failed, wake-on-ring set at start only"); 4166 } 4167 } else { 4168 XTRACE(this, 0, 0, "setupWakeOnRingPMCallback - PM root domain is invalid, wake-on-ring set at start only"); 4169 } 4170 4171 return worOK; 4172 4173}/* end setupWakeOnRingPMCallback */ 4174 4175/****************************************************************************************************/ 4176// 4177// Function: AppleUSBCDCACMData::WakeonRing 4178// 4179// Inputs: none 4180// 4181// Outputs: return code - true(always at the moment...) 4182// 4183// Desc: Get the current Wake on Ring setting 4184// 4185/****************************************************************************************************/ 4186 4187bool AppleUSBCDCACMData::WakeonRing(void) 4188{ 4189 OSObject *initWORValue = NULL; 4190 UInt32 worVal; 4191 4192 XTRACE(this, 0, 0, "WakeonRing"); 4193 4194 fPMRootDomain = getPMRootDomain(); 4195 if (fPMRootDomain) 4196 { 4197 fPMRootDomain->registerInterestedDriver(this); 4198 initWORValue = fPMRootDomain->copyPMSetting((OSSymbol *)gPMWakeOnRingSymbol); 4199 if (initWORValue) 4200 { 4201 worVal = ((OSNumber *)initWORValue)->unsigned32BitValue(); 4202 if (worVal) 4203 { 4204 XTRACE(this, 0, worVal, "WakeonRing - Wake on Ring Enabled"); 4205 fWoR = true; 4206 } else { 4207 XTRACE(this, 0, 0, "WakeonRing - Wake on Ring Disabled"); 4208 } 4209 } else { 4210 XTRACE(this, 0, 0, "WakeonRing - Initial Wake on Ring unavailable, now disabled..."); 4211 } 4212 } else { 4213 XTRACE(this, 0, 0, "WakeonRing - Remote wake up is disabled"); 4214 } 4215 4216 return true; 4217 4218}/* end WakeonRing */ 4219 4220/****************************************************************************************************/ 4221// 4222// Function: AppleUSBCDCACMData::setWakeFeature 4223// 4224// Inputs: none 4225// 4226// Outputs: none 4227// 4228// Desc: Check the wake-on-ring feature and send the device request 4229// 4230/****************************************************************************************************/ 4231 4232void AppleUSBCDCACMData::setWakeFeature(void) 4233{ 4234 IOUSBDevRequest devreq; 4235 IOReturn ior; 4236 4237 XTRACE(this, 0, 0, "setWakeFeature"); 4238 4239 // Set/Clear the Device Remote Wake feature depending upon wake-on-ring 4240 4241 devreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice); 4242 if (!fWoR) 4243 { 4244 devreq.bRequest = kUSBRqClearFeature; 4245 } else { 4246 devreq.bRequest = kUSBRqSetFeature; 4247 } 4248 devreq.wValue = kUSBFeatureDeviceRemoteWakeup; 4249 devreq.wIndex = 0; 4250 devreq.wLength = 0; 4251 devreq.pData = 0; 4252 4253 ior = fDataInterface->GetDevice()->DeviceRequest(&devreq); 4254 if (ior == kIOReturnSuccess) 4255 { 4256 XTRACE(this, fWoR, ior, "setWakeFeature - Set/Clear remote wake up feature successful"); 4257 } else { 4258 XTRACE(this, fWoR, ior, "setWakeFeature - Set/Clear remote wake up feature failed"); 4259 } 4260 4261}/* end setWakeFeature */ 4262 4263/****************************************************************************************************/ 4264// 4265// Method: AppleUSBCDCACMData::clearSleepingThreads 4266// 4267// Inputs: 4268// 4269// Outputs: 4270// 4271// Desc: Try to clear any threads asleep on the command gate 4272// 4273/****************************************************************************************************/ 4274 4275void AppleUSBCDCACMData::clearSleepingThreads() 4276{ 4277 4278 XTRACE(this, 0, fThreadSleepCount, "clearSleepingThreads"); 4279 4280 // If we still have a command gate clean up anything sleeping on it 4281 4282 if (fCommandGate) 4283 { 4284 if (fThreadSleepCount > 0) 4285 { 4286 fPort.WatchStateMask = 0; 4287 fCommandGate->commandWakeup((void *)&fPort.State); 4288 } 4289 } 4290 4291}/* end clearSleepingThreads */ 4292 4293/****************************************************************************************************/ 4294// 4295// Method: AppleUSBCDCACMData::resurrectRead 4296// 4297// Inputs: 4298// 4299// Outputs: 4300// 4301// Desc: Try and resurrect any dead reads 4302// 4303/****************************************************************************************************/ 4304 4305void AppleUSBCDCACMData::resurrectRead() 4306{ 4307 UInt16 i; 4308 IOReturn rtn; 4309 4310 XTRACE(this, 0, 0, "resurrectRead"); 4311 4312 if (fTerminate || fStopping) 4313 { 4314 XTRACE(this, 0, 0, "resurrectRead - device is Offline"); 4315 return; 4316 } 4317 // Let's check the pipes first 4318 4319 if (fPort.InPipe) 4320 { 4321 checkPipe(fPort.InPipe, false); 4322 } 4323 4324 if (fPort.OutPipe) 4325 { 4326 checkPipe(fPort.OutPipe, false); 4327 } 4328 4329 for (i=0; i<fInBufPool; i++) 4330 { 4331 if (fPort.inPool[i].pipeMDP) 4332 { 4333 if (fPort.inPool[i].dead) 4334 { 4335 rtn = fPort.InPipe->Read(fPort.inPool[i].pipeMDP, &fPort.inPool[i].completionInfo, NULL); 4336 if (rtn != kIOReturnSuccess) 4337 { 4338 XTRACE(this, i, rtn, "resurrectRead - Read for bulk-in pipe failed, still dead"); 4339 } else { 4340 XTRACEP(this, &fPort.inPool[i], fPort.InPipe, "resurrectRead - Read posted"); 4341 fPort.inPool[i].dead = false; 4342 } 4343 } 4344 } 4345 } 4346 4347}/* end resurrectRead */ 4348 4349/****************************************************************************************************/ 4350// 4351// Method: AppleUSBCDCACMData::didTerminate 4352// 4353// Inputs: type - provider - my provider 4354// options - additional parameters 4355// defer - defer flag 4356// 4357// Outputs: return Code 4358// 4359// Desc: Handle did termination notification 4360// 4361/****************************************************************************************************/ 4362 4363bool AppleUSBCDCACMData::didTerminate(IOService *provider, IOOptionBits options, bool *defer) 4364{ 4365 bool result = false; 4366 4367 XTRACE(this, 0, fThreadSleepCount, "didTerminate"); 4368 4369 fTerminate = true; // Just to make sure 4370 4371 clearSleepingThreads(); // All the threads should be gone by now but make sure 4372 4373 result = super::didTerminate(provider, options, defer); 4374 4375 return result; 4376 4377}/* end didTerminate */ 4378 4379/****************************************************************************************************/ 4380// 4381// Method: AppleUSBCDCACMData::message 4382// 4383// Inputs: type - message type 4384// provider - my provider 4385// argument - additional parameters 4386// 4387// Outputs: return Code - kIOReturnSuccess 4388// 4389// Desc: Handles IOKit messages. 4390// 4391/****************************************************************************************************/ 4392 4393IOReturn AppleUSBCDCACMData::message(UInt32 type, IOService *provider, void *argument) 4394{ 4395 4396 XTRACE(this, 0, type, "message"); 4397 4398 switch (type) 4399 { 4400 case kIOMessageServiceIsTerminated: 4401 XTRACE(this, fSessions, type, "message - kIOMessageServiceIsTerminated"); 4402 4403 if (!fSuppressWarning) 4404 { 4405 if (fSessions) 4406 { 4407 if (!fTerminate) // Check if we're already being terminated 4408 { 4409#if 0 4410 // NOTE! This call below depends on the hard coded path of this KEXT. Make sure 4411 // that if the KEXT moves, this path is changed! 4412 KUNCUserNotificationDisplayNotice( 4413 10, // Timeout in seconds 4414 0, // Flags (for later usage) 4415 "", // iconPath (not supported yet) 4416 "", // soundPath (not supported yet) 4417 "/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBCDCACMData.kext", // localizationPath 4418 "Unplug Header", // the header 4419 "Unplug Notice", // the notice - look in Localizable.strings 4420 "OK"); 4421#endif 4422 } 4423 } 4424 } 4425 4426 fTerminate = true; // We're being terminated (unplugged) let's see if we can clean up some threads and release some stuff 4427 4428 releaseResources(); 4429 return kIOReturnSuccess; 4430 4431 case kIOMessageServiceIsSuspended: 4432 XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended"); 4433 break; 4434 case kIOMessageServiceIsResumed: 4435 XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed"); 4436 break; 4437 case kIOMessageServiceIsRequestingClose: 4438 XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose"); 4439 break; 4440 case kIOMessageServiceWasClosed: 4441 XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed"); 4442 break; 4443 case kIOMessageServiceBusyStateChange: 4444 XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange"); 4445 break; 4446 case kIOUSBMessagePortHasBeenResumed: 4447 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed"); 4448 resurrectRead(); 4449 return kIOReturnSuccess; 4450 case kIOUSBMessageHubResumePort: 4451 XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort"); 4452 break; 4453 case kIOUSBMessagePortHasBeenReset: 4454 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenReset"); 4455 resurrectRead(); 4456 if (fConfigAttributes & kUSBAtrRemoteWakeup) 4457 { 4458 setWakeFeature(); 4459 } 4460 return kIOReturnSuccess; 4461 default: 4462 XTRACE(this, 0, type, "message - unknown message"); 4463 break; 4464 } 4465 4466 return super::message(type, provider, argument); 4467 4468}/* end message */ 4469 4470/****************************************************************************************************/ 4471// 4472// Method: AppleUSBCDCACMData::getPortNameForInterface 4473// 4474// Inputs: interfaceNumber - the number of the interface we're interested in 4475// 4476// Outputs: return Code - NULL (not found) or the name 4477// 4478// Desc: Gets the name from the mapping 4479// 4480/****************************************************************************************************/ 4481 4482OSString *AppleUSBCDCACMData::getPortNameForInterface(UInt8 interfaceNumber) 4483{ 4484 OSSymbol *ttyName = NULL; 4485 char endPointAddrStr[16]; 4486 4487 XTRACE(this, 0, interfaceNumber, "getPortNameForInterface"); 4488 4489 if (fInterfaceMappings) 4490 { 4491 snprintf(endPointAddrStr,sizeof(endPointAddrStr),"%d",interfaceNumber); 4492 ttyName = (OSSymbol *)fInterfaceMappings->getObject(endPointAddrStr); 4493 } 4494 4495 return ttyName; 4496 4497}/* end getPortNameForInterface */ 4498 4499#undef super 4500#define super IOUserClient 4501 4502OSDefineMetaClassAndStructors(AppleUSBCDCACMDataUserClient, IOUserClient); 4503 4504/****************************************************************************************************/ 4505// 4506// Method: AppleUSBCDCACMDataUserClient::getTargetAndMethodForIndex 4507// 4508// Inputs: 4509// 4510// Outputs: return code - method index 4511// 4512// Desc: Get the method index. 4513// 4514/****************************************************************************************************/ 4515 4516//IOExternalMethod *AppleUSBCDCACMDataUserClient::getExternalMethodForIndex(UInt32 index) 4517IOExternalMethod *AppleUSBCDCACMDataUserClient::getTargetAndMethodForIndex(IOService **targetP, UInt32 index) 4518{ 4519 IOExternalMethod *result = NULL; 4520 4521 XTRACE(this, 0, index, "getTargetAndMethodForIndex"); 4522 4523 if (index == 0) 4524 { 4525 result = &fMethods[0]; 4526 *targetP = this; 4527 } 4528 4529 return result; 4530 4531}/* end getTargetAndMethodForIndex */ 4532 4533/****************************************************************************************************/ 4534// 4535// Method: AppleUSBCDCACMDataUserClient::initWithTask 4536// 4537// Inputs: owningTask - the owner 4538// security_id - Security ID 4539// type - Client code (lucky number) 4540// 4541// Outputs: true - it worked, false - it didn't 4542// 4543// Desc: Set up the user client task. 4544// 4545/****************************************************************************************************/ 4546 4547bool AppleUSBCDCACMDataUserClient::initWithTask(task_t owningTask, void *security_id , UInt32 type) 4548{ 4549 4550 XTRACE(this, 0, 0, "initWithTask"); 4551 4552 if (!super::initWithTask(owningTask, security_id, type)) 4553 { 4554 XTRACE(this, 0, 0, "initWithTask - super failed"); 4555 return false; 4556 } 4557 4558 if (!owningTask) 4559 { 4560 XTRACE(this, 0, 0, "initWithTask - No owning task"); 4561 return false; 4562 } 4563 4564 fTask = owningTask; 4565 fProvider = NULL; 4566 4567 return true; 4568 4569}/* end initWithTask */ 4570 4571/****************************************************************************************************/ 4572// 4573// Method: AppleUSBCDCACMDataUserClient::start 4574// 4575// Inputs: provider - my provider 4576// 4577// Outputs: return code - true(it worked), false (it didn't) 4578// 4579// Desc: Start the user client task. 4580// 4581/****************************************************************************************************/ 4582 4583bool AppleUSBCDCACMDataUserClient::start(IOService *provider) 4584{ 4585 4586 XTRACE(this, 0, 0, "start"); 4587 4588 if (super::start(provider) == false) 4589 { 4590 XTRACE(this, 0, 0, "start - Provider start failed"); 4591 return false; 4592 } 4593 4594 fProvider = OSDynamicCast(AppleUSBCDCACMData, provider); 4595 if (!fProvider) 4596 { 4597 XTRACE(this, 0, 0, "start - Provider invalid"); 4598 return false; 4599 } 4600 4601 // Initialize the call structure 4602 4603 fMethods[0].object = this; 4604 fMethods[0].func = (IOMethod)&AppleUSBCDCACMDataUserClient::doRequest; 4605 fMethods[0].count0 = 0xFFFFFFFF; /* One input as big as I need */ 4606 fMethods[0].count1 = 0xFFFFFFFF; /* One output as big as I need */ 4607 fMethods[0].flags = kIOUCStructIStructO; 4608 4609 return true; 4610 4611}/* end start */ 4612 4613/****************************************************************************************************/ 4614// 4615// Method: AppleUSBCDCACMDataUserClient::clientClose 4616// 4617// Inputs: 4618// 4619// Outputs: return code - kIOReturnSuccess 4620// 4621// Desc: Close things down. 4622// 4623/****************************************************************************************************/ 4624 4625IOReturn AppleUSBCDCACMDataUserClient::clientClose() 4626{ 4627 4628 XTRACE(this, 0, 0, "clientClose"); 4629 4630 if (!fProvider) 4631 { 4632 XTRACE(this, 0, 0, "clientClose - Not attached"); 4633 return kIOReturnNotAttached; 4634 } 4635 4636 // Make sure it's open before we close it. 4637 4638 if (fProvider->isOpen(this)) 4639 fProvider->close(this); 4640 4641 fTask = NULL; 4642 fProvider = NULL; 4643 4644 return kIOReturnSuccess; 4645 4646}/* end clientClose */ 4647 4648/****************************************************************************************************/ 4649// 4650// Method: AppleUSBCDCACMDataUserClient::clientDied 4651// 4652// Inputs: 4653// 4654// Outputs: return code - kIOReturnSuccess 4655// 4656// Desc: Close it down now. 4657// 4658/****************************************************************************************************/ 4659 4660IOReturn AppleUSBCDCACMDataUserClient::clientDied() 4661{ 4662 4663 XTRACE(this, 0, 0, "clientDied"); 4664 4665 return clientClose(); 4666 4667}/* end clientDied */ 4668 4669/****************************************************************************************************/ 4670// 4671// Method: AppleUSBCDCACMDataUserClient::doRequest 4672// 4673// Inputs: pIn - the input buffer 4674// pOut - the output buffer 4675// inputSize - Size of input buffer 4676// pOutPutSize - Size of output buffer 4677// 4678// Outputs: pOutSize - Number of bytes returned 4679// return code - kIOReturnSuccess or kIOReturnBadArgument 4680// 4681// Desc: Execute the client request. 4682// 4683/****************************************************************************************************/ 4684 4685IOReturn AppleUSBCDCACMDataUserClient::doRequest(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *pOutPutSize) 4686{ 4687 UInt8 *input; 4688 4689 XTRACE(this, 0, 0, "doRequest"); 4690 4691 // Make sure we actually have a provider 4692 4693 if (!fProvider) 4694 { 4695 XTRACE(this, 0, 0, "doRequest - Not attached"); 4696 return kIOReturnNotAttached; 4697 } 4698 4699 // check first byte of input data for a command code 4700 4701 if (pIn && (inputSize > 0)) 4702 { 4703 input = (UInt8 *)pIn; 4704 4705 // 1st byte of input has request ID 4706 4707 switch (*input) 4708 { 4709 case cmdACMData_Message: 4710 return ACMDataMessage(pIn, pOut, inputSize, pOutPutSize); 4711 4712 default: 4713 XTRACE(this, 0, *input, "doRequest - Invalid command"); 4714 break; 4715 } 4716 } else { 4717 XTRACE(this, 0, inputSize, "doRequest - pIn/pOut or size error"); 4718 } 4719 4720 return kIOReturnBadArgument; 4721 4722}/* end doRequest */ 4723 4724/****************************************************************************************************/ 4725// 4726// Method: AppleUSBCDCACMDataUserClient::ACMDataMessage 4727// 4728// Inputs: pIn - the input structure 4729// pOut - the output structure 4730// inputSize - Size of the input structure 4731// pOutSize - Size of the output structure 4732// 4733// Outputs: return code - kIOReturnSuccess 4734// 4735// Desc: Process the message 4736// 4737/****************************************************************************************************/ 4738 4739IOReturn AppleUSBCDCACMDataUserClient::ACMDataMessage(void *pIn, void *pOut, IOByteCount inputSize, IOByteCount *pOutPutSize) 4740{ 4741 dataParms *input = (dataParms *)pIn; 4742 statusData *output = (statusData *)pOut; 4743 4744 XTRACE(this, 0, 0, "ACMDataMessage"); 4745 4746 switch (input->message) 4747 { 4748 case noWarning: 4749 XTRACE(this, 0, 0, "ACMDataMessage - noWarning"); 4750 if ((input->vendor == fProvider->fVendorID) && (input->product == fProvider->fProductID)) 4751 { 4752 XTRACE(this, fProvider->fVendorID, fProvider->fProductID, "ACMDataMessage - Unplug warning dialog is being suppressed"); 4753 fProvider->fSuppressWarning = true; 4754 output->status = kSuccess; 4755 } else { 4756 XTRACE(this, 0, 0, "ACMDataMessage - noWarning, not my device"); 4757 output->status = kError; 4758 } 4759 break; 4760 case warning: 4761 XTRACE(this, 0, 0, "ACMDataMessage - warning"); 4762 if ((input->vendor == fProvider->fVendorID) && (input->product == fProvider->fProductID)) 4763 { 4764 XTRACE(this, fProvider->fVendorID, fProvider->fProductID, "ACMDataMessage - Unplug warning dialog is being re-instated"); 4765 fProvider->fSuppressWarning = false; 4766 output->status = kSuccess; 4767 } else { 4768 XTRACE(this, 0, 0, "ACMDataMessage - warning, not my device"); 4769 output->status = kError; 4770 } 4771 break; 4772 default: 4773 XTRACE(this, 0, 0, "ACMDataMessage - Invalid message"); 4774 output->status = kError; 4775 break; 4776 } 4777 4778 return kIOReturnSuccess; 4779 4780}/* end ACMDataMessage */