1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1998-2004 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 /* AppleUSBCDCDMM.cpp - MacOSX implementation of */ 26 /* USB Communication Device Class (CDC) Driver, DMM 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 "AppleUSBCDCDMM" 58 59#include "AppleUSBCDCDMM.h" 60 61#define MIN_BAUD (50 << 1) 62 63 // Globals 64 65#define super IOSerialDriverSync 66 67OSDefineMetaClassAndStructors(AppleUSBCDCDMM, IOSerialDriverSync); 68 69#if LOG_DATA 70#define dumplen 32 // Set this to the number of bytes to dump and the rest should work out correct 71 72#define buflen ((dumplen*2)+dumplen)+3 73#define Asciistart (dumplen*2)+3 74 75/****************************************************************************************************/ 76// 77// Function: USBLogData 78// 79// Inputs: Dir - direction 80// Count - number of bytes 81// buf - the data 82// 83// Outputs: 84// 85// Desc: Puts the data in the log. 86// 87/****************************************************************************************************/ 88 89void AppleUSBCDCDMM::USBLogData(UInt8 Dir, SInt32 Count, char *buf) 90{ 91 SInt32 wlen; 92 SInt32 llen, rlen; 93 SInt16 i, Aspnt, Hxpnt; 94 UInt8 wchr; 95 char LocBuf[buflen+1]; 96 97 switch (Dir) 98 { 99 case kDataIn: 100 Log( "AppleUSBCDCDMM: USBLogData - Read Complete, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 101 break; 102 case kDataOut: 103 Log( "AppleUSBCDCDMM: USBLogData - Write, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 104 break; 105 case kDataOther: 106 Log( "AppleUSBCDCDMM: USBLogData - Other, address = %8p, size = %8d\n", (void *)buf, (UInt)Count ); 107 break; 108 } 109 110#if DUMPALL 111 wlen = Count; 112#else 113 if (Count > dumplen) 114 { 115 wlen = dumplen; 116 } else { 117 wlen = Count; 118 } 119#endif 120 121 if (wlen == 0) 122 { 123 Log( "AppleUSBCDCDMM: USBLogData - No data, Count=0\n" ); 124 return; 125 } 126 127 rlen = 0; 128 do 129 { 130 memset(LocBuf, 0x20, buflen); 131 132 if (wlen > dumplen) 133 { 134 llen = dumplen; 135 wlen -= dumplen; 136 } else { 137 llen = wlen; 138 wlen = 0; 139 } 140 Aspnt = Asciistart; 141 Hxpnt = 0; 142 for (i=1; i<=llen; i++) 143 { 144 wchr = buf[i-1]; 145 LocBuf[Hxpnt++] = Asciify(wchr >> 4); 146 LocBuf[Hxpnt++] = Asciify(wchr); 147 if ((wchr < 0x20) || (wchr > 0x7F)) // Non printable characters 148 { 149 LocBuf[Aspnt++] = 0x2E; // Replace with a period 150 } else { 151 LocBuf[Aspnt++] = wchr; 152 } 153 } 154 LocBuf[Aspnt] = 0x00; 155 156 Log("%s\n", LocBuf); 157#if USE_IOL 158 IOSleep(Sleep_Time); // Try and keep the log from overflowing 159#endif 160 rlen += llen; 161 buf = &buf[rlen]; 162 } while (wlen != 0); 163 164}/* end USBLogData */ 165#endif 166 167/****************************************************************************************************/ 168// 169// Method: AddBytetoQueue 170// 171// Inputs: Queue - the queue to be added to 172// Value - Byte to be added 173// 174// Outputs: Queue status - full or no error 175// 176// Desc: Add a byte to the circular queue. 177// Check to see if there is space by comparing the next pointer, 178// with the last, If they match we are either Empty or full, so 179// check InQueue for zero. 180// 181/****************************************************************************************************/ 182 183QueueStatus AppleUSBCDCDMM::AddBytetoQueue(CirQueue *Queue, char Value) 184{ 185 186 if ((Queue->NextChar == Queue->LastChar) && Queue->InQueue) 187 { 188 return queueFull; 189 } 190 191 *Queue->NextChar++ = Value; 192 Queue->InQueue++; 193 194 // Check to see if we need to wrap the pointer. 195 196 if (Queue->NextChar >= Queue->End) 197 Queue->NextChar = Queue->Start; 198 199 return queueNoError; 200 201}/* end AddBytetoQueue */ 202 203/****************************************************************************************************/ 204// 205// Method: GetBytetoQueue 206// 207// Inputs: Queue - the queue to be removed from 208// 209// Outputs: Value - where to put the byte 210// QueueStatus - empty or no error 211// 212// Desc: Remove a byte from the circular queue. 213// 214/****************************************************************************************************/ 215 216QueueStatus AppleUSBCDCDMM::GetBytetoQueue(CirQueue *Queue, UInt8 *Value) 217{ 218 219 if ((Queue->NextChar == Queue->LastChar) && !Queue->InQueue) 220 { 221 return queueEmpty; 222 } 223 224 *Value = *Queue->LastChar++; 225 Queue->InQueue--; 226 227 // Check to see if we need to wrap the pointer. 228 229 if (Queue->LastChar >= Queue->End) 230 Queue->LastChar = Queue->Start; 231 232 return queueNoError; 233 234}/* end GetBytetoQueue */ 235 236/****************************************************************************************************/ 237// 238// Method: InitQueue 239// 240// Inputs: Queue - the queue to be initialized 241// Buffer - the buffer 242// size - length of buffer 243// 244// Outputs: QueueStatus - queueNoError. 245// 246// Desc: Pass a buffer of memory and this routine will set up the internal data structures. 247// 248/****************************************************************************************************/ 249 250QueueStatus AppleUSBCDCDMM::InitQueue(CirQueue *Queue, UInt8 *Buffer, size_t Size) 251{ 252 Queue->Start = Buffer; 253 Queue->End = (UInt8*)((size_t)Buffer + Size); 254 Queue->Size = Size; 255 Queue->NextChar = Buffer; 256 Queue->LastChar = Buffer; 257 Queue->InQueue = 0; 258 259// IOSleep(1); 260 261 return queueNoError ; 262 263}/* end InitQueue */ 264 265/****************************************************************************************************/ 266// 267// Method: CloseQueue 268// 269// Inputs: Queue - the queue to be closed 270// 271// Outputs: QueueStatus - queueNoError. 272// 273// Desc: Clear out all of the data structures. 274// 275/****************************************************************************************************/ 276 277QueueStatus AppleUSBCDCDMM::CloseQueue(CirQueue *Queue) 278{ 279 280 Queue->Start = 0; 281 Queue->End = 0; 282 Queue->NextChar = 0; 283 Queue->LastChar = 0; 284 Queue->Size = 0; 285 286 return queueNoError; 287 288}/* end CloseQueue */ 289 290/****************************************************************************************************/ 291// 292// Method: AddtoQueue 293// 294// Inputs: Queue - the queue to be added to 295// Buffer - data to add 296// Size - length of data 297// 298// Outputs: BytesWritten - Number of bytes actually put in the queue. 299// 300// Desc: Add an entire buffer to the queue. 301// 302/****************************************************************************************************/ 303 304size_t AppleUSBCDCDMM::AddtoQueue(CirQueue *Queue, UInt8 *Buffer, size_t Size) 305{ 306 size_t BytesWritten = 0; 307 308 while (FreeSpaceinQueue(Queue) && (Size > BytesWritten)) 309 { 310 AddBytetoQueue(Queue, *Buffer++); 311 BytesWritten++; 312 } 313 314 return BytesWritten; 315 316}/* end AddtoQueue */ 317 318/****************************************************************************************************/ 319// 320// Method: RemovefromQueue 321// 322// Inputs: Queue - the queue to be removed from 323// Size - size of buffer 324// 325// Outputs: Buffer - Where to put the data 326// BytesReceived - Number of bytes actually put in Buffer. 327// 328// Desc: Get a buffers worth of data from the queue. 329// 330/****************************************************************************************************/ 331 332size_t AppleUSBCDCDMM::RemovefromQueue(CirQueue *Queue, UInt8 *Buffer, size_t MaxSize) 333{ 334 size_t BytesReceived = 0; 335 UInt8 Value; 336 337 // while((GetBytetoQueue(Queue, &Value) == queueNoError) && (MaxSize >= BytesReceived)) 338 while((MaxSize > BytesReceived) && (GetBytetoQueue(Queue, &Value) == queueNoError)) 339 { 340 *Buffer++ = Value; 341 BytesReceived++; 342 }/* end while */ 343 344 return BytesReceived; 345 346}/* end RemovefromQueue */ 347 348/****************************************************************************************************/ 349// 350// Method: FreeSpaceinQueue 351// 352// Inputs: Queue - the queue to be queried 353// 354// Outputs: Return Value - Free space left 355// 356// Desc: Return the amount of free space left in this buffer. 357// 358/****************************************************************************************************/ 359 360size_t AppleUSBCDCDMM::FreeSpaceinQueue(CirQueue *Queue) 361{ 362 size_t retVal = 0; 363 364 retVal = Queue->Size - Queue->InQueue; 365 366 return retVal; 367 368}/* end FreeSpaceinQueue */ 369 370/****************************************************************************************************/ 371// 372// Method: UsedSpaceinQueue 373// 374// Inputs: Queue - the queue to be queried 375// 376// Outputs: UsedSpace - Amount of data in buffer 377// 378// Desc: Return the amount of data in this buffer. 379// 380/****************************************************************************************************/ 381 382size_t AppleUSBCDCDMM::UsedSpaceinQueue(CirQueue *Queue) 383{ 384 return Queue->InQueue; 385 386}/* end UsedSpaceinQueue */ 387 388/****************************************************************************************************/ 389// 390// Method: GetQueueSize 391// 392// Inputs: Queue - the queue to be queried 393// 394// Outputs: QueueSize - The size of the queue. 395// 396// Desc: Return the total size of the queue. 397// 398/****************************************************************************************************/ 399 400size_t AppleUSBCDCDMM::GetQueueSize(CirQueue *Queue) 401{ 402 return Queue->Size; 403 404}/* end GetQueueSize */ 405 406/****************************************************************************************************/ 407// 408// Method: GetQueueStatus 409// 410// Inputs: Queue - the queue to be queried 411// 412// Outputs: Queue status - full, empty or no error 413// 414// Desc: Returns the status of the circular queue. 415// 416/****************************************************************************************************/ 417 418QueueStatus AppleUSBCDCDMM::GetQueueStatus(CirQueue *Queue) 419{ 420 if ((Queue->NextChar == Queue->LastChar) && Queue->InQueue) 421 return queueFull; 422 else if ((Queue->NextChar == Queue->LastChar) && !Queue->InQueue) 423 return queueEmpty; 424 425 return queueNoError ; 426 427}/* end GetQueueStatus */ 428 429/****************************************************************************************************/ 430// 431// Method: isCRinQueue 432// 433// Inputs: Queue - the queue to be looked at 434// 435// Outputs: return code - number of bytes 436// 437// Desc: Is there a cr in the queue. 438// 439/****************************************************************************************************/ 440 441UInt16 AppleUSBCDCDMM::isCRinQueue(CirQueue *Queue) 442{ 443 UInt8 *last; 444 bool done = false; 445 UInt16 i = 1; 446 447 if ((Queue->NextChar == Queue->LastChar) && !Queue->InQueue) 448 { 449 return 0; 450 } 451 452 last = Queue->LastChar; 453 454 while (!done) 455 { 456 if (*last == 0x0D) 457 { 458 done = true; 459 } else { 460 last++; 461 i++; 462 if (last >= Queue->End) 463 { 464 last = Queue->Start; 465 } 466 if (last == Queue->NextChar) 467 { 468 i = 0; 469 done = true; 470 } 471 } 472 } 473 474 return i; 475 476}/* end isCRinQueue */ 477 478/****************************************************************************************************/ 479// 480// Method: CheckQueues 481// 482// Inputs: 483// 484// Outputs: 485// 486// Desc: Checks the various queue's etc and manipulates the state(s) accordingly 487// Must be called from a gated method or completion routine. 488// 489/****************************************************************************************************/ 490 491void AppleUSBCDCDMM::CheckQueues() 492{ 493 UInt32 Used; 494 UInt32 Free; 495 UInt32 QueuingState; 496 UInt32 DeltaState; 497 498 // Initialise the QueueState with the current state. 499 500 QueuingState = fPort.State; 501 502 // Check to see if there is anything in the Transmit buffer. 503 504 Used = UsedSpaceinQueue(&fPort.TX); 505 Free = FreeSpaceinQueue(&fPort.TX); 506 507 XTRACE(this, Free, Used, "CheckQueues"); 508 509 if (Free == 0) 510 { 511 QueuingState |= PD_S_TXQ_FULL; 512 QueuingState &= ~PD_S_TXQ_EMPTY; 513 } else { 514 if (Used == 0) 515 { 516 QueuingState &= ~PD_S_TXQ_FULL; 517 QueuingState |= PD_S_TXQ_EMPTY; 518 } else { 519 QueuingState &= ~PD_S_TXQ_FULL; 520 QueuingState &= ~PD_S_TXQ_EMPTY; 521 } 522 } 523 524 // Check to see if we are below the low water mark. 525 526 if (Used < fPort.TXStats.LowWater) 527 QueuingState |= PD_S_TXQ_LOW_WATER; 528 else QueuingState &= ~PD_S_TXQ_LOW_WATER; 529 530 if (Used > fPort.TXStats.HighWater) 531 QueuingState |= PD_S_TXQ_HIGH_WATER; 532 else QueuingState &= ~PD_S_TXQ_HIGH_WATER; 533 534 535 // Check to see if there is anything in the Receive buffer. 536 537 Used = UsedSpaceinQueue(&fPort.RX); 538 Free = FreeSpaceinQueue(&fPort.RX); 539 540 if (Free == 0) 541 { 542 QueuingState |= PD_S_RXQ_FULL; 543 QueuingState &= ~PD_S_RXQ_EMPTY; 544 } else { 545 if (Used == 0) 546 { 547 QueuingState &= ~PD_S_RXQ_FULL; 548 QueuingState |= PD_S_RXQ_EMPTY; 549 } else { 550 QueuingState &= ~PD_S_RXQ_FULL; 551 QueuingState &= ~PD_S_RXQ_EMPTY; 552 } 553 } 554 555 // Check to see if we are below the low water mark. 556 557 if (Used < fPort.RXStats.LowWater) 558 QueuingState |= PD_S_RXQ_LOW_WATER; 559 else QueuingState &= ~PD_S_RXQ_LOW_WATER; 560 561 if (Used > fPort.RXStats.HighWater) 562 QueuingState |= PD_S_RXQ_HIGH_WATER; 563 else QueuingState &= ~PD_S_RXQ_HIGH_WATER; 564 565 // Figure out what has changed to get mask. 566 567 DeltaState = QueuingState ^ fPort.State; 568 setStateGated(&QueuingState, &DeltaState); 569 570}/* end CheckQueues */ 571 572/****************************************************************************************************/ 573// 574// Method: AppleUSBCDCDMM::intReadComplete 575// 576// Inputs: obj - me 577// rc - return code 578// remaining - what's left 579// 580// Outputs: None 581// 582// Desc: Interrupt pipe (DMM interface) read completion routine 583// 584/****************************************************************************************************/ 585 586void AppleUSBCDCDMM::intReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 587{ 588 AppleUSBCDCDMM *me = (AppleUSBCDCDMM*)obj; 589 IOReturn ior; 590 UInt32 dLen; 591 592 XTRACE(me, rc, 0, "intReadComplete"); 593 594 if (me->fStopping) 595 return; 596 597 if (rc == kIOReturnSuccess) // If operation returned ok 598 { 599 dLen = me->fIntBufferSize - remaining; 600 XTRACE(me, me->fIntPipeBuffer[1], dLen, "intReadComplete - Notification and length"); 601 602 // Now look at the notification 603 604 if (me->fIntPipeBuffer[1] == kUSBRESPONSE_AVAILABLE) 605 { 606 rc = me->sendMERRequest(kUSBGET_ENCAPSULATED_RESPONSE, 0, me->fMax_Command, me->fInBuffer, &me->fRspCompletionInfo); 607 if (rc != kIOReturnSuccess) 608 { 609 XTRACE(me, 0, rc, "intReadComplete - sendMERRequest failed"); 610 } 611 } 612 } else { 613 XTRACE(me, 0, rc, "intReadComplete - error"); 614 } 615 616 // Queue the next read only if not aborted 617 618 if (rc != kIOReturnAborted) 619 { 620 ior = me->fIntPipe->Read(me->fIntPipeMDP, &me->fIntCompletionInfo, NULL); 621 if (ior != kIOReturnSuccess) 622 { 623 XTRACE(me, 0, rc, "intReadComplete - Read io error"); 624 me->fReadDead = true; 625 } 626 } else { 627 me->fReadDead = true; 628 } 629 630}/* end intReadComplete */ 631 632/****************************************************************************************************/ 633// 634// Method: AppleUSBCDCDMM::merWriteComplete 635// 636// Inputs: obj - me 637// param - MER 638// rc - return code 639// remaining - what's left 640// 641// Outputs: None 642// 643// Desc: Management Element Request write completion routine 644// 645/****************************************************************************************************/ 646 647void AppleUSBCDCDMM::merWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 648{ 649#if LDEBUG 650 AppleUSBCDCDMM *me = (AppleUSBCDCDMM*)obj; 651#endif 652 IOUSBDevRequest *MER = (IOUSBDevRequest *)param; 653 UInt16 dataLen; 654 655 XTRACE(0, 0, remaining, "merWriteComplete"); 656 657 if (MER) 658 { 659 if (rc == kIOReturnSuccess) 660 { 661 XTRACE(me, MER->bRequest, remaining, "merWriteComplete - request"); 662 } else { 663 XTRACE(me, MER->bRequest, rc, "merWriteComplete - io err"); 664 } 665 666 dataLen = MER->wLength; 667 XTRACE(me, 0, dataLen, "merWriteComplete - data length"); 668 if ((dataLen != 0) && (MER->pData)) 669 { 670 IOFree(MER->pData, dataLen); 671 } 672 IOFree(MER, sizeof(IOUSBDevRequest)); 673 674 } else { 675 if (rc == kIOReturnSuccess) 676 { 677 XTRACE(me, 0, remaining, "merWriteComplete (request unknown)"); 678 } else { 679 XTRACE(me, 0, rc, "merWriteComplete (request unknown) - io err"); 680 } 681 } 682 683}/* end merWriteComplete */ 684 685/****************************************************************************************************/ 686// 687// Method: AppleUSBCDCDMM::rspComplete 688// 689// Inputs: obj - me 690// param - MER 691// rc - return code 692// remaining - what's left 693// 694// Outputs: None 695// 696// Desc: Encapsulated response (MER) completion routine 697// 698/****************************************************************************************************/ 699 700void AppleUSBCDCDMM::rspComplete(void *obj, void *param, IOReturn rc, UInt32 remaining) 701{ 702 AppleUSBCDCDMM *me = (AppleUSBCDCDMM*)obj; 703 IOUSBDevRequest *MER = (IOUSBDevRequest *)param; 704 UInt16 dataLen; 705 706 XTRACE(me, 0, remaining, "rspComplete"); 707 708 if (MER) 709 { 710 dataLen = MER->wLength; 711 if (rc == kIOReturnSuccess) 712 { 713 XTRACE(me, MER->bRequest, dataLen, "rspComplete - request and data length"); 714 if ((MER->bRequest == kUSBGET_ENCAPSULATED_RESPONSE) && (dataLen > 0)) 715 { 716 meLogData(kDataIn, dataLen, MER->pData); 717 718 // Move the incoming bytes to the ring buffer 719 720 me->AddtoQueue(&me->fPort.RX, (UInt8 *)MER->pData, dataLen); 721 722 me->CheckQueues(); 723 } 724 } else { 725 XTRACE(me, MER->bRequest, rc, "rspComplete - io err"); 726 } 727 728 if ((dataLen != 0) && (MER->pData)) 729 { 730 IOFree(MER->pData, dataLen); 731 } 732 IOFree(MER, sizeof(IOUSBDevRequest)); 733 734 } else { 735 if (rc == kIOReturnSuccess) 736 { 737 XTRACE(me, 0, remaining, "rspComplete (request unknown)"); 738 } else { 739 XTRACE(me, 0, rc, "rspComplete (request unknown) - io err"); 740 } 741 } 742 743}/* end rspComplete */ 744 745/****************************************************************************************************/ 746// 747// Method: AppleUSBCDCDMM::probe 748// 749// Inputs: provider - my provider 750// 751// Outputs: IOService - from super::probe, score - probe score 752// 753// Desc: Modify the probe score if necessary (we don't at the moment) 754// 755/****************************************************************************************************/ 756 757IOService* AppleUSBCDCDMM::probe( IOService *provider, SInt32 *score ) 758{ 759 IOService *res; 760 761 // If our IOUSBInterface has a "do not match" property, it means that we should not match and need 762 // to bail. See rdar://3716623 763 764 OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface")); 765 if (boolObj && boolObj->isTrue()) 766 { 767 XTRACE(this, 0, 0, "probe - provider doesn't want us to match"); 768 return NULL; 769 } 770 771 res = super::probe(provider, score); 772 773 return res; 774 775}/* end probe */ 776 777/****************************************************************************************************/ 778// 779// Method: AppleUSBCDCDMM::start 780// 781// Inputs: provider - my provider 782// 783// Outputs: Return code - true (it's me), false (sorry it probably was me, but I can't configure it) 784// 785// Desc: This is called once it has been determined I'm probably the best 786// driver for this device. 787// 788/****************************************************************************************************/ 789 790bool AppleUSBCDCDMM::start(IOService *provider) 791{ 792 793 fSessions = 0; 794 fTerminate = false; 795 fStopping = false; 796 fWorkLoop = NULL; 797 fMax_Command = 256; 798 fIntBufferSize = INT_BUFF_SIZE; 799 800 initStructure(); 801 802 XTRACE(this, 0, 0, "start"); 803 804 if(!super::start(provider)) 805 { 806 ALERT(0, 0, "start - super failed"); 807 return false; 808 } 809 810 // Get my USB provider - the interface 811 812 fInterface = OSDynamicCast(IOUSBInterface, provider); 813 if(!fInterface) 814 { 815 ALERT(0, 0, "start - provider invalid"); 816 return false; 817 } 818 819 // get workloop 820 821 fWorkLoop = getWorkLoop(); 822 if (!fWorkLoop) 823 { 824 ALERT(0, 0, "start - getWorkLoop failed"); 825 return false; 826 } 827 828 fCommandGate = IOCommandGate::commandGate(this); 829 if (!fCommandGate) 830 { 831 ALERT(0, 0, "start - commandGate failed"); 832 return false; 833 } 834 835 if (fWorkLoop->addEventSource(fCommandGate) != kIOReturnSuccess) 836 { 837 ALERT(0, 0, "start - addEventSource(commandGate) failed"); 838 return false; 839 } 840 841 if (!configureDMM()) 842 { 843 ALERT(0, 0, "start - configureDMM failed"); 844 return false; 845 } 846 847 if (!allocateResources()) 848 { 849 ALERT(0, 0, "start - allocateResources failed"); 850 return false; 851 } 852 853 if (!createSerialStream()) // Publish SerialStream services 854 { 855 ALERT(0, 0, "start - createSerialStream failed"); 856 return false; 857 } 858 859 // Looks like we're ok 860 861 fInterface->retain(); 862 fWorkLoop->retain(); 863 fCommandGate->enable(); 864 865 XTRACE(this, 0, 0, "start - successful and IOModemSerialStreamSync created"); 866 Log(DEBUG_NAME ": Version number - %s\n", VersionNumber); 867 868 return true; 869 870}/* end start */ 871 872/****************************************************************************************************/ 873// 874// Method: AppleUSBCDCDMM::stop 875// 876// Inputs: provider - my provider 877// 878// Outputs: None 879// 880// Desc: Stops the driver 881// 882/****************************************************************************************************/ 883 884void AppleUSBCDCDMM::stop(IOService *provider) 885{ 886 IOReturn ret; 887 888 XTRACE(this, 0, 0, "stop"); 889 890 fStopping = true; 891 892 retain(); 893 ret = fCommandGate->runAction(stopAction); 894 release(); 895 896 removeProperty((const char *)propertyTag); 897 898 super::stop(provider); 899 900}/* end stop */ 901 902/****************************************************************************************************/ 903// 904// Method: AppleUSBCDCDMM::stopAction 905// 906// Desc: Dummy pass through for stopGated. 907// 908/****************************************************************************************************/ 909 910IOReturn AppleUSBCDCDMM::stopAction(OSObject *owner, void *, void *, void *, void *) 911{ 912 913 ((AppleUSBCDCDMM *)owner)->stopGated(); 914 915 return kIOReturnSuccess; 916 917}/* end stopAction */ 918 919/****************************************************************************************************/ 920// 921// Method: AppleUSBCDCDMM::stopGated 922// 923// Inputs: 924// 925// Outputs: 926// 927// Desc: Releases the resources 928// 929/****************************************************************************************************/ 930 931void AppleUSBCDCDMM::stopGated() 932{ 933 934 XTRACE(this, 0, 0, "stopGated"); 935 936 releaseResources(); 937 938}/* end stopGated */ 939 940/****************************************************************************************************/ 941// 942// Method: AppleUSBCDCDMM::configureDMM 943// 944// Inputs: 945// 946// Outputs: return Code - true (configured), false (not configured) 947// 948// Desc: Configures the Device Management Model interface etc. 949// 950/****************************************************************************************************/ 951 952bool AppleUSBCDCDMM::configureDMM() 953{ 954 955 XTRACE(this, 0, 0, "configureDMM"); 956 957 fInterfaceNumber = fInterface->GetInterfaceNumber(); 958 XTRACE(this, 0, fInterfaceNumber, "configureDMM - Interface number."); 959 960 if (!getFunctionalDescriptors()) 961 { 962 XTRACE(this, 0, 0, "configureDMM - getFunctionalDescriptors failed"); 963 return false; 964 } 965 966 return true; 967 968}/* end configureDMM */ 969 970/****************************************************************************************************/ 971// 972// Method: AppleUSBCDCDMM::getFunctionalDescriptors 973// 974// Inputs: 975// 976// Outputs: return - true (descriptors ok), false (somethings not right or not supported) 977// 978// Desc: Finds all the functional descriptors for the specific interface 979// 980/****************************************************************************************************/ 981 982bool AppleUSBCDCDMM::getFunctionalDescriptors() 983{ 984 bool gotDescriptors = false; 985 UInt16 vers; 986 UInt16 *hdrVers; 987 const FunctionalDescriptorHeader *funcDesc = NULL; 988 HDRFunctionalDescriptor *HDRFDesc; // hearder functional descriptor 989 DMMFunctionalDescriptor *DMMFDesc; // device management functional descriptor 990 991 XTRACE(this, 0, 0, "getFunctionalDescriptors"); 992 993 // Get the associated functional descriptors 994 995 do 996 { 997 funcDesc = (const FunctionalDescriptorHeader *)fInterface->FindNextAssociatedDescriptor((void*)funcDesc, CS_INTERFACE); 998 if (!funcDesc) 999 { 1000 gotDescriptors = true; // We're done 1001 } else { 1002 switch (funcDesc->bDescriptorSubtype) 1003 { 1004 case Header_FunctionalDescriptor: 1005 HDRFDesc = (HDRFunctionalDescriptor *)funcDesc; 1006 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Header Functional Descriptor"); 1007 hdrVers = (UInt16 *)&HDRFDesc->bcdCDC1; 1008 vers = USBToHostWord(*hdrVers); 1009 if (vers > kUSBRel11) 1010 { 1011 XTRACE(this, vers, kUSBRel11, "getFunctionalDescriptors - Header descriptor version number is incorrect"); 1012 } 1013 break; 1014 case DMM_FunctionalDescriptor: 1015 DMMFDesc = (DMMFunctionalDescriptor *)funcDesc; 1016 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - ACM Functional Descriptor"); 1017 fMax_Command = USBToHostWord(DMMFDesc->wMaxCommand); 1018 break; 1019 case Union_FunctionalDescriptor: 1020 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Union Functional Descriptor"); 1021 break; 1022 case CS_FunctionalDescriptor: 1023 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - CS Functional Descriptor"); 1024 break; 1025 default: 1026 XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - unknown Functional Descriptor"); 1027 break; 1028 } 1029 } 1030 } while (!gotDescriptors); 1031 1032 return true; 1033 1034}/* end getFunctionalDescriptors */ 1035 1036/****************************************************************************************************/ 1037// 1038// Method: AppleUSBCDCDMM::createSuffix 1039// 1040// Inputs: 1041// 1042// Outputs: return Code - true (suffix created), false (suffix not create) 1043// sufKey - the key 1044// 1045// Desc: Creates the suffix key. It attempts to use the serial number string from the device 1046// if it's reasonable i.e. less than 8 bytes ascii. Remember it's stored in unicode 1047// format. If it's not present or not reasonable it will generate the suffix based 1048// on the location property tag. At least this remains the same across boots if the 1049// device is plugged into the same physical location. In the latter case trailing 1050// zeros are removed. 1051// The interface number is also added to make it unique for 1052// multiple CDC configuration devices. 1053// 1054/****************************************************************************************************/ 1055 1056bool AppleUSBCDCDMM::createSuffix(unsigned char *sufKey) 1057{ 1058 1059 IOReturn rc; 1060 UInt8 serBuf[12]; // arbitrary size > 8 1061 OSNumber *location; 1062 UInt32 locVal; 1063 SInt16 i, sig = 0; 1064 UInt8 indx; 1065 bool keyOK = false; 1066 1067 XTRACE(this, 0, 0, "createSuffix"); 1068 1069 indx = fInterface->GetDevice()->GetSerialNumberStringIndex(); 1070 if (indx != 0) 1071 { 1072 // Generate suffix key based on the serial number string (if reasonable <= 8 and > 0) 1073 1074 rc = fInterface->GetDevice()->GetStringDescriptor(indx, (char *)&serBuf, sizeof(serBuf)); 1075 if (!rc) 1076 { 1077 if ((strlen((char *)&serBuf) < 9) && (strlen((char *)&serBuf) > 0)) 1078 { 1079 strlcpy((char *)sufKey, (const char *)&serBuf, strlen((char *)&serBuf)); 1080// strcpy((char *)sufKey, (const char *)&serBuf); 1081 sig = strlen((char *)sufKey); 1082 keyOK = true; 1083 } 1084 } else { 1085 XTRACE(this, 0, rc, "createSuffix error reading serial number string"); 1086 } 1087 } 1088 1089 if (!keyOK) 1090 { 1091 // Generate suffix key based on the location property tag 1092 1093 location = (OSNumber *)fInterface->GetDevice()->getProperty(kUSBDevicePropertyLocationID); 1094 if (location) 1095 { 1096 locVal = location->unsigned32BitValue(); 1097 snprintf((char *)sufKey, (sizeof(locVal)*2)+1, "%x", (unsigned int)locVal); 1098 sig = strlen((const char *)sufKey)-1; 1099 for (i=sig; i>=0; i--) 1100 { 1101 if (sufKey[i] != '0') 1102 { 1103 break; 1104 } 1105 } 1106 sig = i + 1; 1107 keyOK = true; 1108 } 1109 } 1110 1111 // Make it unique just in case there's more than one configuration on this device 1112 1113 if (keyOK) 1114 { 1115 sufKey[sig] = Asciify((UInt8)fInterfaceNumber >> 4); 1116 if (sufKey[sig] != '0') 1117 sig++; 1118 sufKey[sig++] = Asciify((UInt8)fInterfaceNumber); 1119 sufKey[sig] = 0x00; 1120 } 1121 1122 return keyOK; 1123 1124}/* end createSuffix */ 1125 1126/****************************************************************************************************/ 1127// 1128// Method: AppleUSBCDCDMM::createSerialStream 1129// 1130// Inputs: 1131// 1132// Outputs: return Code - true (created and initialilzed ok), false (it failed) 1133// 1134// Desc: Creates and initializes the nub 1135// 1136/****************************************************************************************************/ 1137 1138bool AppleUSBCDCDMM::createSerialStream() 1139{ 1140 IOModemSerialStreamSync *pNub = new IOModemSerialStreamSync; 1141 bool ret; 1142 unsigned char rname[20]; 1143 const char *suffix = (const char *)&rname; 1144 1145 XTRACEP(this, 0, pNub, "createSerialStream"); 1146 if (!pNub) 1147 { 1148 return false; 1149 } 1150 1151 // Either we attached and should get rid of our reference 1152 // or we failed in which case we should get rid our reference as well. 1153 // This just makes sure the reference count is correct. 1154 1155 ret = (pNub->init(0, 0) && pNub->attach(this)); 1156 1157 pNub->release(); 1158 if (!ret) 1159 { 1160 XTRACE(this, ret, 0, "createSerialStream - Failed to attach to the nub"); 1161 return false; 1162 } 1163 1164 // Report the base name to be used for generating device nodes 1165 1166 pNub->setProperty(kIOTTYBaseNameKey, baseName); 1167 1168 // Create suffix key and set it 1169 1170 if (createSuffix((unsigned char *)suffix)) 1171 { 1172 pNub->setProperty(kIOTTYSuffixKey, suffix); 1173 } 1174 1175 pNub->setProperty((const char *)hiddenTag, true); 1176 1177 pNub->registerService(); 1178 1179 return true; 1180 1181}/* end createSerialStream */ 1182 1183/****************************************************************************************************/ 1184// 1185// Method: AppleUSBCDCDMM::acquirePort 1186// 1187// Inputs: sleep - true (wait for it), false (don't) 1188// refCon - unused 1189// 1190// Outputs: Return Code - kIOReturnSuccess, kIOReturnExclusiveAccess, kIOReturnIOError and various others 1191// 1192// Desc: Set up for gated acquirePort call. 1193// 1194/****************************************************************************************************/ 1195 1196IOReturn AppleUSBCDCDMM::acquirePort(bool sleep, void *refCon) 1197{ 1198 IOReturn ret; 1199 1200 XTRACEP(this, refCon, 0, "acquirePort"); 1201 1202 // Check for being acquired after stop has been issued and before start 1203 1204 if (fTerminate || fStopping) 1205 { 1206 XTRACE(this, 0, 0, "acquirePort - Offline"); 1207 return kIOReturnOffline; 1208 } 1209 1210 // Make sure we have a valid workloop 1211 1212 if (!fWorkLoop) 1213 { 1214 XTRACE(this, 0, 0, "acquirePort - No workLoop"); 1215 return kIOReturnOffline; 1216 } 1217 1218 retain(); 1219 ret = fCommandGate->runAction(acquirePortAction, (void *)sleep); 1220 release(); 1221 1222 return ret; 1223 1224}/* end acquirePort */ 1225 1226/****************************************************************************************************/ 1227// 1228// Method: AppleUSBCDCDMM::acquirePortAction 1229// 1230// Desc: Dummy pass through for acquirePortGated. 1231// 1232/****************************************************************************************************/ 1233 1234IOReturn AppleUSBCDCDMM::acquirePortAction(OSObject *owner, void *arg0, void *, void *, void *) 1235{ 1236 1237 return ((AppleUSBCDCDMM *)owner)->acquirePortGated((bool)arg0); 1238 1239}/* end acquirePortAction */ 1240 1241/****************************************************************************************************/ 1242// 1243// Method: AppleUSBCDCDMM::acquirePortGated 1244// 1245// Inputs: sleep - true (wait for it), false (don't) 1246// 1247// Outputs: Return Code - kIOReturnSuccess, kIOReturnExclusiveAccess, kIOReturnIOError and various others 1248// 1249// Desc: acquirePort tests and sets the state of the port object. If the port was 1250// available, then the state is set to busy, and kIOReturnSuccess is returned. 1251// If the port was already busy and sleep is YES, then the thread will sleep 1252// until the port is freed, then re-attempts the acquire. If the port was 1253// already busy and sleep is NO, then kIOReturnExclusiveAccess is returned. 1254// 1255/****************************************************************************************************/ 1256 1257IOReturn AppleUSBCDCDMM::acquirePortGated(bool sleep) 1258{ 1259 UInt32 busyState = 0; 1260 UInt32 state; 1261 UInt32 mask; 1262 IOReturn rtn = kIOReturnSuccess; 1263 1264 XTRACE(this, 0, sleep, "acquirePortGated"); 1265 1266 retain(); // Hold reference till releasePortGated, unless we fail to acquire 1267 while (true) 1268 { 1269 busyState = fPort.State & PD_S_ACQUIRED; 1270 if (!busyState) 1271 { 1272 // Set busy bit (acquired), and clear everything else 1273 1274 state = PD_S_ACQUIRED | DEFAULT_STATE; 1275 mask = STATE_ALL; 1276 setStateGated(&state, &mask); 1277 break; 1278 } else { 1279 if (!sleep) 1280 { 1281 XTRACE(this, 0, 0, "acquirePortGated - Busy exclusive access"); 1282 release(); 1283 return kIOReturnExclusiveAccess; 1284 } else { 1285 busyState = 0; 1286 mask = PD_S_ACQUIRED; 1287 rtn = watchStateGated(&busyState, &mask); 1288 if ((rtn == kIOReturnIOError) || (rtn == kIOReturnSuccess)) 1289 { 1290 continue; 1291 } else { 1292 XTRACE(this, 0, 0, "acquirePortGated - Interrupted!"); 1293 release(); 1294 return rtn; 1295 } 1296 } 1297 } 1298 } 1299 1300 setStructureDefaults(); // Set the default values 1301 1302 fSessions++; // Bump number of active sessions and turn on clear to send 1303 state = PD_RS232_S_CTS; 1304 mask = PD_RS232_S_CTS; 1305 setStateGated(&state, &mask); 1306 1307 return kIOReturnSuccess; 1308 1309}/* end acquirePortGated */ 1310 1311/****************************************************************************************************/ 1312// 1313// Method: AppleUSBCDCDMM::releasePort 1314// 1315// Inputs: refCon - unused 1316// 1317// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 1318// 1319// Desc: Set up for gated releasePort call. 1320// 1321/****************************************************************************************************/ 1322 1323IOReturn AppleUSBCDCDMM::releasePort(void *refCon) 1324{ 1325 IOReturn ret = kIOReturnSuccess; 1326 1327 XTRACE(this, 0, 0, "releasePort"); 1328 1329 retain(); 1330 ret = fCommandGate->runAction(releasePortAction); 1331 release(); 1332 1333 // Clear any sleeping threads 1334 1335 fPort.WatchStateMask = 0; 1336 fCommandGate->commandWakeup((void *)&fPort.State); 1337 1338 return ret; 1339 1340}/* end releasePort */ 1341 1342/****************************************************************************************************/ 1343// 1344// Method: AppleUSBCDCDMM::releasePortAction 1345// 1346// Desc: Dummy pass through for releasePortGated. 1347// 1348/****************************************************************************************************/ 1349 1350IOReturn AppleUSBCDCDMM::releasePortAction(OSObject *owner, void *, void *, void *, void *) 1351{ 1352 1353 return ((AppleUSBCDCDMM *)owner)->releasePortGated(); 1354 1355}/* end releasePortAction */ 1356 1357/****************************************************************************************************/ 1358// 1359// Method: AppleUSBCDCDMM::releasePortGated 1360// 1361// Inputs: 1362// 1363// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 1364// 1365// Desc: releasePort returns all the resources and does clean up. 1366// 1367/****************************************************************************************************/ 1368 1369IOReturn AppleUSBCDCDMM::releasePortGated() 1370{ 1371 UInt32 busyState; 1372 UInt32 state; 1373 UInt32 mask; 1374 1375 XTRACE(this, 0, 0, "releasePortGated"); 1376 1377 busyState = (fPort.State & PD_S_ACQUIRED); 1378 if (!busyState) 1379 { 1380 if (fTerminate || fStopping) 1381 { 1382 XTRACE(this, 0, 0, "releasePortGated - Offline"); 1383 return kIOReturnOffline; 1384 } 1385 1386 XTRACE(this, 0, 0, "releasePortGated - Not open"); 1387 return kIOReturnNotOpen; 1388 } 1389 1390 if (!fTerminate) 1391 setControlLineState(false, false); // clear RTS and clear DTR only if not terminated 1392 1393 state = 0; 1394 mask = STATE_ALL; 1395 setStateGated(&state, &mask); // Clear the entire state word - which also deactivates the port 1396 1397 fSessions--; // reduce number of active sessions 1398 1399 release(); // Dispose of the self-reference we took in acquirePortGated() 1400 1401 XTRACE(this, 0, 0, "releasePort - Exit"); 1402 1403 return kIOReturnSuccess; 1404 1405}/* end releasePortGated */ 1406 1407/****************************************************************************************************/ 1408// 1409// Method: AppleUSBCDCDMM::getState 1410// 1411// Inputs: refCon - unused 1412// 1413// Outputs: Return value - port state 1414// 1415// Desc: Set up for gated getState call. 1416// 1417/****************************************************************************************************/ 1418 1419UInt32 AppleUSBCDCDMM::getState(void *refCon) 1420{ 1421 UInt32 currState; 1422 1423 XTRACE(this, 0, 0, "getState"); 1424 1425 if (fTerminate || fStopping) 1426 { 1427 XTRACE(this, 0, kIOReturnOffline, "getState - Offline"); 1428 return 0; 1429 } 1430 1431 retain(); 1432 currState = fCommandGate->runAction(getStateAction); 1433 release(); 1434 1435 return currState; 1436 1437}/* end getState */ 1438 1439/****************************************************************************************************/ 1440// 1441// Method: AppleUSBCDCDMM::getStateAction 1442// 1443// Desc: Dummy pass through for getStateGated. 1444// 1445/****************************************************************************************************/ 1446 1447IOReturn AppleUSBCDCDMM::getStateAction(OSObject *owner, void *, void *, void *, void *) 1448{ 1449 UInt32 newState; 1450 1451 newState = ((AppleUSBCDCDMM *)owner)->getStateGated(); 1452 1453 return newState; 1454 1455}/* end getStateAction */ 1456 1457/****************************************************************************************************/ 1458// 1459// Method: AppleUSBCDCDMM::getStateGated 1460// 1461// Inputs: port - unused 1462// 1463// Outputs: return value - port state 1464// 1465// Desc: Get the state for the port. 1466// 1467/****************************************************************************************************/ 1468 1469UInt32 AppleUSBCDCDMM::getStateGated() 1470{ 1471 UInt32 state; 1472 1473 XTRACE(this, 0, 0, "getStateGated"); 1474 1475 if (fTerminate || fStopping) 1476 return 0; 1477 1478 CheckQueues(); 1479 1480 state = fPort.State & EXTERNAL_MASK; 1481 1482 XTRACE(this, state, EXTERNAL_MASK, "getStateGated - Exit"); 1483 1484 return state; 1485 1486}/* end getStateGated */ 1487 1488/****************************************************************************************************/ 1489// 1490// Method: AppleUSBCDCDMM::setState 1491// 1492// Inputs: state - the state 1493// mask - the mask 1494// refCon - unused 1495// 1496// Outputs: Return code - kIOReturnSuccess or kIOReturnBadArgument 1497// 1498// Desc: Set up for gated setState call. 1499// 1500/****************************************************************************************************/ 1501 1502IOReturn AppleUSBCDCDMM::setState(UInt32 state, UInt32 mask, void *refCon) 1503{ 1504 IOReturn ret = kIOReturnSuccess; 1505 1506 XTRACE(this, 0, 0, "setState"); 1507 1508 if (fTerminate || fStopping) 1509 { 1510 XTRACE(this, 0, kIOReturnOffline, "setState - Offline"); 1511 return 0; 1512 } 1513 1514 // Cannot acquire or activate via setState 1515 1516 if (mask & (PD_S_ACQUIRED | PD_S_ACTIVE | (~EXTERNAL_MASK))) 1517 { 1518 ret = kIOReturnBadArgument; 1519 } else { 1520 1521 // ignore any bits that are read-only 1522 1523 mask &= (~fPort.FlowControl & PD_RS232_A_MASK) | PD_S_MASK; 1524 if (mask) 1525 { 1526 retain(); 1527 ret = fCommandGate->runAction(setStateAction, (void *)&state, (void *)&mask); 1528 release(); 1529 } 1530 } 1531 1532 return ret; 1533 1534}/* end setState */ 1535 1536/****************************************************************************************************/ 1537// 1538// Method: AppleUSBCDCDMM::setStateAction 1539// 1540// Desc: Dummy pass through for setStateGated. 1541// 1542/****************************************************************************************************/ 1543 1544IOReturn AppleUSBCDCDMM::setStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *) 1545{ 1546 1547 return ((AppleUSBCDCDMM *)owner)->setStateGated((UInt32 *)arg0, (UInt32 *)arg1); 1548 1549}/* end setStateAction */ 1550 1551/****************************************************************************************************/ 1552// 1553// Method: AppleUSBCDCDMM::setStateGated 1554// 1555// Inputs: state - state to set 1556// mask - state mask 1557// 1558// Outputs: Return Code - kIOReturnSuccess or kIOReturnBadArgument 1559// 1560// Desc: Set the state for the port device. The lower 16 bits are used to set the 1561// state of various flow control bits (this can also be done by enqueueing a 1562// PD_E_FLOW_CONTROL event). If any of the flow control bits have been set 1563// for automatic control, then they can't be changed by setState. For flow 1564// control bits set to manual (that are implemented in hardware), the lines 1565// will be changed before this method returns. The one weird case is if RXO 1566// is set for manual, then an XON or XOFF character may be placed at the end 1567// of the TXQ and transmitted later. 1568// 1569/****************************************************************************************************/ 1570 1571IOReturn AppleUSBCDCDMM::setStateGated(UInt32 *pState, UInt32 *pMask) 1572{ 1573 UInt32 state = *pMask; 1574 UInt32 mask = *pMask; 1575 UInt32 delta; 1576 1577 XTRACE(this, state, mask, "setStateGated"); 1578 1579 if (fStopping) 1580 return kIOReturnOffline; 1581 1582 // Check if it's being acquired or already acquired 1583 1584 if ((state & PD_S_ACQUIRED) || (fPort.State & PD_S_ACQUIRED)) 1585 { 1586 if (mask & PD_RS232_S_DTR) 1587 { 1588 if ((state & PD_RS232_S_DTR) != (fPort.State & PD_RS232_S_DTR)) 1589 { 1590 if (state & PD_RS232_S_DTR) 1591 { 1592 XTRACE(this, 0, 0, "setState - DTR TRUE"); 1593 setControlLineState(false, true); 1594 } else { 1595 if (!fTerminate) 1596 { 1597 XTRACE(this, 0, 0, "setState - DTR FALSE"); 1598 setControlLineState(false, false); 1599 } 1600 } 1601 } 1602 } 1603 1604 state = (fPort.State & ~mask) | (state & mask); // compute the new state 1605 delta = state ^ fPort.State; // keep a copy of the diffs 1606 fPort.State = state; 1607 1608 // Wake up all threads asleep on WatchStateMask 1609 1610 if (delta & fPort.WatchStateMask) 1611 { 1612 fCommandGate->commandWakeup((void *)&fPort.State); 1613 } 1614 1615 return kIOReturnSuccess; 1616 1617 } else { 1618 XTRACE(this, fPort.State, 0, "setStateGated - Not Acquired"); 1619 } 1620 1621 return kIOReturnNotOpen; 1622 1623}/* end setStateGated */ 1624 1625/****************************************************************************************************/ 1626// 1627// Method: AppleUSBCDCDMM::watchState 1628// 1629// Inputs: state - state to watch for 1630// mask - state mask bits 1631// refCon - unused 1632// 1633// Outputs: Return Code - kIOReturnSuccess or value returned from ::watchState 1634// 1635// Desc: Set up for gated watchState call. 1636// 1637/****************************************************************************************************/ 1638 1639IOReturn AppleUSBCDCDMM::watchState(UInt32 *state, UInt32 mask, void *refCon) 1640{ 1641 IOReturn ret; 1642 1643 XTRACE(this, *state, mask, "watchState"); 1644 1645 if (fTerminate || fStopping) 1646 { 1647 XTRACE(this, 0, kIOReturnOffline, "watchState - Offline"); 1648 return kIOReturnOffline; 1649 } 1650 1651 if (!state) 1652 return kIOReturnBadArgument; 1653 1654 if (!mask) 1655 return kIOReturnSuccess; 1656 1657 retain(); 1658 ret = fCommandGate->runAction(watchStateAction, (void *)state, (void *)&mask); 1659 release(); 1660 1661 return ret; 1662 1663}/* end watchState */ 1664 1665/****************************************************************************************************/ 1666// 1667// Method: AppleUSBCDCDMM::watchStateAction 1668// 1669// Desc: Dummy pass through for watchStateGated. 1670// 1671/****************************************************************************************************/ 1672 1673IOReturn AppleUSBCDCDMM::watchStateAction(OSObject *owner, void *arg0, void *arg1, void *, void *) 1674{ 1675 1676 return ((AppleUSBCDCDMM *)owner)->watchStateGated((UInt32 *)arg0, (UInt32 *)arg1); 1677 1678}/* end watchStateAction */ 1679 1680/****************************************************************************************************/ 1681// 1682// Method: AppleUSBCDCDMM::watchStateGated 1683// 1684// Inputs: state - state to watch for 1685// mask - state mask bits 1686// 1687// Outputs: Return Code - kIOReturnSuccess or value returned from privateWatchState 1688// 1689// Desc: Wait for the at least one of the state bits defined in mask to be equal 1690// to the value defined in state. Check on entry then sleep until necessary, 1691// A return value of kIOReturnSuccess means that at least one of the port state 1692// bits specified by mask is equal to the value passed in by state. A return 1693// value of kIOReturnIOError indicates that the port went inactive. A return 1694// value of kIOReturnIPCError indicates sleep was interrupted by a signal. 1695// 1696/****************************************************************************************************/ 1697 1698IOReturn AppleUSBCDCDMM::watchStateGated(UInt32 *state, UInt32 *pMask) 1699{ 1700 UInt32 mask = *pMask; 1701 unsigned watchState, foundStates; 1702 bool autoActiveBit = false; 1703 IOReturn ret = kIOReturnNotOpen; 1704 1705 XTRACE(this, *state, mask, "watchStateGated"); 1706 1707 if (fTerminate || fStopping) 1708 return kIOReturnOffline; 1709 1710 if (fPort.State & PD_S_ACQUIRED) 1711 { 1712 ret = kIOReturnSuccess; 1713 mask &= EXTERNAL_MASK; 1714 1715 watchState = *state; 1716 if (!(mask & (PD_S_ACQUIRED | PD_S_ACTIVE))) 1717 { 1718 watchState &= ~PD_S_ACTIVE; // Check for low PD_S_ACTIVE 1719 mask |= PD_S_ACTIVE; // Register interest in PD_S_ACTIVE bit 1720 autoActiveBit = true; 1721 } 1722 1723 while (true) 1724 { 1725 // Check port state for any interesting bits with watchState value 1726 // NB. the '^ ~' is a XNOR and tests for equality of bits. 1727 1728 foundStates = (watchState ^ ~fPort.State) & mask; 1729 1730 if (foundStates) 1731 { 1732 *state = fPort.State; 1733 if (autoActiveBit && (foundStates & PD_S_ACTIVE)) 1734 { 1735 ret = kIOReturnIOError; 1736 } else { 1737 ret = kIOReturnSuccess; 1738 } 1739 break; 1740 } 1741 1742 // Everytime we go around the loop we have to reset the watch mask. 1743 // This means any event that could affect the WatchStateMask must 1744 // wakeup all watch state threads. The two events are an interrupt 1745 // or one of the bits in the WatchStateMask changing. 1746 1747 fPort.WatchStateMask |= mask; 1748 1749 XTRACE(this, fPort.State, fPort.WatchStateMask, "watchStateGated - Thread sleeping"); 1750 1751 retain(); // Just to make sure all threads are awake 1752 fCommandGate->retain(); // before we're released 1753 1754 ret = fCommandGate->commandSleep((void *)&fPort.State); 1755 1756 fCommandGate->release(); 1757 1758 XTRACE(this, fPort.State, ret, "watchStateGated - Thread restart"); 1759 1760 if (ret == THREAD_TIMED_OUT) 1761 { 1762 ret = kIOReturnTimeout; 1763 release(); 1764 break; 1765 } else { 1766 if (ret == THREAD_INTERRUPTED) 1767 { 1768 ret = kIOReturnAborted; 1769 release(); 1770 break; 1771 } else { 1772 if (fTerminate || fStopping) // Make sure we not terminated or stopping 1773 { 1774 ret = kIOReturnOffline; 1775 release(); 1776 break; 1777 } 1778 } 1779 } 1780 release(); 1781 } 1782 1783 // As it is impossible to undo the masking used by this 1784 // thread, we clear down the watch state mask and wakeup 1785 // every sleeping thread to reinitialize the mask before exiting. 1786 1787 fPort.WatchStateMask = 0; 1788 XTRACE(this, *state, 0, "watchStateGated - Thread wakeing others"); 1789 fCommandGate->commandWakeup((void *)&fPort.State); 1790 1791 *state &= EXTERNAL_MASK; 1792 } 1793 1794 XTRACE(this, ret, 0, "watchStateGated - Exit"); 1795 1796 return ret; 1797 1798}/* end watchStateGated */ 1799 1800/****************************************************************************************************/ 1801// 1802// Method: AppleUSBCDCDMM::nextEvent 1803// 1804// Inputs: refCon - unused 1805// 1806// Outputs: Return Code - kIOReturnSuccess or kIOReturnOffline 1807// 1808// Desc: Not used by this driver. 1809// 1810/****************************************************************************************************/ 1811 1812UInt32 AppleUSBCDCDMM::nextEvent(void *refCon) 1813{ 1814 1815 XTRACE(this, 0, 0, "nextEvent"); 1816 1817 if (fTerminate || fStopping) 1818 return kIOReturnOffline; 1819 1820 if (getState(&fPort) & PD_S_ACTIVE) 1821 { 1822 return kIOReturnSuccess; 1823 } 1824 1825 return kIOReturnNotOpen; 1826 1827}/* end nextEvent */ 1828 1829/****************************************************************************************************/ 1830// 1831// Method: AppleUSBCDCDMM::executeEvent 1832// 1833// Inputs: event - The event 1834// data - any data associated with the event 1835// refCon - unused 1836// 1837// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen or kIOReturnBadArgument 1838// 1839// Desc: Set up for gated executeEvent call. 1840// 1841/****************************************************************************************************/ 1842 1843IOReturn AppleUSBCDCDMM::executeEvent(UInt32 event, UInt32 data, void *refCon) 1844{ 1845 IOReturn ret; 1846 1847 XTRACE(this, data, event, "executeEvent"); 1848 1849 if (fTerminate || fStopping) 1850 { 1851 XTRACE(this, 0, kIOReturnOffline, "executeEvent - Offline"); 1852 return kIOReturnOffline; 1853 } 1854 1855 retain(); 1856 ret = fCommandGate->runAction(executeEventAction, (void *)&event, (void *)&data); 1857 release(); 1858 1859 return ret; 1860 1861}/* end executeEvent */ 1862 1863/****************************************************************************************************/ 1864// 1865// Method: AppleUSBCDCDMM::executeEventAction 1866// 1867// Desc: Dummy pass through for executeEventGated. 1868// 1869/****************************************************************************************************/ 1870 1871IOReturn AppleUSBCDCDMM::executeEventAction(OSObject *owner, void *arg0, void *arg1, void *, void *) 1872{ 1873 1874 return ((AppleUSBCDCDMM *)owner)->executeEventGated((UInt32 *)arg0, (UInt32 *)arg1); 1875 1876}/* end executeEventAction */ 1877 1878/****************************************************************************************************/ 1879// 1880// Method: AppleUSBCDCDMM::executeEventGated 1881// 1882// Inputs: event - The event 1883// data - any data associated with the event 1884// 1885// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen or kIOReturnBadArgument 1886// 1887// Desc: executeEvent causes the specified event to be processed immediately. 1888// This is primarily used for channel control commands like START & STOP 1889// 1890/****************************************************************************************************/ 1891 1892IOReturn AppleUSBCDCDMM::executeEventGated(UInt32 *pEvent, UInt32 *pData) 1893{ 1894 UInt32 event = *pEvent; 1895 UInt32 data = *pData; 1896 IOReturn ret = kIOReturnSuccess; 1897 UInt32 state, delta; 1898 UInt32 mask; 1899 1900 if (fTerminate || fStopping) 1901 return kIOReturnOffline; 1902 1903 delta = 0; 1904 state = fPort.State; 1905 XTRACE(this, state, event, "executeEventGated"); 1906 1907 if ((state & PD_S_ACQUIRED) == 0) 1908 return kIOReturnNotOpen; 1909 1910 switch (event) 1911 { 1912 case PD_RS232_E_XON_BYTE: 1913 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_XON_BYTE"); 1914 fPort.XONchar = data; 1915 break; 1916 case PD_RS232_E_XOFF_BYTE: 1917 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_XOFF_BYTE"); 1918 fPort.XOFFchar = data; 1919 break; 1920 case PD_E_SPECIAL_BYTE: 1921 XTRACE(this, data, event, "executeEventGated - PD_E_SPECIAL_BYTE"); 1922 fPort.SWspecial[ data >> SPECIAL_SHIFT ] |= (1 << (data & SPECIAL_MASK)); 1923 break; 1924 case PD_E_VALID_DATA_BYTE: 1925 XTRACE(this, data, event, "executeEventGated - PD_E_VALID_DATA_BYTE"); 1926 fPort.SWspecial[ data >> SPECIAL_SHIFT ] &= ~(1 << (data & SPECIAL_MASK)); 1927 break; 1928 case PD_E_FLOW_CONTROL: 1929 XTRACE(this, data, event, "executeEventGated - PD_E_FLOW_CONTROL"); 1930 break; 1931 case PD_E_ACTIVE: 1932 XTRACE(this, data, event, "executeEventGated - PD_E_ACTIVE"); 1933 if ((bool)data) 1934 { 1935 if (!(state & PD_S_ACTIVE)) 1936 { 1937 setStructureDefaults(); 1938 state = PD_S_ACTIVE; 1939 mask = PD_S_ACTIVE; 1940 setStateGated(&state, &mask); // activate port 1941 1942 setControlLineState(true, true); // set RTS and set DTR 1943 } 1944 } else { 1945 if ((state & PD_S_ACTIVE)) 1946 { 1947 state = 0; 1948 mask = PD_S_ACTIVE; 1949 setStateGated(&state, &mask); // deactivate port 1950 1951 setControlLineState(false, false); // clear RTS and clear DTR 1952 } 1953 } 1954 break; 1955 case PD_E_DATA_LATENCY: 1956 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_LATENCY"); 1957 fPort.DataLatInterval = long2tval(data * 1000); 1958 break; 1959 case PD_RS232_E_MIN_LATENCY: 1960 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_MIN_LATENCY"); 1961 fPort.MinLatency = bool(data); 1962 break; 1963 case PD_E_DATA_INTEGRITY: 1964 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_INTEGRITY"); 1965 if ((data < PD_RS232_PARITY_NONE) || (data > PD_RS232_PARITY_SPACE)) 1966 { 1967 ret = kIOReturnBadArgument; 1968 } else { 1969 fPort.TX_Parity = data; 1970 fPort.RX_Parity = PD_RS232_PARITY_DEFAULT; 1971 1972 setLineCoding(); 1973 } 1974 break; 1975 case PD_E_DATA_RATE: 1976 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_RATE"); 1977 1978 // For API compatiblilty with Intel. 1979 1980 data >>= 1; 1981 XTRACE(this, data, 0, "executeEventGated - actual data rate"); 1982 if ((data < MIN_BAUD) || (data > kMaxBaudRate)) 1983 { 1984 ret = kIOReturnBadArgument; 1985 } else { 1986 fPort.BaudRate = data; 1987 1988 setLineCoding(); 1989 } 1990 break; 1991 case PD_E_DATA_SIZE: 1992 XTRACE(this, data, event, "executeEventGated - PD_E_DATA_SIZE"); 1993 1994 // For API compatiblilty with Intel. 1995 1996 data >>= 1; 1997 XTRACE(this, data, 0, "executeEventGated - actual data size"); 1998 if ((data < 5) || (data > 8)) 1999 { 2000 ret = kIOReturnBadArgument; 2001 } else { 2002 fPort.CharLength = data; 2003 2004 setLineCoding(); 2005 } 2006 break; 2007 case PD_RS232_E_STOP_BITS: 2008 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_STOP_BITS"); 2009 if ((data < 0) || (data > 20)) 2010 { 2011 ret = kIOReturnBadArgument; 2012 } else { 2013 fPort.StopBits = data; 2014 2015 setLineCoding(); 2016 } 2017 break; 2018 case PD_E_RXQ_FLUSH: 2019 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_FLUSH"); 2020 break; 2021 case PD_E_RX_DATA_INTEGRITY: 2022 XTRACE(this, data, event, "executeEventGated - PD_E_RX_DATA_INTEGRITY"); 2023 if ((data != PD_RS232_PARITY_DEFAULT) && (data != PD_RS232_PARITY_ANY)) 2024 { 2025 ret = kIOReturnBadArgument; 2026 } else { 2027 fPort.RX_Parity = data; 2028 } 2029 break; 2030 case PD_E_RX_DATA_RATE: 2031 XTRACE(this, data, event, "executeEventGated - PD_E_RX_DATA_RATE"); 2032 if (data) 2033 { 2034 ret = kIOReturnBadArgument; 2035 } 2036 break; 2037 case PD_E_RX_DATA_SIZE: 2038 XTRACE(this, data, event, "executeEventGated - PD_E_RX_DATA_SIZE"); 2039 if (data) 2040 { 2041 ret = kIOReturnBadArgument; 2042 } 2043 break; 2044 case PD_RS232_E_RX_STOP_BITS: 2045 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_RX_STOP_BITS"); 2046 if (data) 2047 { 2048 ret = kIOReturnBadArgument; 2049 } 2050 break; 2051 case PD_E_TXQ_FLUSH: 2052 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_FLUSH"); 2053 break; 2054 case PD_RS232_E_LINE_BREAK: 2055 XTRACE(this, data, event, "executeEventGated - PD_RS232_E_LINE_BREAK"); 2056 state &= ~PD_RS232_S_BRK; 2057 delta |= PD_RS232_S_BRK; 2058 setStateGated(&state, &delta); 2059 break; 2060 case PD_E_DELAY: 2061 XTRACE(this, data, event, "executeEventGated - PD_E_DELAY"); 2062 fPort.CharLatInterval = long2tval(data * 1000); 2063 break; 2064 case PD_E_RXQ_SIZE: 2065 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_SIZE"); 2066 break; 2067 case PD_E_TXQ_SIZE: 2068 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_SIZE"); 2069 break; 2070 case PD_E_RXQ_HIGH_WATER: 2071 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_HIGH_WATER"); 2072 break; 2073 case PD_E_RXQ_LOW_WATER: 2074 XTRACE(this, data, event, "executeEventGated - PD_E_RXQ_LOW_WATER"); 2075 break; 2076 case PD_E_TXQ_HIGH_WATER: 2077 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_HIGH_WATER"); 2078 break; 2079 case PD_E_TXQ_LOW_WATER: 2080 XTRACE(this, data, event, "executeEventGated - PD_E_TXQ_LOW_WATER"); 2081 break; 2082 default: 2083 XTRACE(this, data, event, "executeEventGated - unrecognized event"); 2084 ret = kIOReturnBadArgument; 2085 break; 2086 } 2087 2088 return ret; 2089 2090}/* end executeEventGated */ 2091 2092/****************************************************************************************************/ 2093// 2094// Method: AppleUSBCDCDMM::requestEvent 2095// 2096// Inputs: event - The event 2097// refCon - unused 2098// 2099// Outputs: Return Code - kIOReturnSuccess, kIOReturnBadArgument 2100// data - any data associated with the event 2101// 2102// Desc: requestEvent processes the specified event as an immediate request and 2103// returns the results in data. This is primarily used for getting link 2104// status information and verifying baud rate etc. 2105// For the most part this can be done immediately without being gated. 2106// 2107/****************************************************************************************************/ 2108 2109IOReturn AppleUSBCDCDMM::requestEvent(UInt32 event, UInt32 *data, void *refCon) 2110{ 2111 IOReturn returnValue = kIOReturnSuccess; 2112 2113 XTRACE(this, 0, event, "requestEvent"); 2114 2115 if (fTerminate || fStopping) 2116 { 2117 XTRACE(this, 0, kIOReturnOffline, "requestEvent - Offline"); 2118 return kIOReturnOffline; 2119 } 2120 2121 if (data == NULL) 2122 { 2123 XTRACE(this, 0, event, "requestEvent - data is null"); 2124 returnValue = kIOReturnBadArgument; 2125 } else { 2126 switch (event) 2127 { 2128 case PD_E_ACTIVE: 2129 XTRACE(this, 0, event, "requestEvent - PD_E_ACTIVE"); 2130 *data = bool(getState(&fPort) & PD_S_ACTIVE); // Just to be safe put this through the gate 2131 break; 2132 case PD_E_FLOW_CONTROL: 2133 XTRACE(this, fPort.FlowControl, event, "requestEvent - PD_E_FLOW_CONTROL"); 2134 *data = fPort.FlowControl; 2135 break; 2136 case PD_E_DELAY: 2137 XTRACE(this, 0, event, "requestEvent - PD_E_DELAY"); 2138 *data = tval2long(fPort.CharLatInterval)/ 1000; 2139 break; 2140 case PD_E_DATA_LATENCY: 2141 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_LATENCY"); 2142 *data = tval2long(fPort.DataLatInterval)/ 1000; 2143 break; 2144 case PD_E_TXQ_SIZE: 2145 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_SIZE"); 2146 *data = GetQueueSize(&fPort.TX); 2147 break; 2148 case PD_E_RXQ_SIZE: 2149 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_SIZE"); 2150 *data = GetQueueSize(&fPort.RX); 2151 break; 2152 case PD_E_TXQ_LOW_WATER: 2153 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_LOW_WATER"); 2154 *data = 0; 2155 returnValue = kIOReturnBadArgument; 2156 break; 2157 case PD_E_RXQ_LOW_WATER: 2158 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_LOW_WATER"); 2159 *data = 0; 2160 returnValue = kIOReturnBadArgument; 2161 break; 2162 case PD_E_TXQ_HIGH_WATER: 2163 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_HIGH_WATER"); 2164 *data = 0; 2165 returnValue = kIOReturnBadArgument; 2166 break; 2167 case PD_E_RXQ_HIGH_WATER: 2168 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_HIGH_WATER"); 2169 *data = 0; 2170 returnValue = kIOReturnBadArgument; 2171 break; 2172 case PD_E_TXQ_AVAILABLE: 2173 XTRACE(this, 0, event, "requestEvent - PD_E_TXQ_AVAILABLE"); 2174 *data = FreeSpaceinQueue(&fPort.TX); 2175 break; 2176 case PD_E_RXQ_AVAILABLE: 2177 XTRACE(this, 0, event, "requestEvent - PD_E_RXQ_AVAILABLE"); 2178 *data = UsedSpaceinQueue(&fPort.RX); 2179 break; 2180 case PD_E_DATA_RATE: 2181 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_RATE"); 2182 *data = fPort.BaudRate << 1; 2183 break; 2184 case PD_E_RX_DATA_RATE: 2185 XTRACE(this, 0, event, "requestEvent - PD_E_RX_DATA_RATE"); 2186 *data = 0x00; 2187 break; 2188 case PD_E_DATA_SIZE: 2189 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_SIZE"); 2190 *data = fPort.CharLength << 1; 2191 break; 2192 case PD_E_RX_DATA_SIZE: 2193 XTRACE(this, 0, event, "requestEvent - PD_E_RX_DATA_SIZE"); 2194 *data = 0x00; 2195 break; 2196 case PD_E_DATA_INTEGRITY: 2197 XTRACE(this, 0, event, "requestEvent - PD_E_DATA_INTEGRITY"); 2198 *data = fPort.TX_Parity; 2199 break; 2200 case PD_E_RX_DATA_INTEGRITY: 2201 XTRACE(this, 0, event, "requestEvent - PD_E_RX_DATA_INTEGRITY"); 2202 *data = fPort.RX_Parity; 2203 break; 2204 case PD_RS232_E_STOP_BITS: 2205 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_STOP_BITS"); 2206 *data = fPort.StopBits << 1; 2207 break; 2208 case PD_RS232_E_RX_STOP_BITS: 2209 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_RX_STOP_BITS"); 2210 *data = 0x00; 2211 break; 2212 case PD_RS232_E_XON_BYTE: 2213 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_XON_BYTE"); 2214 *data = fPort.XONchar; 2215 break; 2216 case PD_RS232_E_XOFF_BYTE: 2217 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_XOFF_BYTE"); 2218 *data = fPort.XOFFchar; 2219 break; 2220 case PD_RS232_E_LINE_BREAK: 2221 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_LINE_BREAK"); 2222 *data = bool(getState(&fPort) & PD_RS232_S_BRK); // This should be gated too 2223 break; 2224 case PD_RS232_E_MIN_LATENCY: 2225 XTRACE(this, 0, event, "requestEvent - PD_RS232_E_MIN_LATENCY"); 2226 *data = bool(fPort.MinLatency); 2227 break; 2228 default: 2229 XTRACE(this, 0, event, "requestEvent - unrecognized event"); 2230 returnValue = kIOReturnBadArgument; 2231 break; 2232 } 2233 } 2234 2235 return kIOReturnSuccess; 2236 2237}/* end requestEvent */ 2238 2239/****************************************************************************************************/ 2240// 2241// Method: AppleUSBCDCDMM::enqueueEvent 2242// 2243// Inputs: event - The event 2244// data - any data associated with the event, 2245// sleep - true (wait for it), false (don't) 2246// refCon - unused 2247// 2248// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 2249// 2250// Desc: Not used by this driver. 2251// Events are passed on to executeEvent for immediate action. 2252// 2253/****************************************************************************************************/ 2254 2255IOReturn AppleUSBCDCDMM::enqueueEvent(UInt32 event, UInt32 data, bool sleep, void *refCon) 2256{ 2257 IOReturn ret; 2258 2259 XTRACE(this, data, event, "enqueueEvent"); 2260 2261 if (fTerminate || fStopping) 2262 { 2263 XTRACE(this, 0, kIOReturnOffline, "enqueueEvent - Offline"); 2264 return kIOReturnOffline; 2265 } 2266 2267 retain(); 2268 ret = fCommandGate->runAction(executeEventAction, (void *)&event, (void *)&data); 2269 release(); 2270 2271 return ret; 2272 2273}/* end enqueueEvent */ 2274 2275/****************************************************************************************************/ 2276// 2277// Method: AppleUSBCDCDMM::dequeueEvent 2278// 2279// Inputs: sleep - true (wait for it), false (don't) 2280// refCon - unused 2281// 2282// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen 2283// 2284// Desc: Not used by this driver. 2285// 2286/****************************************************************************************************/ 2287 2288IOReturn AppleUSBCDCDMM::dequeueEvent(UInt32 *event, UInt32 *data, bool sleep, void *refCon) 2289{ 2290 2291 XTRACE(this, 0, 0, "dequeueEvent"); 2292 2293 if (fTerminate || fStopping) 2294 { 2295 XTRACE(this, 0, kIOReturnOffline, "dequeueEvent - Offline"); 2296 return kIOReturnOffline; 2297 } 2298 2299 if ((event == NULL) || (data == NULL)) 2300 return kIOReturnBadArgument; 2301 2302 if (getState(&fPort) & PD_S_ACTIVE) 2303 { 2304 return kIOReturnSuccess; 2305 } 2306 2307 return kIOReturnNotOpen; 2308 2309}/* end dequeueEvent */ 2310 2311/****************************************************************************************************/ 2312// 2313// Method: AppleUSBCDCDMM::enqueueData 2314// 2315// Inputs: buffer - the data 2316// size - number of bytes 2317// sleep - true (wait for it), false (don't) 2318// refCon - unused 2319// 2320// Outputs: Return Code - kIOReturnSuccess, kIOReturnBadArgument or value returned from watchState 2321// count - bytes transferred 2322// 2323// Desc: set up for enqueueDataGated call. 2324// 2325/****************************************************************************************************/ 2326 2327IOReturn AppleUSBCDCDMM::enqueueData(UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep, void *refCon) 2328{ 2329 IOReturn ret; 2330 2331 XTRACE(this, size, sleep, "enqueueData"); 2332 2333 if (fTerminate || fStopping) 2334 { 2335 XTRACE(this, 0, kIOReturnOffline, "enqueueData - Offline"); 2336 return kIOReturnOffline; 2337 } 2338 2339 if (count == NULL || buffer == NULL) 2340 return kIOReturnBadArgument; 2341 2342 retain(); 2343 ret = fCommandGate->runAction(enqueueDataAction, (void *)buffer, (void *)&size, (void *)count, (void *)&sleep); 2344 release(); 2345 2346 return ret; 2347 2348}/* end enqueueData */ 2349 2350/****************************************************************************************************/ 2351// 2352// Method: AppleUSBCDCDMM::enqueueDatatAction 2353// 2354// Desc: Dummy pass through for enqueueDataGated. 2355// 2356/****************************************************************************************************/ 2357 2358IOReturn AppleUSBCDCDMM::enqueueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3) 2359{ 2360 2361 return ((AppleUSBCDCDMM *)owner)->enqueueDataGated((UInt8 *)arg0, (UInt32 *)arg1, (UInt32 *)arg2, (bool *)arg3); 2362 2363}/* end enqueueDataAction */ 2364 2365/****************************************************************************************************/ 2366// 2367// Method: AppleUSBCDCDMM::enqueueDataGated 2368// 2369// Inputs: buffer - the data 2370// size - number of bytes 2371// sleep - true (wait for it), false (don't) 2372// 2373// Outputs: Return Code - kIOReturnSuccess or value returned from watchState 2374// count - bytes transferred, 2375// 2376// Desc: enqueueData will attempt to copy data from the specified buffer to 2377// the TX queue as a sequence of VALID_DATA events. The argument 2378// bufferSize specifies the number of bytes to be sent. The actual 2379// number of bytes transferred is returned in count. 2380// If sleep is true, then this method will sleep until all bytes can be 2381// transferred. If sleep is false, then as many bytes as possible 2382// will be copied to the TX queue. 2383// Note that the caller should ALWAYS check the transferCount unless 2384// the return value was kIOReturnBadArgument, indicating one or more 2385// arguments were not valid. Other possible return values are 2386// kIOReturnSuccess if all requirements were met or kIOReturnOffline 2387// if the device was unplugged. 2388// 2389/****************************************************************************************************/ 2390 2391IOReturn AppleUSBCDCDMM::enqueueDataGated(UInt8 *buffer, UInt32 *pSize, UInt32 *count, bool *pSleep) 2392{ 2393 UInt32 size = *pSize; 2394 bool sleep = *pSleep; 2395 UInt32 state = PD_S_TXQ_LOW_WATER; 2396 UInt32 mask; 2397 IOReturn rtn = kIOReturnSuccess; 2398 2399 XTRACE(this, size, sleep, "enqueueDataGated"); 2400 2401 if (fTerminate || fStopping) 2402 return kIOReturnOffline; 2403 2404 *count = 0; 2405 2406 if (!(fPort.State & PD_S_ACTIVE)) 2407 return kIOReturnNotOpen; 2408 2409 XTRACE(this, fPort.State, size, "enqueueDataGated - current State"); 2410// LogData(kDataOther, size, buffer); 2411 2412 // Go ahead and try to add something to the buffer 2413 2414 *count = AddtoQueue(&fPort.TX, buffer, size); 2415 CheckQueues(); 2416 2417 // Let the tranmitter know that we have something ready to go 2418 2419 setUpTransmit(); 2420 2421 // If we could not queue up all of the data on the first pass and 2422 // the user wants us to sleep until it's all out then sleep 2423 2424 while ((*count < size) && sleep) 2425 { 2426 state = PD_S_TXQ_LOW_WATER; 2427 mask = PD_S_TXQ_LOW_WATER; 2428 rtn = watchStateGated(&state, &mask); 2429 if (rtn != kIOReturnSuccess) 2430 { 2431 XTRACE(this, 0, rtn, "enqueueDataGated - interrupted"); 2432 return rtn; 2433 } 2434 2435 *count += AddtoQueue(&fPort.TX, buffer + *count, size - *count); 2436 CheckQueues(); 2437 2438 // Let the tranmitter know that we have something ready to go. 2439 2440 setUpTransmit(); 2441 } 2442 2443 XTRACE(this, *count, size, "enqueueDataGated - Exit"); 2444 2445 return kIOReturnSuccess; 2446 2447}/* end enqueueDataGated */ 2448 2449/****************************************************************************************************/ 2450// 2451// Method: AppleUSBCDCDMM::dequeueData 2452// 2453// Inputs: size - buffer size 2454// min - minimum bytes required 2455// refCon - the Port 2456// 2457// Outputs: buffer - data returned 2458// min - number of bytes 2459// Return Code - kIOReturnSuccess, kIOReturnBadArgument, kIOReturnNotOpen, or value returned from watchState 2460// 2461// Desc: set up for dequeueDataGated call. 2462// 2463/****************************************************************************************************/ 2464 2465IOReturn AppleUSBCDCDMM::dequeueData(UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, void *refCon) 2466{ 2467 IOReturn ret; 2468 2469 XTRACE(this, size, min, "dequeueData"); 2470 2471 if (fTerminate || fStopping) 2472 { 2473 XTRACE(this, 0, kIOReturnOffline, "dequeueData - Offline"); 2474 return kIOReturnOffline; 2475 } 2476 2477 if ((count == NULL) || (buffer == NULL) || (min > size)) 2478 return kIOReturnBadArgument; 2479 2480 retain(); 2481 ret = fCommandGate->runAction(dequeueDataAction, (void *)buffer, (void *)&size, (void *)count, (void *)&min); 2482 release(); 2483 2484 return ret; 2485 2486}/* end dequeueData */ 2487 2488/****************************************************************************************************/ 2489// 2490// Method: AppleUSBCDCDMM::dequeueDatatAction 2491// 2492// Desc: Dummy pass through for dequeueDataGated. 2493// 2494/****************************************************************************************************/ 2495 2496IOReturn AppleUSBCDCDMM::dequeueDataAction(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3) 2497{ 2498 2499 return ((AppleUSBCDCDMM *)owner)->dequeueDataGated((UInt8 *)arg0, (UInt32 *)arg1, (UInt32 *)arg2, (UInt32 *)arg3); 2500 2501}/* end dequeueDataAction */ 2502 2503/****************************************************************************************************/ 2504// 2505// Method: AppleUSBCDCDMM::dequeueDataGated 2506// 2507// Inputs: size - buffer size 2508// min - minimum bytes required 2509// 2510// Outputs: buffer - data returned 2511// min - number of bytes 2512// Return Code - kIOReturnSuccess, kIOReturnBadArgument, kIOReturnNotOpen, or value returned from watchState 2513// 2514// Desc: dequeueData will attempt to copy data from the RX queue to the 2515// specified buffer. No more than bufferSize VALID_DATA events 2516// will be transferred. In other words, copying will continue until 2517// either a non-data event is encountered or the transfer buffer 2518// is full. The actual number of bytes transferred is returned 2519// in count. 2520// The sleep semantics of this method are slightly more complicated 2521// than other methods in this API. Basically, this method will 2522// continue to sleep until either min characters have been 2523// received or a non data event is next in the RX queue. If 2524// min is zero, then this method never sleeps and will return 2525// immediately if the queue is empty. 2526// Note that the caller should ALWAYS check the transferCount 2527// unless the return value was kIOReturnBadArgument, indicating one or 2528// more arguments were not valid. 2529// 2530/****************************************************************************************************/ 2531 2532IOReturn AppleUSBCDCDMM::dequeueDataGated(UInt8 *buffer, UInt32 *pSize, UInt32 *count, UInt32 *pMin) 2533{ 2534 UInt32 size = *pSize; 2535 UInt32 min = *pMin; 2536 IOReturn rtn = kIOReturnSuccess; 2537 UInt32 state = 0; 2538 UInt32 mask; 2539 bool goXOIdle; 2540 2541 XTRACE(this, size, min, "dequeueDataGated"); 2542 2543 if (fTerminate || fStopping) 2544 return kIOReturnOffline; 2545 2546 // If the port is not active then there should not be any chars. 2547 2548 *count = 0; 2549 if (!(fPort.State & PD_S_ACTIVE)) 2550 return kIOReturnNotOpen; 2551 2552 // Get any data living in the queue. 2553 2554 *count = RemovefromQueue(&fPort.RX, buffer, size); 2555 CheckQueues(); 2556 2557 while ((min > 0) && (*count < min)) 2558 { 2559 // Figure out how many bytes we have left to queue up 2560 2561 state = 0; 2562 mask = PD_S_RXQ_EMPTY; 2563 rtn = watchStateGated(&state, &mask); 2564 2565 if (rtn != kIOReturnSuccess) 2566 { 2567 XTRACE(this, 0, rtn, "dequeueDataGated - Interrupted!"); 2568 return rtn; 2569 } 2570 2571 // Try and get more data starting from where we left off 2572 2573 *count += RemovefromQueue(&fPort.RX, buffer + *count, (size - *count)); 2574 CheckQueues(); 2575 2576 } 2577 2578 // Now let's check our receive buffer to see if we need to stop 2579 2580 goXOIdle = (UsedSpaceinQueue(&fPort.RX) < fPort.RXStats.LowWater) && (fPort.RXOstate == SENT_XOFF); 2581 2582 if (goXOIdle) 2583 { 2584 fPort.RXOstate = IDLE_XO; 2585 AddBytetoQueue(&fPort.TX, fPort.XOFFchar); 2586 setUpTransmit(); 2587 } 2588 2589 XTRACE(this, *count, size, "dequeueData - Exit"); 2590 2591 return rtn; 2592 2593}/* end dequeueDataGated */ 2594 2595/****************************************************************************************************/ 2596// 2597// Method: AppleUSBCDCDMM::setUpTransmit 2598// 2599// Inputs: 2600// 2601// Outputs: return code - true (transmit started), false (transmission already in progress) 2602// 2603// Desc: Setup and then start transmisson 2604// 2605/****************************************************************************************************/ 2606 2607bool AppleUSBCDCDMM::setUpTransmit() 2608{ 2609 2610 XTRACE(this, 0, 0, "setUpTransmit"); 2611 2612 // As a precaution just check we've not been terminated (maybe a woken thread) 2613 2614 if (fTerminate || fStopping) 2615 { 2616 XTRACE(this, 0, 0, "setUpTransmit - terminated"); 2617 return false; 2618 } 2619 2620 if (UsedSpaceinQueue(&fPort.TX) > 0) 2621 { 2622 startTransmission(); 2623 } 2624 2625 return TRUE; 2626 2627}/* end setUpTransmit */ 2628 2629/****************************************************************************************************/ 2630// 2631// Method: AppleUSBCDCDMM::startTransmission 2632// 2633// Inputs: 2634// 2635// Outputs: 2636// 2637// Desc: Start the transmisson 2638// Must be called from a gated method 2639// 2640/****************************************************************************************************/ 2641 2642void AppleUSBCDCDMM::startTransmission() 2643{ 2644 UInt32 state; 2645 UInt32 mask; 2646 size_t count; 2647 IOReturn ior; 2648 2649 XTRACE(this, 0, 0, "startTransmission"); 2650 2651 // Check if we have a cr, if not just exit 2652 2653 count = isCRinQueue(&fPort.TX); 2654 2655 if (count <= 0) 2656 { 2657 // Updates all the status flags 2658 2659 CheckQueues(); 2660 return; 2661 } 2662 2663 // Fill up the buffer with characters from the queue 2664 2665 count = RemovefromQueue(&fPort.TX, fOutBuffer, count); 2666 2667 state = PD_S_TX_BUSY; 2668 mask = PD_S_TX_BUSY; 2669 setStateGated(&state, &mask); 2670 2671 XTRACE(this, fPort.State, count, "startTransmission - Bytes to write"); 2672 LogData(kDataOut, count, fOutBuffer); 2673 2674 ior = sendMERRequest(kUSBSEND_ENCAPSULATED_COMMAND, 0, count, fOutBuffer, &fMERCompletionInfo); 2675 if (ior != kIOReturnSuccess) 2676 { 2677 XTRACE(this, 0, ior, "startTransmission - sendMERRequest failed"); 2678 } 2679 2680 // We just removed a bunch of stuff from the 2681 // queue, so see if we can free some thread(s) 2682 // to enqueue more stuff. 2683 2684 CheckQueues(); 2685 2686}/* end startTransmission */ 2687 2688/****************************************************************************************************/ 2689// 2690// Method: AppleUSBCDCDMM::sendMERRequest 2691// 2692// Inputs: 2693// 2694// Outputs: 2695// 2696// Desc: Set up and send a Management Element Request(MER). 2697// 2698/****************************************************************************************************/ 2699 2700IOReturn AppleUSBCDCDMM::sendMERRequest(UInt8 request, UInt16 val, UInt16 len, UInt8 *buff, IOUSBCompletion *Comp) 2701{ 2702 IOUSBDevRequest *MER; 2703 IOReturn rc = kIOReturnSuccess; 2704 2705 XTRACE(this, 0, 0, "sendMERRequest"); 2706 2707 MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest)); 2708 if (!MER) 2709 { 2710 XTRACE(this, 0, 0, "sendMERRequest - allocate MER failed"); 2711 return kIOReturnError; 2712 } 2713 bzero(MER, sizeof(IOUSBDevRequest)); 2714 2715 // now build the Management Element Request 2716 2717 MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface); 2718 MER->bRequest = request; 2719 MER->wValue = val; 2720 MER->wIndex = fInterfaceNumber; 2721 if (len > 0) 2722 { 2723 MER->wLength = len; 2724 MER->pData = buff; 2725 } else { 2726 MER->wLength = 0; 2727 MER->pData = NULL; 2728 } 2729 2730 Comp->parameter = MER; 2731 2732 rc = fInterface->GetDevice()->DeviceRequest(MER, Comp); 2733 if (rc != kIOReturnSuccess) 2734 { 2735 XTRACE(this, MER->bRequest, rc, "sendMERRequest - error issueing DeviceRequest"); 2736 IOFree(MER, sizeof(IOUSBDevRequest)); 2737 } 2738 2739 return rc; 2740 2741} 2742 2743/* end sendMERRequest */ 2744 2745/****************************************************************************************************/ 2746// 2747// Method: AppleUSBCDCDMM::setLineCoding 2748// 2749// Inputs: 2750// 2751// Outputs: 2752// 2753// Desc: Set up and send SetLineCoding Management Element Request(MER) for all settings. 2754// 2755/****************************************************************************************************/ 2756 2757void AppleUSBCDCDMM::setLineCoding() 2758{ 2759 IOReturn ior; 2760 LineCoding *lineParms; 2761 UInt16 lcLen = sizeof(LineCoding)-1; 2762 2763 XTRACE(this, 0, 0, "setLineCoding"); 2764 2765 return; 2766 2767 // Check for changes and only do it if something's changed 2768 2769 if ((fPort.BaudRate == fPort.LastBaudRate) && (fPort.StopBits == fPort.LastStopBits) && 2770 (fPort.TX_Parity == fPort.LastTX_Parity) && (fPort.CharLength == fPort.LastCharLength)) 2771 { 2772 return; 2773 } 2774 2775 lineParms = (LineCoding *)IOMalloc(lcLen); 2776 if (!lineParms) 2777 { 2778 XTRACE(this, 0, 0, "setLineCoding - allocate lineParms failed"); 2779 return; 2780 } 2781 bzero(lineParms, lcLen); 2782 2783 // Convert BaudRate - intel format doubleword (32 bits) 2784 2785 OSWriteLittleInt32(lineParms, dwDTERateOffset, fPort.BaudRate); 2786 lineParms->bCharFormat = fPort.StopBits - 2; 2787 lineParms->bParityType = fPort.TX_Parity - 1; 2788 lineParms->bDataBits = fPort.CharLength; 2789 2790 // Now send it 2791 2792 ior = sendMERRequest(kUSBSET_LINE_CODING, 0, lcLen, (UInt8 *)lineParms, &fMERCompletionInfo); 2793 if (ior != kIOReturnSuccess) 2794 { 2795 XTRACE(this, 0, ior, "setLineCoding - sendMERRequest failed"); 2796 IOFree(lineParms, lcLen); 2797 } 2798 2799}/* end setLineCoding */ 2800 2801/****************************************************************************************************/ 2802// 2803// Method: AppleUSBCDCDMM::setControlLineState 2804// 2805// Inputs: RTS - true(set RTS), false(clear RTS) 2806// DTR - true(set DTR), false(clear DTR) 2807// 2808// Outputs: 2809// 2810// Desc: Set up and send SetControlLineState Management Element Request(MER). 2811// 2812/****************************************************************************************************/ 2813 2814void AppleUSBCDCDMM::setControlLineState(bool RTS, bool DTR) 2815{ 2816 IOReturn ior; 2817 UInt16 CSBitmap = 0; 2818 2819 XTRACE(this, 0, 0, "setControlLineState"); 2820 2821 return; 2822 2823 if (RTS) 2824 CSBitmap |= kRTSOn; 2825 if (DTR) 2826 CSBitmap |= kDTROn; 2827 2828 // Now send it 2829 2830 ior = sendMERRequest(kUSBSET_CONTROL_LINE_STATE, CSBitmap, 0, NULL, &fMERCompletionInfo); 2831 if (ior != kIOReturnSuccess) 2832 { 2833 XTRACE(this, 0, ior, "setControlLineState - sendMERRequest failed"); 2834 } 2835 2836}/* end setControlLineState */ 2837 2838/****************************************************************************************************/ 2839// 2840// Method: AppleUSBCDCDMM::sendBreak 2841// 2842// Inputs: sBreak - true(set Break), false(clear Break) 2843// 2844// Outputs: 2845// 2846// Desc: Set up and send SendBreak Management Element Request(MER). 2847// 2848/****************************************************************************************************/ 2849 2850void AppleUSBCDCDMM::sendBreak(bool sBreak) 2851{ 2852 IOReturn ior; 2853 UInt16 breakVal = 0; 2854 2855 XTRACE(this, 0, 0, "sendBreak"); 2856 2857 return; 2858 2859 if (sBreak) 2860 { 2861 breakVal = 0xFFFF; 2862 } 2863 2864 // Now send it 2865 2866 ior = sendMERRequest(kUSBSEND_BREAK, breakVal, 0, NULL, &fMERCompletionInfo); 2867 if (ior != kIOReturnSuccess) 2868 { 2869 XTRACE(this, 0, ior, "sendBreak - sendMERRequest failed"); 2870 } 2871 2872}/* end sendBreak */ 2873 2874/****************************************************************************************************/ 2875// 2876// Method: AppleUSBCDCDMM::initStructure 2877// 2878// Inputs: 2879// 2880// Outputs: 2881// 2882// Desc: Initialize the port structure 2883// 2884/****************************************************************************************************/ 2885 2886void AppleUSBCDCDMM::initStructure() 2887{ 2888 2889 XTRACE(this, 0, 0, "initStructure"); 2890 2891 // These are set up at start and should not be reset during execution. 2892 2893 fPort.FCRimage = 0x00; 2894 fPort.IERmask = 0x00; 2895 2896 fPort.State = (PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER); 2897 fPort.WatchStateMask = 0x00000000; 2898 2899}/* end initStructure */ 2900 2901/****************************************************************************************************/ 2902// 2903// Method: AppleUSBCDCDMM::setStructureDefaults 2904// 2905// Inputs: 2906// 2907// Outputs: 2908// 2909// Desc: Sets the defaults for the specified port structure 2910// 2911/****************************************************************************************************/ 2912 2913void AppleUSBCDCDMM::setStructureDefaults() 2914{ 2915 UInt32 tmp; 2916 2917 XTRACE(this, 0, 0, "setStructureDefaults"); 2918 2919 fPort.BaudRate = kDefaultBaudRate; // 9600 bps 2920 fPort.LastBaudRate = 0; 2921 fPort.CharLength = 8; // 8 Data bits 2922 fPort.LastCharLength = 0; 2923 fPort.StopBits = 2; // 1 Stop bit 2924 fPort.LastStopBits = 0; 2925 fPort.TX_Parity = 1; // No Parity 2926 fPort.LastTX_Parity = 0; 2927 fPort.RX_Parity = 1; // --ditto-- 2928 fPort.MinLatency = false; 2929 fPort.XONchar = '\x11'; 2930 fPort.XOFFchar = '\x13'; 2931 fPort.FlowControl = 0x00000000; 2932 fPort.RXOstate = IDLE_XO; 2933 fPort.TXOstate = IDLE_XO; 2934 fPort.FrameTOEntry = NULL; 2935 2936 fPort.RXStats.BufferSize = kMaxCirBufferSize; 2937 fPort.RXStats.HighWater = (fPort.RXStats.BufferSize << 1) / 3; 2938 fPort.RXStats.LowWater = fPort.RXStats.HighWater >> 1; 2939 fPort.TXStats.BufferSize = kMaxCirBufferSize; 2940 fPort.TXStats.HighWater = (fPort.RXStats.BufferSize << 1) / 3; 2941 fPort.TXStats.LowWater = fPort.RXStats.HighWater >> 1; 2942 2943 fPort.FlowControl = (DEFAULT_AUTO | DEFAULT_NOTIFY); 2944 2945 for (tmp=0; tmp < (256 >> SPECIAL_SHIFT); tmp++) 2946 fPort.SWspecial[ tmp ] = 0; 2947 2948}/* end setStructureDefaults */ 2949 2950/****************************************************************************************************/ 2951// 2952// Method: AppleUSBCDCDMM::allocateResources 2953// 2954// Inputs: 2955// 2956// Outputs: return code - true (allocate was successful), false (it failed) 2957// 2958// Desc: Finishes up the rest of the configuration and gets all the endpoints open etc. 2959// 2960/****************************************************************************************************/ 2961 2962bool AppleUSBCDCDMM::allocateResources() 2963{ 2964 IOUSBFindEndpointRequest epReq; 2965 IOReturn rtn; 2966 2967 XTRACE(this, 0, 0, "allocateResources."); 2968 2969 // Open all the end points and get the buffers 2970 2971 if (!fInterface->open(this)) 2972 { 2973 XTRACE(this, 0, 0, "allocateResources - open data interface failed."); 2974 return false; 2975 } 2976 2977 // Interrupt pipe 2978 2979 epReq.type = kUSBInterrupt; 2980 epReq.direction = kUSBIn; 2981 fIntPipe = fInterface->FindNextPipe(0, &epReq); 2982 if (!fIntPipe) 2983 { 2984 XTRACE(this, 0, 0, "allocateResources - no interrrupt pipe."); 2985 return false; 2986 } 2987 XTRACEP(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - interrupt pipe."); 2988 fIntBufferSize = epReq.maxPacketSize; 2989 2990 // Allocate Memory Descriptor Pointer with memory for the Interrupt pipe: 2991 2992 fIntPipeMDP = IOBufferMemoryDescriptor::withCapacity(fIntBufferSize, kIODirectionIn); 2993 if (!fIntPipeMDP) 2994 { 2995 XTRACE(this, 0, 0, "allocateResources - Couldn't allocate MDP for interrupt pipe"); 2996 return false; 2997 } 2998 2999 fIntPipeBuffer = (UInt8*)fIntPipeMDP->getBytesNoCopy(); 3000 XTRACEP(this, 0, fIntPipeBuffer, "allocateResources - comm buffer"); 3001 3002 // Now the input and output buffers 3003 3004 fInBuffer = (UInt8 *)IOMalloc(fMax_Command); 3005 if (!fInBuffer) 3006 { 3007 XTRACE(this, 0, 0, "allocateResources - allocate input buffer failed"); 3008 return false; 3009 } 3010 bzero(fInBuffer, fMax_Command); 3011 3012 fOutBuffer = (UInt8 *)IOMalloc(fMax_Command); 3013 if (!fOutBuffer) 3014 { 3015 XTRACE(this, 0, 0, "allocateResources - allocate output buffer failed"); 3016 return false; 3017 } 3018 bzero(fOutBuffer, fMax_Command); 3019 3020 // Now the ring buffers 3021 3022 if (!allocateRingBuffer(&fPort.TX, fPort.TXStats.BufferSize)) 3023 { 3024 XTRACE(this, 0, 0, "allocateResources - Couldn't allocate TX ring buffer"); 3025 return false; 3026 } 3027 3028 XTRACEP(this, 0, fPort.TX.Start, "allocateResources - TX ring buffer"); 3029 3030 if (!allocateRingBuffer(&fPort.RX, fPort.RXStats.BufferSize)) 3031 { 3032 XTRACE(this, 0, 0, "allocateResources - Couldn't allocate RX ring buffer"); 3033 return false; 3034 } 3035 3036 XTRACEP(this, 0, fPort.RX.Start, "allocateResources - RX ring buffer"); 3037 3038 // Read the interrupt pipe 3039 3040 fIntCompletionInfo.target = this; 3041 fIntCompletionInfo.action = intReadComplete; 3042 fIntCompletionInfo.parameter = NULL; 3043 3044 rtn = fIntPipe->Read(fIntPipeMDP, &fIntCompletionInfo, NULL); 3045 if (rtn != kIOReturnSuccess) 3046 { 3047 XTRACE(this, rtn, 0, "allocateResources - Read for interrupt pipe failed"); 3048 return false; 3049 } 3050 3051 // Set up the MER completion routine 3052 3053 fMERCompletionInfo.target = this; 3054 fMERCompletionInfo.action = merWriteComplete; 3055 fMERCompletionInfo.parameter = NULL; 3056 3057 // Set up the response completion routine 3058 3059 fRspCompletionInfo.target = this; 3060 fRspCompletionInfo.action = rspComplete; 3061 fRspCompletionInfo.parameter = NULL; 3062 3063 return true; 3064 3065}/* end allocateResources */ 3066 3067/****************************************************************************************************/ 3068// 3069// Method: AppleUSBCDCDMM::releaseResources 3070// 3071// Inputs: 3072// 3073// Outputs: 3074// 3075// Desc: Frees up the resources allocated in allocateResources 3076// 3077/****************************************************************************************************/ 3078 3079void AppleUSBCDCDMM::releaseResources() 3080{ 3081 3082 XTRACE(this, 0, 0, "releaseResources"); 3083 3084 if (fIntPipe) 3085 { 3086 fIntPipe->Abort(); 3087 } 3088 3089 if (fInterface) 3090 { 3091 fInterface->close(this); 3092 fInterface->release(); 3093 fInterface = NULL; 3094 } 3095 3096 if (fIntPipeMDP) 3097 { 3098 fIntPipeMDP->release(); 3099 fIntPipeMDP = 0; 3100 } 3101 3102#if 0 3103 if (fInBuffer) 3104 { 3105 IOFree(fInBuffer, fMax_Command); 3106 fInBuffer = 0; 3107 } 3108#endif 3109 3110 if (fWorkLoop) 3111 { 3112 fWorkLoop->release(); 3113 fWorkLoop = NULL; 3114 } 3115 3116 freeRingBuffer(&fPort.TX); 3117 freeRingBuffer(&fPort.RX); 3118 3119}/* end releaseResources */ 3120 3121/****************************************************************************************************/ 3122// 3123// Method: AppleUSBCDCDMM::freeRingBuffer 3124// 3125// Inputs: Queue - the specified queue to free 3126// 3127// Outputs: 3128// 3129// Desc: Frees all resources assocated with the queue, then sets all queue parameters 3130// to safe values. 3131// 3132/****************************************************************************************************/ 3133 3134void AppleUSBCDCDMM::freeRingBuffer(CirQueue *Queue) 3135{ 3136 XTRACEP(this, 0, Queue, "freeRingBuffer"); 3137 3138 if (Queue) 3139 { 3140 if (Queue->Start) 3141 { 3142 IOFree(Queue->Start, Queue->Size); 3143 } 3144 CloseQueue(Queue); 3145 } 3146 3147}/* end freeRingBuffer */ 3148 3149/****************************************************************************************************/ 3150// 3151// Method: AppleUSBCDCDMM::allocateRingBuffer 3152// 3153// Inputs: Queue - the specified queue to allocate 3154// BufferSize - size to allocate 3155// 3156// Outputs: return Code - true (buffer allocated), false (it failed) 3157// 3158// Desc: Allocates resources needed by the queue, then sets up all queue parameters. 3159// 3160/****************************************************************************************************/ 3161 3162bool AppleUSBCDCDMM::allocateRingBuffer(CirQueue *Queue, size_t BufferSize) 3163{ 3164 UInt8 *Buffer; 3165 3166 // Size is ignored and kMaxCirBufferSize, which is 4096, is used. 3167 3168 XTRACE(this, 0, BufferSize, "allocateRingBuffer"); 3169 Buffer = (UInt8*)IOMalloc(kMaxCirBufferSize); 3170 3171 InitQueue(Queue, Buffer, kMaxCirBufferSize); 3172 3173 if (Buffer) 3174 return true; 3175 3176 return false; 3177 3178}/* end allocateRingBuffer */ 3179 3180/****************************************************************************************************/ 3181// 3182// Method: AppleUSBCDCDMM::message 3183// 3184// Inputs: type - message type 3185// provider - my provider 3186// argument - additional parameters 3187// 3188// Outputs: return Code - kIOReturnSuccess 3189// 3190// Desc: Handles IOKit messages. 3191// 3192/****************************************************************************************************/ 3193 3194IOReturn AppleUSBCDCDMM::message(UInt32 type, IOService *provider, void *argument) 3195{ 3196 IOReturn rtn; 3197 3198 XTRACE(this, 0, type, "message"); 3199 3200 switch (type) 3201 { 3202 case kIOMessageServiceIsTerminated: 3203 XTRACE(this, fSessions, type, "message - kIOMessageServiceIsTerminated"); 3204 fTerminate = true; // We're being terminated (unplugged) 3205 releaseResources(); 3206 return kIOReturnSuccess; 3207 case kIOMessageServiceIsSuspended: 3208 XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended"); 3209 break; 3210 case kIOMessageServiceIsResumed: 3211 XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed"); 3212 break; 3213 case kIOMessageServiceIsRequestingClose: 3214 XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose"); 3215 break; 3216 case kIOMessageServiceWasClosed: 3217 XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed"); 3218 break; 3219 case kIOMessageServiceBusyStateChange: 3220 XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange"); 3221 break; 3222 case kIOUSBMessagePortHasBeenResumed: 3223 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed"); 3224 if (fReadDead) 3225 { 3226 rtn = fIntPipe->Read(fIntPipeMDP, &fIntCompletionInfo, NULL); 3227 if (rtn != kIOReturnSuccess) 3228 { 3229 XTRACE(this, 0, rtn, "message - Read for interrupt-in pipe failed, still dead"); 3230 } else { 3231 fReadDead = false; 3232 } 3233 } 3234 return kIOReturnSuccess; 3235 case kIOUSBMessageHubResumePort: 3236 XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort"); 3237 break; 3238 case kIOUSBMessagePortHasBeenReset: 3239 XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenReset"); 3240 if (fReadDead) 3241 { 3242 rtn = fIntPipe->Read(fIntPipeMDP, &fIntCompletionInfo, NULL); 3243 if (rtn != kIOReturnSuccess) 3244 { 3245 XTRACE(this, 0, rtn, "message - Read for interrupt-in pipe failed, still dead"); 3246 } else { 3247 fReadDead = false; 3248 } 3249 } 3250 return kIOReturnSuccess; 3251 default: 3252 XTRACE(this, 0, type, "message - unknown message"); 3253 break; 3254 } 3255 3256 return super::message(type, provider, argument); 3257 3258}/* end message */