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