1 2 /* Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23 /* AppleUSBIrDA.cpp - MacOSX implementation of USB IrDA Driver. */ 24 25#include <machine/limits.h> /* UINT_MAX */ 26#include <libkern/OSByteOrder.h> 27 28#include <IOKit/assert.h> 29#include <IOKit/IOLib.h> 30#include <IOKit/IOService.h> 31#include <IOKit/IOBufferMemoryDescriptor.h> 32#include <IOKit/IOMessage.h> 33 34#include <IOKit/usb/IOUSBBus.h> 35#include <IOKit/usb/IOUSBNub.h> 36#include <IOKit/usb/IOUSBPipe.h> 37#include <IOKit/usb/USB.h> 38#include <IOKit/usb/IOUSBInterface.h> 39 40#include <IOKit/serial/IOSerialKeys.h> 41#include <IOKit/serial/IOModemSerialStreamSync.h> 42#include <IOKit/serial/IORS232SerialStreamSync.h> 43 44#include <UserNotification/KUNCUserNotifications.h> 45 46#include "AppleUSBIrDA.h" 47#include "IrDAComm.h" 48#include "IrDAUser.h" 49#include "IrDALog.h" 50#include "IrDADebugging.h" 51 52 53#if (hasTracing > 0 && hasAppleUSBIrDATracing > 0) 54 55enum tracecodes 56{ 57 kLogInit = 1, 58 kLogFree, 59 kLogProbe, 60 kLogStart, 61 kLogStop, 62 63 kLogNewNub, 64 kLogNewPort, 65 kLogDestroyNub, 66 67 kLogSetSpeed, 68 kLogGetState, 69 kLogXmitLen, 70 kLogXmitData, 71 72 kLogAddRxBytes, 73 kLogSetBofCount, 74 kLogGetIrDAStatus, 75 76 kLogSetIrDAState, 77 kLogInterruptRead, 78 kLogDataReadComplete, 79 80 kLogInputData, 81 kLogDataWriteComplete, 82 kLogDataWriteCompleteZero, 83 84 kLogAllocateResources, 85 kLogReleaseResources, 86 kLogConfigureDevice, 87 kLogCreateSerialStream, 88 89 kLogAcquirePort, 90 kLogReleasePort, 91 kLogSetState, 92 kLogWatchState, 93 94 kLogExecEvent, 95 kLogExecEventData, 96 kLogReqEvent, 97 kLogReqEventData, 98 99 kLogSetupTransmit, 100 kLogSetStructureDefaults, 101 kLogMessage, 102 103 kLogWorkAround, 104 kLogWorkAroundComplete, 105 106 kLogInitForPM, 107 kLogInitialPowerState, 108 kLogSetPowerState 109}; 110 111static 112EventTraceCauseDesc gTraceEvents[] = { 113 {kLogInit, "AppleUSBIrDADriver: init"}, 114 {kLogFree, "AppleUSBIrDADriver: free"}, 115 {kLogProbe, "AppleUSBIrDADriver: probe, provider="}, 116 {kLogStart, "AppleUSBIrDADriver: start, provider="}, 117 {kLogStop, "AppleUSBIrDADriver: stop"}, 118 119 {kLogNewNub, "AppleUSBIrDADriver: new nub"}, 120 {kLogNewPort, "AppleUSBIrDADriver: new port"}, 121 {kLogDestroyNub, "AppleUSBIrDADriver: destroy nub"}, 122 123 {kLogSetSpeed, "AppleUSBIrDADriver: set irda speed"}, 124 {kLogGetState, "AppleUSBIrDADriver: get state"}, 125 {kLogXmitLen, "AppleUSBIrDADriver: xmit length"}, 126 {kLogXmitData, "AppleUSBIrDADriver: xmit data"}, 127 128 {kLogAddRxBytes, "AppleUSBIrDADriver: add rx bytes, count="}, 129 {kLogSetBofCount, "AppleUSBIrDADriver: set bof count, input="}, 130 {kLogGetIrDAStatus, "AppleUSBIrDADriver: get irda status, on="}, 131 132 {kLogSetIrDAState, "AppleUSBIrDADriver: set irda state, current=, want="}, 133 {kLogInterruptRead, "AppleUSBIrDADriver: interrupt read complete"}, 134 {kLogDataReadComplete, "AppleUSBIrDADriver: data read complete, rc, len="}, 135 136 {kLogInputData, "AppleUSBIrDADriver: data read buffer"}, 137 {kLogDataWriteComplete, "AppleUSBIrDADriver: data write complete, rc, len="}, 138 {kLogDataWriteCompleteZero, "AppleUSBIrDADriver: data write complete sending zero length packet"}, 139 140 {kLogAllocateResources, "AppleUSBIrDADriver: allocate resources"}, 141 {kLogReleaseResources, "AppleUSBIrDADriver: release resources"}, 142 {kLogConfigureDevice, "AppleUSBIrDADriver: configure device"}, 143 {kLogCreateSerialStream, "AppleUSBIrDADriver: create serial stream"}, 144 145 {kLogAcquirePort, "AppleUSBIrDADriver: acquire port"}, 146 {kLogReleasePort, "AppleUSBIrDADriver: release port"}, 147 {kLogSetState, "AppleUSBIrDADriver: set state"}, 148 {kLogWatchState, "AppleUSBIrDADriver: watch state"}, 149 150 {kLogExecEvent, "AppleUSBIrDADriver: execute event"}, 151 {kLogExecEventData, "AppleUSBIrDADriver: execute event, data="}, 152 {kLogReqEvent, "AppleUSBIrDADriver: request event"}, 153 {kLogReqEventData, "AppleUSBIrDADriver: request event, data="}, 154 155 {kLogSetupTransmit, "AppleUSBIrDADriver: setup transmit"}, 156 {kLogSetStructureDefaults, "AppleUSBIrDADriver: set structure defaults"}, 157 {kLogMessage, "AppleUSBIrDADriver: message"}, 158 159 {kLogWorkAround, "AppleUSBIrDADriver: workaround called"}, 160 {kLogWorkAroundComplete, "AppleUSBIrDADriver: workaround complete"}, 161 162 {kLogInitForPM, "AppleUSBIrDADriver: init power management"}, 163 {kLogInitialPowerState, "AppleUSBIrDADriver: get initial power state, flags="}, 164 {kLogSetPowerState, "AppleUSBIrDADriver: set power state, ordinal="} 165 166}; 167 168 169#define XTRACE(x, y, z) IrDALogAdd ( x, y, ((uintptr_t)z & 0xffff), gTraceEvents, true) 170#else 171#define XTRACE(x, y, z) ((void)0) 172#endif 173 174 175enum { 176 kUseInterruptsForRead = true 177}; 178 179enum { 180 kIrDAPowerOffState = 0, 181 kIrDAPowerOnState = 1, 182 kNumIrDAStates = 2 183}; 184 185static IOPMPowerState gOurPowerStates[kNumIrDAStates] = { 186 {1,0,0,0,0,0,0,0,0,0,0,0}, 187 {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0} 188}; 189 190 191 static IrDAglobals g; /**** Instantiate the globals ****/ 192 193#define super IOSerialDriverSync 194 195 OSDefineMetaClassAndStructors( AppleUSBIrDADriver, IOSerialDriverSync ); 196 197/****************************************************************************************************/ 198// 199// Function: Asciify 200// 201// Inputs: i - the nibble 202// 203// Outputs: return byte - ascii byte 204// 205// Desc: Converts to ascii. 206// 207/****************************************************************************************************/ 208 209static UInt8 Asciify(UInt8 i) 210{ 211 212 i &= 0xF; 213 if ( i < 10 ) 214 return( '0' + i ); 215 else return( 55 + i ); 216 217}/* end Asciify */ 218 219#if USE_ELG 220/****************************************************************************************************/ 221// 222// Function: AllocateEventLog 223// 224// Inputs: size - amount of memory to allocate 225// 226// Outputs: None 227// 228// Desc: Allocates the event log buffer 229// 230/****************************************************************************************************/ 231 232void AllocateEventLog( UInt32 size ) 233{ 234 if ( g.evLogBuf ) 235 return; 236 237 g.evLogFlag = 0; /* assume insufficient memory */ 238 g.evLogBuf = (UInt8*)IOMalloc( size ); 239 if ( !g.evLogBuf ) 240 { 241 kprintf( "AppleUSBIrDA: evLog allocation failed" ); 242 return; 243 } 244 245 bzero( g.evLogBuf, size ); 246 g.evLogBufp = g.evLogBuf; 247 g.evLogBufe = g.evLogBufp + kEvLogSize - 0x20; // ??? overran buffer? 248 g.evLogFlag = 0xFEEDBEEF; // continuous wraparound 249// g.evLogFlag = 'step'; // stop at each ELG 250// g.evLogFlag = 0x0333; // any nonzero - don't wrap - stop logging at buffer end 251 252 IOLog( "AppleUSBIrDA: AllocateEventLog - &USBglobals=%p buffer=%p", &g, (uintptr_t)g.evLogBuf ); 253 254 return; 255 256}/* end AllocateEventLog */ 257 258/****************************************************************************************************/ 259// 260// Function: EvLog 261// 262// Inputs: a - anything, b - anything, ascii - 4 charater tag, str - any info string 263// 264// Outputs: None 265// 266// Desc: Writes the various inputs to the event log buffer 267// 268/****************************************************************************************************/ 269 270void EvLog( UInt32 a, UInt32 b, UInt32 ascii, char* str ) 271{ 272 register UInt32 *lp; /* Long pointer */ 273 mach_timespec_t time; 274 275 if ( g.evLogFlag == 0 ) 276 return; 277 278 IOGetTime( &time ); 279 280 lp = (UInt32*)g.evLogBufp; 281 g.evLogBufp += 0x10; 282 283 if ( g.evLogBufp >= g.evLogBufe ) /* handle buffer wrap around if any */ 284 { g.evLogBufp = g.evLogBuf; 285 if ( g.evLogFlag != 0xFEEDBEEF ) // make 0xFEEDBEEF a symbolic ??? 286 g.evLogFlag = 0; /* stop tracing if wrap undesired */ 287 } 288 289 /* compose interrupt level with 3 byte time stamp: */ 290 291 *lp++ = (g.intLevel << 24) | ((time.tv_nsec >> 10) & 0x003FFFFF); // ~ 1 microsec resolution 292 *lp++ = a; 293 *lp++ = b; 294 *lp = ascii; 295 296 if( g.evLogFlag == 'step' ) 297 { static char code[ 5 ] = {0,0,0,0,0}; 298 *(UInt32*)&code = ascii; 299 IOLog( "AppleUSBIrDA: %8x %8x %8x %s\n", time.tv_nsec>>10, (unsigned int)a, (unsigned int)b, code ); 300 } 301 302 return; 303 304}/* end EvLog */ 305#endif // USE_ELG 306 307#if LOG_DATA 308#define dumplen 32 // Set this to the number of bytes to dump and the rest should work out correct 309 310#define buflen ((dumplen*2)+dumplen)+3 311#define Asciistart (dumplen*2)+3 312 313/****************************************************************************************************/ 314// 315// Function: DEVLogData 316// 317// Inputs: Dir - direction, Count - number of bytes, buf - the data 318// 319// Outputs: None 320// 321// Desc: Puts the data in the log. 322// 323/****************************************************************************************************/ 324 325void DEVLogData(UInt8 Dir, UInt32 Count, char *buf) 326{ 327 UInt8 wlen, i, Aspnt, Hxpnt; 328 UInt8 wchr; 329 char LocBuf[buflen+1]; 330 331 for ( i=0; i<=buflen; i++ ) 332 { 333 LocBuf[i] = 0x20; 334 } 335 LocBuf[i] = 0x00; 336 337 if ( Dir == kUSBIn ) 338 { 339 IOLog( "AppleUSBIrDA: USBLogData - Received, size = %8lx\n", (long unsigned int)Count ); 340 } else { 341 if ( Dir == kUSBOut ) 342 { 343 IOLog( "AppleUSBIrDA: USBLogData - Write, size = %8lx\n", (long unsigned int)Count ); 344 } else { 345 if ( Dir == kUSBAnyDirn ) 346 { 347 IOLog( "AppleUSBIrDA: USBLogData - Other, size = %8lx\n", (long unsigned int)Count ); 348 } 349 } 350 } 351 352 if ( Count > dumplen ) 353 { 354 wlen = dumplen; 355 } else { 356 wlen = Count; 357 } 358 359 if ( wlen > 0 ) 360 { 361 Aspnt = Asciistart; 362 Hxpnt = 0; 363 for ( i=1; i<=wlen; i++ ) 364 { 365 wchr = buf[i-1]; 366 LocBuf[Hxpnt++] = Asciify( wchr >> 4 ); 367 LocBuf[Hxpnt++] = Asciify( wchr ); 368 if (( wchr < 0x20) || (wchr > 0x7F )) // Non printable characters 369 { 370 LocBuf[Aspnt++] = 0x2E; // Replace with a period 371 } else { 372 LocBuf[Aspnt++] = wchr; 373 } 374 } 375 LocBuf[(wlen + Asciistart) + 1] = 0x00; 376 IOLog( "%s\n", LocBuf ); 377 } else { 378 IOLog( "AppleUSBIrDA: USBLogData - No data, Count = 0\n" ); 379 } 380 381}/* end DEVLogData */ 382#endif // LOG_DATA 383 384/* QueuePrimatives */ 385 386/****************************************************************************************************/ 387// 388// Method: AppleUSBIrDADriver::AddBytetoQueue 389// 390// Inputs: Queue - the queue to be added to 391// 392// Outputs: Value - Byte to be added, Queue status - full or no error 393// 394// Desc: Add a byte to the circular queue. 395// 396/****************************************************************************************************/ 397 398QueueStatus AppleUSBIrDADriver::AddBytetoQueue( CirQueue *Queue, char Value ) 399{ 400 /* Check to see if there is space by comparing the next pointer, */ 401 /* with the last, If they match we are either Empty or full, so */ 402 /* check the InQueue of being zero. */ 403 404 require(fPort && fPort->serialRequestLock, Fail); 405 IOLockLock( fPort->serialRequestLock ); 406 407 if ( (Queue->NextChar == Queue->LastChar) && Queue->InQueue ) { 408 IOLockUnlock( fPort->serialRequestLock); 409 return queueFull; 410 } 411 412 *Queue->NextChar++ = Value; 413 Queue->InQueue++; 414 415 /* Check to see if we need to wrap the pointer. */ 416 417 if ( Queue->NextChar >= Queue->End ) 418 Queue->NextChar = Queue->Start; 419 420 IOLockUnlock( fPort->serialRequestLock); 421 return queueNoError; 422 423Fail: 424 return queueFull; // for lack of a better error 425 426}/* end AddBytetoQueue */ 427 428/****************************************************************************************************/ 429// 430// Method: AppleUSBIrDADriver::GetBytetoQueue 431// 432// Inputs: Queue - the queue to be removed from 433// 434// Outputs: Value - where to put the byte, Queue status - empty or no error 435// 436// Desc: Remove a byte from the circular queue. 437// 438/****************************************************************************************************/ 439 440QueueStatus AppleUSBIrDADriver::GetBytetoQueue( CirQueue *Queue, UInt8 *Value ) 441{ 442 443 require(fPort && fPort->serialRequestLock, Fail); 444 IOLockLock( fPort->serialRequestLock ); 445 446 /* Check to see if the queue has something in it. */ 447 448 if ( (Queue->NextChar == Queue->LastChar) && !Queue->InQueue ) { 449 IOLockUnlock(fPort->serialRequestLock); 450 return queueEmpty; 451 } 452 453 *Value = *Queue->LastChar++; 454 Queue->InQueue--; 455 456 /* Check to see if we need to wrap the pointer. */ 457 458 if ( Queue->LastChar >= Queue->End ) 459 Queue->LastChar = Queue->Start; 460 461 IOLockUnlock(fPort->serialRequestLock); 462 return queueNoError; 463 464Fail: 465 return queueEmpty; // can't get to it, pretend it's empty 466 467}/* end GetBytetoQueue */ 468 469/****************************************************************************************************/ 470// 471// Method: AppleUSBIrDADriver::InitQueue 472// 473// Inputs: Queue - the queue to be initialized, Buffer - the buffer, size - length of buffer 474// 475// Outputs: Queue status - queueNoError. 476// 477// Desc: Pass a buffer of memory and this routine will set up the internal data structures. 478// 479/****************************************************************************************************/ 480 481QueueStatus AppleUSBIrDADriver::InitQueue( CirQueue *Queue, UInt8 *Buffer, size_t Size ) 482{ 483 Queue->Start = Buffer; 484 Queue->End = (UInt8*)((size_t)Buffer + Size); 485 Queue->Size = Size; 486 Queue->NextChar = Buffer; 487 Queue->LastChar = Buffer; 488 Queue->InQueue = 0; 489 490 IOSleep( 1 ); 491 492 return queueNoError ; 493 494}/* end InitQueue */ 495 496/****************************************************************************************************/ 497// 498// Method: AppleUSBIrDADriver::CloseQueue 499// 500// Inputs: Queue - the queue to be closed 501// 502// Outputs: Queue status - queueNoError. 503// 504// Desc: Clear out all of the data structures. 505// 506/****************************************************************************************************/ 507 508QueueStatus AppleUSBIrDADriver::CloseQueue( CirQueue *Queue ) 509{ 510 511 Queue->Start = 0; 512 Queue->End = 0; 513 Queue->NextChar = 0; 514 Queue->LastChar = 0; 515 Queue->Size = 0; 516 517 return queueNoError; 518 519}/* end CloseQueue */ 520 521/****************************************************************************************************/ 522// 523// Method: AppleUSBIrDADriver::AddtoQueue 524// 525// Inputs: Queue - the queue to be added to, Buffer - data to add, Size - length of data 526// 527// Outputs: BytesWritten - Number of bytes actually put in the queue. 528// 529// Desc: Add an entire buffer to the queue. 530// 531/****************************************************************************************************/ 532 533size_t AppleUSBIrDADriver::AddtoQueue( CirQueue *Queue, UInt8 *Buffer, size_t Size ) 534{ 535 size_t BytesWritten = 0; 536 537 while ( FreeSpaceinQueue( Queue ) && (Size > BytesWritten) ) 538 { 539 AddBytetoQueue( Queue, *Buffer++ ); 540 BytesWritten++; 541 } 542 543 return BytesWritten; 544 545}/* end AddtoQueue */ 546 547/****************************************************************************************************/ 548// 549// Method: AppleUSBIrDADriver::RemovefromQueue 550// 551// Inputs: Queue - the queue to be removed from, Size - size of buffer 552// 553// Outputs: Buffer - Where to put the data, BytesReceived - Number of bytes actually put in Buffer. 554// 555// Desc: Get a buffers worth of data from the queue. 556// 557/****************************************************************************************************/ 558 559size_t AppleUSBIrDADriver::RemovefromQueue( CirQueue *Queue, UInt8 *Buffer, size_t MaxSize ) 560{ 561 size_t BytesReceived = 0; 562 UInt8 Value; 563 564 while( (MaxSize > BytesReceived) && (GetBytetoQueue(Queue, &Value) == queueNoError) ) 565 { 566 *Buffer++ = Value; 567 BytesReceived++; 568 }/* end while */ 569 570 return BytesReceived; 571 572}/* end RemovefromQueue */ 573 574/****************************************************************************************************/ 575// 576// Method: AppleUSBIrDADriver::FreeSpaceinQueue 577// 578// Inputs: Queue - the queue to be queried 579// 580// Outputs: Return Value - Free space left 581// 582// Desc: Return the amount of free space left in this buffer. 583// 584/****************************************************************************************************/ 585 586size_t AppleUSBIrDADriver::FreeSpaceinQueue( CirQueue *Queue ) 587{ 588 size_t retVal = 0; 589 590 require(fPort && fPort->serialRequestLock, Fail); 591 IOLockLock( fPort->serialRequestLock ); 592 593 retVal = Queue->Size - Queue->InQueue; 594 595 IOLockUnlock(fPort->serialRequestLock); 596 597Fail: 598 return retVal; 599 600}/* end FreeSpaceinQueue */ 601 602/****************************************************************************************************/ 603// 604// Method: AppleUSBIrDADriver::UsedSpaceinQueue 605// 606// Inputs: Queue - the queue to be queried 607// 608// Outputs: UsedSpace - Amount of data in buffer 609// 610// Desc: Return the amount of data in this buffer. 611// 612/****************************************************************************************************/ 613 614size_t AppleUSBIrDADriver::UsedSpaceinQueue( CirQueue *Queue ) 615{ 616 return Queue->InQueue; 617 618}/* end UsedSpaceinQueue */ 619 620/****************************************************************************************************/ 621// 622// Method: AppleUSBIrDADriver::GetQueueSize 623// 624// Inputs: Queue - the queue to be queried 625// 626// Outputs: QueueSize - The size of the queue. 627// 628// Desc: Return the total size of the queue. 629// 630/****************************************************************************************************/ 631 632size_t AppleUSBIrDADriver::GetQueueSize( CirQueue *Queue ) 633{ 634 return Queue->Size; 635 636}/* end GetQueueSize */ 637 638/****************************************************************************************************/ 639// 640// Method: AppleUSBIrDADriver::GetQueueStatus 641// 642// Inputs: Queue - the queue to be queried 643// 644// Outputs: Queue status - full, empty or no error 645// 646// Desc: Returns the status of the circular queue. 647// 648/****************************************************************************************************/ 649/* 650QueueStatus AppleUSBIrDADriver::GetQueueStatus( CirQueue *Queue ) 651{ 652 if ( (Queue->NextChar == Queue->LastChar) && Queue->InQueue ) 653 return queueFull; 654 else if ( (Queue->NextChar == Queue->LastChar) && !Queue->InQueue ) 655 return queueEmpty; 656 657 return queueNoError ; 658 659}*/ /* end GetQueueStatus */ 660 661/****************************************************************************************************/ 662// 663// Method: AppleUSBIrDADriver::CheckQueues 664// 665// Inputs: port - the port to check 666// 667// Outputs: None 668// 669// Desc: Checks the various queue's etc and manipulates the state(s) accordingly 670// 671/****************************************************************************************************/ 672 673void AppleUSBIrDADriver::CheckQueues( PortInfo_t *port ) 674{ 675 unsigned long Used; 676 unsigned long Free; 677 unsigned long QueuingState; 678 unsigned long DeltaState; 679 680 // Initialise the QueueState with the current state. 681 QueuingState = readPortState( port ); 682 683 /* Check to see if there is anything in the Transmit buffer. */ 684 Used = UsedSpaceinQueue( &port->TX ); 685 Free = FreeSpaceinQueue( &port->TX ); 686// ELG( Free, Used, 'CkQs', "CheckQueues" ); 687 if ( Free == 0 ) 688 { 689 QueuingState |= PD_S_TXQ_FULL; 690 QueuingState &= ~PD_S_TXQ_EMPTY; 691 } 692 else if ( Used == 0 ) 693 { 694 QueuingState &= ~PD_S_TXQ_FULL; 695 QueuingState |= PD_S_TXQ_EMPTY; 696 } 697 else 698 { 699 QueuingState &= ~PD_S_TXQ_FULL; 700 QueuingState &= ~PD_S_TXQ_EMPTY; 701 } 702 703 /* Check to see if we are below the low water mark. */ 704 if ( Used < port->TXStats.LowWater ) 705 QueuingState |= PD_S_TXQ_LOW_WATER; 706 else QueuingState &= ~PD_S_TXQ_LOW_WATER; 707 708 if ( Used > port->TXStats.HighWater ) 709 QueuingState |= PD_S_TXQ_HIGH_WATER; 710 else QueuingState &= ~PD_S_TXQ_HIGH_WATER; 711 712 713 /* Check to see if there is anything in the Receive buffer. */ 714 Used = UsedSpaceinQueue( &port->RX ); 715 Free = FreeSpaceinQueue( &port->RX ); 716 717 if ( Free == 0 ) 718 { 719 QueuingState |= PD_S_RXQ_FULL; 720 QueuingState &= ~PD_S_RXQ_EMPTY; 721 } 722 else if ( Used == 0 ) 723 { 724 QueuingState &= ~PD_S_RXQ_FULL; 725 QueuingState |= PD_S_RXQ_EMPTY; 726 } 727 else 728 { 729 QueuingState &= ~PD_S_RXQ_FULL; 730 QueuingState &= ~PD_S_RXQ_EMPTY; 731 } 732 733 /* Check to see if we are below the low water mark. */ 734 if ( Used < port->RXStats.LowWater ) 735 QueuingState |= PD_S_RXQ_LOW_WATER; 736 else QueuingState &= ~PD_S_RXQ_LOW_WATER; 737 738 if ( Used > port->RXStats.HighWater ) 739 QueuingState |= PD_S_RXQ_HIGH_WATER; 740 else QueuingState &= ~PD_S_RXQ_HIGH_WATER; 741 742 /* Figure out what has changed to get mask.*/ 743 DeltaState = QueuingState ^ readPortState( port ); 744 changeState( port, QueuingState, DeltaState ); 745 746 return; 747 748}/* end CheckQueues */ 749 750/* end of QueuePrimatives */ 751 752/****************************************************************************************************/ 753// 754// Method: AppleUSBIrDADriver::Add_RXBytes 755// 756// Inputs: Buffer - the raw input data, Size - the length 757// 758// Outputs: 759// 760// Desc: Adds data to the circular receive queue 761// 762/****************************************************************************************************/ 763 764void AppleUSBIrDADriver::Add_RXBytes( UInt8 *Buffer, size_t Size ) 765{ 766 XTRACE(kLogAddRxBytes, 0, Size); 767 ELG( 0, Size, 'AdRB', "Add_RXBytes" ); 768 769 AddtoQueue( &fPort->RX, Buffer, Size ); 770 CheckQueues( fPort ); 771}/* end Add_RXBytes */ 772 773/****************************************************************************************************/ 774// 775// Method: AppleUSBIrDADriver::SetBofCount 776// 777// Inputs: bof_count - the requested number of Beginning Of Frames 778// 779// Outputs: return word - the actual count (not bofs) 780// 781// Desc: Encode the requested number of BOF bytes to the first value that's big enough 782// 783/****************************************************************************************************/ 784 785SInt16 AppleUSBIrDADriver::SetBofCount( SInt16 bof_count ) 786{ 787 SInt16 counts[] = { 0, 1, 2, 3, 6, 12, 24, 48, -1}; // the bof counts that are encoded below 788 SInt16 codes[] = { 8, 7, 6, 5, 4, 3, 2, 1, 1}; // could use an f(i), but this is easier to match to spec 789 int i, sz; 790 791 ELG( 0, bof_count, 'Sbof', "SetBofCount" ); 792 XTRACE(kLogSetBofCount, 0, bof_count); 793 794 // input is desired bof count at the current speed, but the usb hardware wants the 795 // unadjusted bof count (i.e. xbofs at 115k bps), so we have to adjust back to 115k. 796 797 if (fCurrentBaud < 115200) { 798 bof_count = bof_count * (115200 / fCurrentBaud); 799 XTRACE(kLogSetBofCount, 1, bof_count); 800 } 801 802 sz = sizeof(counts) / sizeof(counts[0]); 803 804 // note that the input bof counts can be computed, so we do an 'at least' test instead 805 // of insisting upon an exact match to one of the supported bof counts. 806 807 for (i = 0 ; i < sz; i++) 808 { 809 if (counts[i] >= bof_count || counts[i] < 0) // if table entry at least what's wanted (no smaller), or end-of-table 810 { 811 fBofsCode = codes[i]; // then save the encoded version 812 return counts[i]; // and return raw count used to caller 813 } 814 } 815 816 ELG( 0, i, 'Sbf-', "SetBofCount - logic error" ); 817 return 0; 818}/* end SetBofCount */ 819 820/****************************************************************************************************/ 821// 822// Method: AppleUSBIrDADriver::SetSpeed 823// 824// Inputs: brate - the requested baud rate 825// 826// Outputs: return word - baud coding 827// 828// Desc: Set the baudrate for the device 829// 830/****************************************************************************************************/ 831 832UInt16 AppleUSBIrDADriver::SetSpeed( UInt32 brate ) 833{ 834 XTRACE(kLogSetSpeed, brate >> 16, (short)brate); 835 ELG( 0, brate, 'Sbof', "SetSpeed" ); 836 837 fCurrentBaud = brate; 838 839 switch (brate) 840 { 841 case 2400: 842 fBaudCode = kLinkSpeed2400; // 0x01 843 break; 844 845 case 9600: 846 fBaudCode = kLinkSpeed9600; // 0x02 847 break; 848 849 case 19200: 850 fBaudCode = kLinkSpeed19200; // 0x03 851 break; 852 853 case 38400: 854 fBaudCode = kLinkSpeed38400; // 0x04 855 break; 856 857 case 57600: 858 fBaudCode = kLinkSpeed57600; // 0x05 859 break; 860 861 case 115200: 862 fBaudCode = kLinkSpeed115200; // 0x06 863 break; 864 865 case 576000: 866 fBaudCode = kLinkSpeed576000; // 0x07 867 break; 868 869 case 1152000: 870 fBaudCode = kLinkSpeed1152000; // 0x08 871 break; 872 873 case 4000000: 874 fBaudCode = kLinkSpeed4000000; // 0x09 875 break; 876 877 case 300: 878 case 600: 879 case 1200: 880 case 1800: 881 case 3600: 882 case 4800: 883 case 7200: 884 default: 885 ELG( 0, brate, 'SSp-', "SetSpeed - Unsupported baud rate"); 886 fBaudCode = 0; 887 break; 888 } 889 890 // start a one-byte transmit to set the speed in the device 891 StartTransmit(0, NULL, 0, NULL); // no control or data bytes, just the mode byte please 892 // note SetSpeedComplete is called out of transmit complete 893 return fBaudCode; 894}/* end SetSpeed */ 895 896/****************************************************************************************************/ 897// 898// Method: AppleUSBIrDADriver::GetIrDAComm 899// 900// Inputs: 901// 902// Outputs: IrDAComm - Address of the IrDA object 903// 904// Desc: Returns the address of the IrDA object 905// 906/****************************************************************************************************/ 907 908IrDAComm* AppleUSBIrDADriver::GetIrDAComm( void ) 909{ 910 return fIrDA; 911}/* end GetIrDAComm */ 912 913/****************************************************************************************************/ 914// 915// Method: AppleUSBIrDADriver::GetIrDAQoS 916// 917// Inputs: 918// 919// Outputs: USBIrDAQoS - Address of the QoS structure 920// 921// Desc: Returns the address of the Quality of Service structure 922// 923/****************************************************************************************************/ 924 925USBIrDAQoS* AppleUSBIrDADriver::GetIrDAQoS( void ) 926{ 927 return &fQoS; 928}/* end GetIrDAQoS */ 929 930/****************************************************************************************************/ 931// 932// Method: AppleUSBIrDADriver::GetIrDAStatus 933// 934// Inputs: status - status structure 935// 936// Outputs: 937// 938// Desc: Sets the connection state and CRC errors of the status structure 939// 940/****************************************************************************************************/ 941 942void AppleUSBIrDADriver::GetIrDAStatus( IrDAStatus *status ) 943{ 944 //int review_get_irda_status; // check w/irda on/off logic 945 946 ELG( 0, 0, 'GIrS', "GetIrDAStatus" ); 947 XTRACE(kLogGetIrDAStatus, 0, fIrDAOn); 948 949 if ( !fIrDAOn ) 950 { 951 //bzero( status, sizeof(IrDAStatus) ); 952 status->connectionState = kIrDAStatusOff; 953 } else { 954 if ( status->connectionState == kIrDAStatusOff ) 955 { 956 status->connectionState = kIrDAStatusIdle; 957 } 958 status->crcErrors = 0; // Unavailable 959 } 960 961}/* end GetIrDAStatus */ 962 963/****************************************************************************************************/ 964// 965// Method: AppleUSBIrDADriver::CheckIrDAState 966// 967// Inputs: open session count (fSessions) 968// user-client start request (fStartStopUserClient) 969// usb start/stop (fStartStopUSB) -- replace with fTerminate? 970// 971// Outputs: 972// 973// Desc: Turns IrDA on or off if appropriate 974// 975/****************************************************************************************************/ 976 977IOReturn AppleUSBIrDADriver::CheckIrDAState( void ) 978{ 979 IOReturn ior = kIOReturnSuccess; 980 Boolean newState = fUSBStarted & // usb must have started, and 981 (fPowerState == kIrDAPowerOnState) && // powered on by the power manager, and 982 (fUserClientStarted | (fSessions > 0)); // one of the clients too 983 984 ELG( 0, 0, 'SIrS', "CheckIrDAState" ); 985 XTRACE(kLogSetIrDAState, fIrDAOn, newState); 986 987 if ( newState && !fIrDAOn ) // Turn IrDA on if needed 988 { 989 fIrDAOn = true; 990 fTerminate = false; 991 992 if (!fSuspendFail) { // if previous suspend worked, then 993 // resume it and startIrDA will run from message(). 994 ior = fpDevice->SuspendDevice( false ); // Ask to resume the device 995 if ( ior != kIOReturnSuccess ) 996 { 997 ELG( 0, ior, 'SIR-', "SetIrDAState - Resume failed" ); 998 IOLog("AppleUSBIrDA: failed to resume device\n"); 999 fIrDAOn = false; // We're basically dead at this point 1000 fTerminate = true; 1001 } 1002 } 1003 else{ // earlier suspend failed, just start irda here 1004 if ( !startIrDA() ) 1005 { 1006 fIrDAOn = false; 1007 fTerminate = true; 1008 IOLog("AppleUSBIrDADriver: SetIrDAState - startIrDA failed" ); 1009 } else { 1010 ELG( 0, 0, 'msc+', "SetIrDAState - startIrDA successful" ); 1011 //IOLog("AppleUSBIrDADriver: message - startIrDA successful\n" ); 1012 } 1013 } 1014 } 1015 else if (!newState && fIrDAOn) // Turn IrDA off if needed 1016 { 1017 fIrDAOn = false; 1018 fTerminate = true; // Make it look like we've been terminated 1019 1020 stopIrDA(); // stop irda and stop pipe i/o 1021 1022 ior = fpDevice->SuspendDevice( true ); // Try to suspend the device 1023 if ( ior != kIOReturnSuccess ) 1024 { 1025 ELG( 0, 0, 'SIS-', "SetIrDAState - Suspend failed" ); 1026 IOLog("AppleUSBIrDA: failed to suspend device\n"); 1027 } 1028 } 1029 1030 return ior; 1031}/* end CheckIrDAState */ 1032 1033// 1034// User client has asked to start/stop irda. do it if 1035// it's ok w/bsd open count and usb start/stop flag. 1036// 1037IOReturn AppleUSBIrDADriver::SetIrDAUserClientState( bool IrDAOn ) 1038{ 1039 fUserClientStarted = IrDAOn; 1040 return CheckIrDAState(); 1041} 1042 1043/****************************************************************************************************/ 1044// 1045// Function: AppleUSBIrDADriver::init 1046// 1047// Inputs: dict - Dictionary 1048// 1049// Outputs: Return code - from super::init 1050// 1051// Desc: Driver initialization 1052// 1053/****************************************************************************************************/ 1054 1055bool AppleUSBIrDADriver::init( OSDictionary *dict ) 1056{ 1057 bool rc; 1058 1059 rc = super::init( dict ); 1060 IOLogIt( (uintptr_t)IrDALogGetInfo(), rc, 'init', "init" ); 1061 XTRACE(kLogInit, 0, rc); 1062 return rc; 1063 1064}/* end init */ 1065 1066/****************************************************************************************************/ 1067// 1068// Function: AppleUSBIrDADriver::probe 1069// 1070// Inputs: provider - my provider 1071// 1072// Outputs: IOService - from super::probe, score - probe score 1073// 1074// Desc: Modify the probe score if necessary (we don't at the moment) 1075// 1076/****************************************************************************************************/ 1077 1078IOService* AppleUSBIrDADriver::probe( IOService *provider, SInt32 *score ) 1079{ 1080 IOService *res; 1081 1082 res = super::probe( provider, score ); 1083 IOLogIt( provider, res, 'prob', "probe" ); 1084 XTRACE(kLogProbe, 0, provider); 1085 return res; 1086 1087}/* end probe */ 1088 1089 1090/****************************************************************************************************/ 1091// 1092// Method: AppleUSBIrDADriver::start 1093// 1094// Inputs: provider - my provider 1095// 1096// Outputs: Return code - true (it's me), false (sorry it probably was me, but I can't configure it) 1097// 1098// Desc: This is called once it has beed determined I'm probably the best 1099// driver for this device. 1100// 1101/****************************************************************************************************/ 1102 1103bool AppleUSBIrDADriver::start( IOService *provider ) 1104{ 1105 UInt8 configs; // number of device configurations 1106 bool ok; 1107 1108 XTRACE(kLogStart, 0, provider); 1109 1110 g.evLogBufp = NULL; 1111 1112 fTerminate = false; // Make sure we don't think we're being terminated 1113 fPort = NULL; 1114 fIrDA = NULL; 1115 fNub = NULL; 1116 fIrDAOn = false; 1117 fSuspendFail = false; 1118 fpInterface = NULL; 1119 1120 fpinterruptPipeBuffer = NULL; 1121 fPipeInBuffer = NULL; 1122 fPipeOutBuffer = NULL; 1123 1124 fpDevice = NULL; 1125 fpInPipe = NULL; 1126 fpOutPipe = NULL; 1127 fpInterruptPipe = NULL; 1128 1129 fUserClientStarted = false; // user/client has not started us yet 1130 fUSBStarted = false; // set to true when start finishes up ok 1131 fSessions = 0; 1132 1133 fReadActive = false; 1134 1135 fWriteActive = false; 1136 1137 fGate = IOCommandGate::commandGate(this, 0); // create a new command gate for PM 1138 require(fGate, Fail); 1139 getWorkLoop()->addEventSource(fGate); // add it to the usb workloop 1140 1141#if USE_ELG 1142 AllocateEventLog( kEvLogSize ); 1143 ELG( &g, g.evLogBufp, 'USBM', "start - event logging set up." ); 1144 1145 waitForService( resourceMatching( "kdp" ) ); 1146#endif /* USE_ELG */ 1147 1148 ELG( this, provider, 'strt', "start - this, provider." ); 1149 if( !super::start( provider ) ) 1150 { 1151 IOLogIt( 0, 0, 'SS--', "start - super failed" ); 1152 return false; 1153 } 1154 1155 /* Get my USB provider - the interface and then get the device */ 1156 1157 fpInterface = OSDynamicCast( IOUSBInterface, provider ); 1158 require(fpInterface, Fail); 1159 1160 fpDevice = fpInterface->GetDevice(); 1161 require(fpDevice, Fail); 1162 1163 /* Let's see if we have any configurations to play with */ 1164 1165 configs = fpDevice->GetNumConfigurations(); 1166 require(configs == 1, Fail); 1167 1168 // make our nub (and fPort) now 1169 ok = createNub(); 1170 require(ok, Fail); 1171 1172 // Now configure it (leaves device suspended) 1173 ok = configureDevice(configs); 1174 require(ok, Fail); 1175 1176 // Finally create the bsd tty (serial stream) and leave it there until usb stop 1177 1178 ok = createSerialStream(); 1179 require(ok, Fail); 1180 1181 ok = initForPM(provider); 1182 require(ok, Fail); 1183 1184 fUSBStarted = true; // now pay attn to bsd open's and user client start-irda requests 1185 1186 return true; 1187 1188Fail: 1189 1190 IOLogIt( 0, 0, 'sts-', "start - failed" ); 1191 stop( provider ); 1192 1193 return false; 1194 1195}/* end start */ 1196 1197// 1198// initForPM 1199// 1200// Add ourselves to the power management tree so we 1201// can do the right thing on sleep/wakeup. 1202// 1203bool AppleUSBIrDADriver::initForPM(IOService * provider) 1204{ 1205 XTRACE(kLogInitForPM, 0, 0); 1206 1207 fPowerThreadCall = thread_call_allocate(handleSetPowerState, (thread_call_param_t) this ); 1208 require(fPowerThreadCall != NULL, Fail); 1209 1210 fPowerState = kIrDAPowerOnState; // init our power state to be 'on' 1211 PMinit(); // init power manager instance variables 1212 provider->joinPMtree(this); // add us to the power management tree 1213 require(pm_vars != NULL, Fail); 1214 1215 // register ourselves with ourself as policy-maker 1216 registerPowerDriver(this, gOurPowerStates, kNumIrDAStates); 1217 return true; 1218 1219Fail: 1220 return false; 1221} 1222 1223// 1224// request for our initial power state 1225// 1226unsigned long AppleUSBIrDADriver::initialPowerStateForDomainState ( IOPMPowerFlags flags) 1227{ 1228 XTRACE(kLogInitialPowerState, flags >> 16, (short)flags); 1229 return fPowerState; 1230} 1231 1232// 1233// request to turn device on or off. since PM doesn't call us on our workloop, we'll 1234// get it going on another thead and wait for it. 1235// 1236IOReturn AppleUSBIrDADriver::setPowerState(unsigned long powerStateOrdinal, IOService * whatDevice) 1237{ 1238 //UInt32 counter = 0; 1239 1240 if (powerStateOrdinal == fPowerState) return kIOPMAckImplied; 1241 1242 if (fPowerThreadCall) { 1243 bool ok; 1244 1245 retain(); // paranoia is your friend, make sure we're not freed 1246 1247 fWaitForGatedCmd = true; 1248 ok = thread_call_enter1(fPowerThreadCall, (void *)powerStateOrdinal); // invoke handleSetPowerState 1249 1250 while (fWaitForGatedCmd) { // wait for it now 1251 IOSleep(1); // cycles to gated thread 1252 //counter++; 1253 } 1254 1255 if (ok) { // if thread was already pending ... 1256 release(); // don't need/want the retain, so undo it 1257 } // normally released below 1258 } 1259 //IOLog("irda setPowerState %d, waited %d ms\n", (int)powerStateOrdinal, (int)counter); 1260 return kIOPMAckImplied; 1261} 1262 1263// handleSetPowerState() 1264// 1265// param0 - the object 1266// param1 - new power state ordinal 1267//static 1268void AppleUSBIrDADriver::handleSetPowerState(thread_call_param_t param0, thread_call_param_t param1 ) 1269{ 1270 AppleUSBIrDADriver *self = OSDynamicCast(AppleUSBIrDADriver, (const OSMetaClassBase *)param0); 1271 uintptr_t powerStateOrdinal = (uintptr_t)param1; 1272 1273 if (self && self->fGate) { 1274 self->fGate->runAction(&(self->setPowerStateGated), (void *)powerStateOrdinal, (void *)0, (void *)0, (void *)0); 1275 self->release(); // offset the retain in setPowerState() 1276 } 1277} 1278 1279// could cast Action directly to setPowerStateGatedPrivate, but not w/out a compiler warning 1280// static 1281IOReturn AppleUSBIrDADriver::setPowerStateGated(OSObject *owner, void *arg0, void *arg1, void *arg2, void *arg3) 1282{ 1283 AppleUSBIrDADriver *self = OSDynamicCast(AppleUSBIrDADriver, (const OSMetaClassBase *)owner); 1284 uintptr_t powerStateOrdinal = (uintptr_t)arg0; 1285 1286 if (self) return self->setPowerStateGatedPrivate(powerStateOrdinal); 1287 else return -1; 1288} 1289 1290// 1291// setPowerStateGatedPrivate - do the work of setPowerState, now that we are on the workloop 1292// 1293IOReturn AppleUSBIrDADriver::setPowerStateGatedPrivate(uintptr_t powerStateOrdinal) 1294{ 1295 fPowerState = powerStateOrdinal; 1296 CheckIrDAState(); 1297 fWaitForGatedCmd = false; // release caller (power thread) 1298 return kIOReturnSuccess; 1299} 1300 1301 1302/****************************************************************************************************/ 1303// 1304// Method: AppleUSBIrDADriver::interruptReadComplete 1305// 1306// Inputs: obj - me, param - parameter block(the Port), rc - return code, remaining - what's left 1307// (whose idea was that?) 1308// 1309// Outputs: None 1310// 1311// Desc: Interrupt pipe read completion routine 1312// 1313/****************************************************************************************************/ 1314 1315void AppleUSBIrDADriver::interruptReadComplete( void *obj, void *param, IOReturn rc, UInt32 remaining ) 1316{ 1317 AppleUSBIrDADriver *me = (AppleUSBIrDADriver*)obj; 1318 //PortInfo_t *port = (PortInfo_t*)param; 1319 IOReturn ior; 1320 UInt32 dLen; 1321 1322 XTRACE(kLogInterruptRead, me->fpinterruptPipeBuffer[0], rc); 1323 if (me->fIrDAOn) { // if we're still "up" and haven't been turned off 1324 check(INTERRUPT_BUFF_SIZE - remaining == 1); 1325 check(me->fpinterruptPipeBuffer[0] == 1); 1326 } 1327 1328 if ( rc == kIOReturnSuccess ) /* If operation returned ok: */ 1329 { 1330 dLen = INTERRUPT_BUFF_SIZE - remaining; 1331 ELG( rc, dLen, 'iRC+', "interruptReadComplete" ); 1332 XTRACE(kLogInterruptRead, 1, dLen); 1333 1334 /* Now look at the data */ 1335// LogData( kUSBAnyDirn, dLen, me->fpinterruptPipeBuffer ); 1336 1337 if (dLen != 1) 1338 { 1339 XTRACE(kLogInterruptRead, 0xdead, 0xbeef); 1340 ELG( 0, dLen, 'iRC-', "interruptReadComplete - what was that?" ); 1341 } else { 1342 1343 if (kUseInterruptsForRead) { // We're using interrupts to trigger reads ... 1344 check(me->fReadActive == false); 1345 if (me->fReadActive == false) { 1346 ior = me->fpInPipe->Read( me->fpPipeInMDP, &me->fReadCompletionInfo, NULL ); // start a read 1347 if (ior != kIOReturnSuccess) 1348 { 1349 ELG( 0, ior, 'icf-', "interrupt complete failed to start read"); 1350 } else { 1351 me->fReadActive = true; 1352 } 1353 } 1354 } 1355 } 1356 1357 /* Queue the next interrupt read: */ 1358 1359 ior = me->fpInterruptPipe->Read( me->fpinterruptPipeMDP, &me->finterruptCompletionInfo, NULL ); 1360 if ( ior == kIOReturnSuccess ) { 1361 XTRACE(kLogInterruptRead, 0xffff, 0xffff); 1362 return; 1363 } 1364 } 1365 1366 /* Read returned with error OR next interrupt read failed to be queued: */ 1367 1368 XTRACE(kLogInterruptRead, 0xdead, 2); 1369 ELG( 0, rc, 'iRC-', "interruptReadComplete - error" ); 1370 1371 return; 1372 1373}/* end interruptReadComplete */ 1374 1375/****************************************************************************************************/ 1376// 1377// Method: AppleUSBIrDADriver::dataReadComplete 1378// 1379// Inputs: obj - me, param - parameter block(the Port), rc - return code, remaining - what's left 1380// 1381// Outputs: None 1382// 1383// Desc: BulkIn pipe (Data interface) read completion routine 1384// 1385/****************************************************************************************************/ 1386 1387void AppleUSBIrDADriver::dataReadComplete( void *obj, void *param, IOReturn rc, UInt32 remaining ) 1388{ 1389 AppleUSBIrDADriver *me = (AppleUSBIrDADriver*)obj; 1390 PortInfo_t *port = (PortInfo_t*)param; 1391 UInt16 dtlength; 1392 IOReturn ior = kIOReturnSuccess; 1393 1394 XTRACE(kLogDataReadComplete, rc, USBLapPayLoad - remaining); 1395 1396#if (hasTracing > 0 && hasAppleUSBIrDATracing > 1) 1397 if (1) { 1398 int len = USBLapPayLoad - remaining; 1399 UInt32 w; 1400 UInt8 *b = me->fPipeInBuffer; 1401 int i; 1402 1403 while (len > 0) { 1404 w = 0; 1405 for (i = 0 ; i < 4; i++) { 1406 w = w << 8; 1407 if (len > 0) // don't run off end (pad w/zeros) 1408 w = w | *b; 1409 b++; 1410 len--; 1411 } 1412 XTRACE(kLogInputData, w >> 16, (short)w); 1413 } 1414 } 1415#endif // tracing high 1416 1417 check(me->fReadActive == true); 1418 1419 if ( rc == kIOReturnSuccess ) /* If operation returned ok: */ 1420 { 1421 me->fReadActive = false; 1422 dtlength = USBLapPayLoad - remaining; 1423 ELG( port->State, dtlength, 'dRC+', "dataReadComplete" ); 1424 1425// LogData( kUSBIn, dtlength, me->fPipeInBuffer ); 1426 1427 if ( dtlength > 1 ) 1428 { 1429 if ( me->fIrDA ) 1430 { 1431 ior = me->fIrDA->ReadComplete( &me->fPipeInBuffer[1], dtlength-1 ); 1432 } 1433 if ( ior != kIOReturnSuccess ) 1434 { 1435 ELG( 0, ior, 'IrR-', "dataReadComplete - IrDA ReadComplete problem" ); 1436 } 1437 } 1438 1439 /* Queue the next read if not using interrupts */ 1440 1441 if (kUseInterruptsForRead == false) { 1442 1443 ior = me->fpInPipe->Read( me->fpPipeInMDP, &me->fReadCompletionInfo, NULL ); 1444 1445 if ( ior == kIOReturnSuccess ) 1446 { 1447 me->fReadActive = true; 1448 me->CheckQueues( port ); 1449 return; 1450 } else { 1451 ELG( 0, ior, 'DtQ-', "dataReadComplete - queueing bulk read failed" ); 1452 } 1453 } 1454 } else { 1455 1456 /* Read returned with error */ 1457 ELG( 0, rc, 'DtR-', "dataReadComplete - io err" ); 1458 } 1459 1460 return; 1461 1462}/* end dataReadComplete */ 1463 1464/****************************************************************************************************/ 1465// 1466// Method: AppleUSBIrDADriver::dataWriteComplete 1467// 1468// Inputs: obj - me, param - parameter block(the Port), rc - return code, remaining - what's left 1469// 1470// Outputs: None 1471// 1472// Desc: BulkOut pipe (Data interface) write completion routine 1473// 1474/****************************************************************************************************/ 1475 1476void AppleUSBIrDADriver::dataWriteComplete( void *obj, void *param, IOReturn rc, UInt32 remaining ) 1477{ 1478 AppleUSBIrDADriver *me = (AppleUSBIrDADriver*)obj; 1479 Boolean done = true; // write really finished? 1480 1481 ELG( rc, (me->fCount - remaining), 'dWCt', "dataWriteComplete" ); 1482 XTRACE(kLogDataWriteComplete, rc, me->fCount - remaining); 1483 1484 check(me->fWriteActive); 1485 me->fWriteActive = false; 1486 1487 // first check for speed change, it's the only time we do a single-byte write 1488 if (me->fCount == 1) { 1489 if (me->fIrDA) 1490 me->fIrDA->SetSpeedComplete(rc == kIOReturnSuccess); 1491 return; 1492 } 1493 1494 // in a transmit complete, but need to manually transmit a zero-length packet 1495 // if it's a multiple of the max usb packet size for the bulk-out pipe (64 bytes) 1496 if ( rc == kIOReturnSuccess ) /* If operation returned ok: */ 1497 { 1498 if ( me->fCount > 0 ) // Check if it was not a zero length write 1499 { 1500 if ( (me->fCount % 64) == 0 ) // If was a multiple of 64 bytes then we need to do a zero length write 1501 { 1502 XTRACE(kLogDataWriteCompleteZero, 0, 0); 1503 LogData( kUSBOut, 0, me->fPipeOutBuffer ); 1504 me->fWriteActive = true; 1505 me->fpPipeOutMDP->setLength( 0 ); 1506 me->fCount = 0; 1507 me->fpOutPipe->Write( me->fpPipeOutMDP, &me->fWriteCompletionInfo ); 1508 done = false; // don't complete back to irda quite yet 1509 } 1510 } 1511 } 1512 1513 if (done && me->fIrDA ) // if time to let irda know the write has finished 1514 { 1515 me->fIrDA->Transmit_Complete( rc == kIOReturnSuccess ); // let IrDA know how write finished 1516 } 1517 return; 1518 1519}/* end dataWriteComplete */ 1520 1521/****************************************************************************************************/ 1522// 1523// Method: AppleUSBIrDADriver::free 1524// 1525// Inputs: None 1526// 1527// Outputs: None 1528// 1529// Desc: Clean up and free the log 1530// 1531/****************************************************************************************************/ 1532 1533void AppleUSBIrDADriver::free() 1534{ 1535 XTRACE(kLogFree, 0, 0); 1536 ELG( 0, 0, 'free', "free" ); 1537 1538 if (fIrDA) { 1539 fIrDA->release(); // we don't do delete's in the kernal I suppose ... 1540 fIrDA=NULL; 1541 } 1542 1543 if (fPowerThreadCall) { 1544 thread_call_free(fPowerThreadCall); 1545 fPowerThreadCall = NULL; 1546 } 1547 1548 if (fGate) { 1549 IOWorkLoop *work = getWorkLoop(); 1550 if (work) work->removeEventSource(fGate); 1551 fGate->release(); 1552 fGate = NULL; 1553 } 1554 1555 1556#if USE_ELG 1557 if ( g.evLogBuf ) 1558 IOFree( g.evLogBuf, kEvLogSize ); 1559#endif /* USE_ELG */ 1560 1561 super::free(); 1562 1563 XTRACE(kLogFree, 0xffff, 0xffff); 1564 return; 1565 1566}/* end free */ 1567 1568/****************************************************************************************************/ 1569// 1570// Method: AppleUSBIrDADriver::stop 1571// 1572// Inputs: provider - my provider 1573// 1574// Outputs: None 1575// 1576// Desc: Stops 1577// 1578/****************************************************************************************************/ 1579 1580void AppleUSBIrDADriver::stop( IOService *provider ) 1581{ 1582 XTRACE(kLogStop, 0, provider); 1583 ELG( 0, 0, 'stop', "stop" ); 1584 1585 fUSBStarted = false; // reset usb start/stop flag for CheckIrDAState 1586 CheckIrDAState(); // turn irda off, release resources 1587 1588 destroySerialStream(); // release the bsd tty 1589 1590 destroyNub(); // delete the nubs and fPort 1591 1592 if ( fpInterface ) 1593 { 1594 fpInterface->release(); // retain done in ConfigureDevice 1595 fpInterface = NULL; 1596 } 1597 1598 // release our power manager state 1599 PMstop(); 1600 1601 super::stop( provider ); 1602 XTRACE(kLogStop, 0xffff, 0xffff); 1603 return; 1604 1605}/* end stop */ 1606 1607/****************************************************************************************************/ 1608// 1609// Method: AppleUSBIrDADriver::allocateResources 1610// 1611// Inputs: 1612// 1613// Outputs: return code - true (allocate was successful), false (it failed) 1614// 1615// Desc: Finishes up the rest of the configuration and gets all the endpoints open 1616// 1617/****************************************************************************************************/ 1618 1619bool AppleUSBIrDADriver::allocateResources( void ) 1620{ 1621 IOUSBFindEndpointRequest epReq; // endPoint request struct on stack 1622 bool goodCall; // return flag fm Interface call 1623 1624 ELG( 0, 0, 'Allo', "allocateResources." ); 1625 XTRACE(kLogAllocateResources, 0, 0); 1626 1627 // Open all the end points 1628 require(fpInterface, Fail); 1629 1630 goodCall = fpInterface->open( this ); // close done in releaseResources 1631 if ( !goodCall ) 1632 { 1633 ELG( 0, 0, 'epD-', "allocateResources - open data interface failed." ); 1634 fpInterface->release(); 1635 fpInterface = NULL; 1636 return false; 1637 } 1638 1639 fpInterfaceNumber = fpInterface->GetInterfaceNumber(); 1640 1641 epReq.type = kUSBBulk; 1642 epReq.direction = kUSBIn; 1643 epReq.maxPacketSize = 0; 1644 epReq.interval = 0; 1645 fpInPipe = fpInterface->FindNextPipe( 0, &epReq ); 1646 require(fpInPipe, Fail); 1647 ELG( epReq.maxPacketSize << 16 |epReq.interval, fpInPipe, 'i P+', "allocateResources - bulk input pipe." ); 1648 1649 epReq.direction = kUSBOut; 1650 fpOutPipe = fpInterface->FindNextPipe( 0, &epReq ); 1651 require(fpOutPipe, Fail); 1652 ELG( epReq.maxPacketSize << 16 |epReq.interval, fpOutPipe, 'o P+', "allocateResources - bulk output pipe." ); 1653 1654 epReq.type = kUSBInterrupt; 1655 epReq.direction = kUSBIn; 1656 fpInterruptPipe = fpInterface->FindNextPipe( 0, &epReq ); 1657 require(fpInterruptPipe, Fail); 1658 ELG( epReq.maxPacketSize << 16 |epReq.interval, fpInterruptPipe, 'irP+', "allocateResources - interrupt pipe." ); 1659 1660 // Allocate Memory Descriptor Pointer with memory for the interrupt-in pipe: 1661 1662 fpinterruptPipeMDP = IOBufferMemoryDescriptor::withCapacity( INTERRUPT_BUFF_SIZE, kIODirectionIn ); 1663 require(fpinterruptPipeMDP, Fail); 1664 1665 fpinterruptPipeMDP->setLength( INTERRUPT_BUFF_SIZE ); 1666 fpinterruptPipeBuffer = (UInt8*)fpinterruptPipeMDP->getBytesNoCopy(); 1667 ELG( 0, fpinterruptPipeBuffer, 'iBuf', "allocateResources - interrupt in buffer" ); 1668 1669 // Allocate Memory Descriptor Pointer with memory for the data-in bulk pipe: 1670 1671 fpPipeInMDP = IOBufferMemoryDescriptor::withCapacity( USBLapPayLoad, kIODirectionIn ); 1672 require(fpPipeInMDP, Fail); 1673 1674 fpPipeInMDP->setLength( USBLapPayLoad ); 1675 fPipeInBuffer = (UInt8*)fpPipeInMDP->getBytesNoCopy(); 1676 ELG( 0, fPipeInBuffer, 'iBuf', "allocateResources - input buffer" ); 1677 1678 // Allocate Memory Descriptor Pointer with memory for the data-out bulk pipe: 1679 1680 fpPipeOutMDP = IOBufferMemoryDescriptor::withCapacity( MAX_BLOCK_SIZE, kIODirectionOut ); 1681 require(fpPipeOutMDP, Fail); 1682 1683 fpPipeOutMDP->setLength( MAX_BLOCK_SIZE ); 1684 fPipeOutBuffer = (UInt8*)fpPipeOutMDP->getBytesNoCopy(); 1685 ELG( 0, fPipeOutBuffer, 'oBuf', "allocateResources - output buffer" ); 1686 1687 // set up the completion info for all three pipes 1688 1689 require(fPort, Fail); 1690 finterruptCompletionInfo.target = this; 1691 finterruptCompletionInfo.action = interruptReadComplete; 1692 finterruptCompletionInfo.parameter = fPort; 1693 1694 fReadCompletionInfo.target = this; 1695 fReadCompletionInfo.action = dataReadComplete; 1696 fReadCompletionInfo.parameter = fPort; 1697 1698 fWriteCompletionInfo.target = this; 1699 fWriteCompletionInfo.action = dataWriteComplete; 1700 fWriteCompletionInfo.parameter = fPort; 1701 1702 1703 ELG( 0, 0, 'aRs+', "allocateResources successful" ); 1704 return true; 1705 1706Fail: 1707 return false; 1708 1709} // allocateResources 1710 1711 1712/****************************************************************************************************/ 1713// 1714// Method: AppleUSBIrDADriver::releaseResources 1715// 1716// Inputs: port - the Port 1717// 1718// Outputs: None 1719// 1720// Desc: Frees up the pipe resources allocated in allocateResources 1721// 1722/****************************************************************************************************/ 1723 1724void AppleUSBIrDADriver::releaseResources( void ) 1725{ 1726 ELG( 0, 0, 'rlRs', "releaseResources" ); 1727 XTRACE(kLogReleaseResources, 0, 0); 1728 1729 if ( fpInterface ) 1730 { 1731 fpInterface->close( this ); 1732 } 1733 1734 if ( fpPipeOutMDP ) 1735 { 1736 fpPipeOutMDP->release(); 1737 fpPipeOutMDP = 0; 1738 } 1739 1740 if ( fpPipeInMDP ) 1741 { 1742 fpPipeInMDP->release(); 1743 fpPipeInMDP = 0; 1744 } 1745 1746 if ( fpinterruptPipeMDP ) 1747 { 1748 fpinterruptPipeMDP->release(); 1749 fpinterruptPipeMDP = 0; 1750 } 1751 1752 return; 1753 1754}/* end releaseResources */ 1755 1756// 1757// start reading on the pipes 1758// 1759bool AppleUSBIrDADriver::startPipes( void ) 1760{ 1761 IOReturn rtn; 1762 1763 require(fPort, Fail); 1764 require(fpinterruptPipeMDP, Fail); 1765 require(fpPipeInMDP, Fail); 1766 require(fpPipeOutMDP, Fail); 1767 1768 1769 if (kUseInterruptsForRead) { // read on interrupt pipe if using interrupts 1770 rtn = fpInterruptPipe->Read(fpinterruptPipeMDP, &finterruptCompletionInfo, NULL ); 1771 } 1772 else { // Read the data-in bulk pipe if not using interrupts 1773 rtn = fpInPipe->Read(fpPipeInMDP, 1000, 1000, &fReadCompletionInfo, NULL ); 1774 } 1775 require(rtn == kIOReturnSuccess, Fail); 1776 1777 // is this really referenced by anyone?? 1778 fReadActive = (kUseInterruptsForRead == false); // remember if we did a read 1779 1780 return true; 1781 1782Fail: 1783 return false; 1784}/* end startPipes */ 1785 1786// 1787// stop i/o on the pipes 1788// 1789void AppleUSBIrDADriver::stopPipes() 1790{ 1791 if (fpInPipe) fpInPipe->Abort(); 1792 if (fpOutPipe) fpOutPipe->Abort(); 1793 if (fpInterruptPipe) fpInterruptPipe->Abort(); 1794} 1795 1796 1797/****************************************************************************************************/ 1798// 1799// Method: AppleUSBIrDADriver::configureDevice 1800// 1801// Inputs: numConfigs - number of configurations present 1802// 1803// Outputs: return Code - true (device configured), false (device not configured) 1804// 1805// Desc: Finds the configurations and then the appropriate interfaces etc. 1806// 1807/****************************************************************************************************/ 1808 1809bool AppleUSBIrDADriver::configureDevice( UInt8 numConfigs ) 1810{ 1811 IOUSBFindInterfaceRequest req; // device request Class on stack 1812 const IOUSBConfigurationDescriptor *cd = NULL; // configuration descriptor 1813 IOUSBInterfaceDescriptor *intf = NULL; // interface descriptor 1814 IOReturn ior; 1815 UInt8 cval; 1816 UInt8 config = 0; 1817 USBIrDAQoS *qos; 1818 1819 ELG( 0, numConfigs, 'cDev', "configureDevice" ); 1820 XTRACE(kLogConfigureDevice, 0, 0); 1821 1822 for (cval=0; cval<numConfigs; cval++) 1823 { 1824 ELG( 0, cval, 'CkCn', "configureDevice - Checking Configuration" ); 1825 1826 cd = fpDevice->GetFullConfigurationDescriptor(cval); 1827 if ( !cd ) 1828 { 1829 ELG( 0, 0, 'GFC-', "configureDevice - Error getting the full configuration descriptor" ); 1830 } else { 1831 1832 // Find the first one - there may be more to go on in the future 1833 1834 req.bInterfaceClass = kIOUSBFindInterfaceDontCare; 1835 req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; 1836 req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; 1837 req.bAlternateSetting = kIOUSBFindInterfaceDontCare; 1838 ior = fpDevice->FindNextInterfaceDescriptor(cd, intf, &req, &intf); 1839 if ( ior == kIOReturnSuccess ) 1840 { 1841 if ( intf ) 1842 { 1843 config = cd->bConfigurationValue; 1844 ELG( cd, config, 'FNI+', "configureDevice - Interface descriptor found" ); 1845 break; 1846 } else { 1847 ELG( 0, config, 'FNI-', "configureDevice - That's weird the interface was null" ); 1848 cd = NULL; 1849 } 1850 } else { 1851 ELG( 0, cval, 'FNID', "configureDevice - No CDC interface found this configuration" ); 1852 cd = NULL; 1853 } 1854 } 1855 } 1856 1857 if ( !cd ) 1858 { 1859 return false; 1860 } 1861 1862 // Now lets do it for real 1863 1864 req.bInterfaceClass = kIOUSBFindInterfaceDontCare; 1865 req.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; 1866 req.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; 1867 req.bAlternateSetting = kIOUSBFindInterfaceDontCare; 1868 1869 fpInterface = fpDevice->FindNextInterface( NULL, &req ); 1870 if ( !fpInterface ) 1871 { 1872 ELG( 0, 0, 'FIC-', "configureDevice - Find next interface failed" ); 1873 return false; 1874 } 1875 fpInterface->retain(); // release done in stop() 1876 1877 // Get the QoS Functional Descriptor (it's the only one) 1878 1879 qos = (USBIrDAQoS *)fpInterface->FindNextAssociatedDescriptor(NULL, USBIrDAClassDescriptor); 1880 if (!qos) 1881 { 1882 ELG( 0, 0, 'OSF-', "configureDevice - No QOS descriptor" ); 1883 1884 /* Set some defaults - qos values need tuning of course */ 1885 1886 fQoS.bFunctionLength = 12; 1887 fQoS.bDescriptorType = USBIrDAClassDescriptor; 1888 fQoS.version = 0x100; 1889 fQoS.datasize = 0x1f; // 1k = 1f, 2k = 3f 1890 fQoS.windowsize = 1; 1891 fQoS.minturn = 2; // review & tune. 1892 fQoS.baud1 = 0x01; // 4mbit no mir, all sir 1893 fQoS.baud2 = 0x3e; 1894 fQoS.bofs = 4; // review and tune. 1895 fQoS.sniff = 0; 1896 fQoS.unicast = 0; 1897 } else { 1898 ELG( qos->bDescriptorType, qos, 'QSFD', "AppleUSBCDCDriver::configureDevice - Got QoS Functional Descriptor" ); 1899 1900 /* Save the real values */ 1901 1902 fQoS.bFunctionLength = qos->bFunctionLength; 1903 fQoS.bDescriptorType = qos->bDescriptorType; 1904 fQoS.version = USBToHostWord(qos->version); 1905 fQoS.datasize = qos->datasize; 1906 fQoS.windowsize = qos->windowsize; 1907 fQoS.minturn = qos->minturn; 1908 fQoS.baud1 = qos->baud2; // flipped because of our good friends at you know who 1909 fQoS.baud2 = qos->baud1; 1910 fQoS.bofs = qos->bofs; 1911 fQoS.sniff = qos->sniff; 1912 fQoS.unicast = qos->unicast; 1913 } 1914 1915 1916 // irda starts up turned off so always try and suspend the hardware 1917 ior = fpDevice->SuspendDevice( true ); // Suspend the device 1918 require(ior == kIOReturnSuccess, Fail); 1919 1920 return true; 1921 1922Fail: 1923 return false; 1924 1925}/* end configureDevice */ 1926 1927/****************************************************************************************************/ 1928// 1929// Method: AppleUSBIrDADriver::createSuffix 1930// 1931// Inputs: None 1932// 1933// Outputs: return Code - true (suffix created), false (suffix not create), sufKey - the key 1934// 1935// Desc: Creates the suffix key. It attempts to use the serial number string from the device 1936// if it's reasonable i.e. less than 8 bytes ascii. Remember it's stored in unicode 1937// format. If it's not present or not reasonable it will generate the suffix based 1938// on the location property tag. At least this remains the same across boots if the 1939// device is plugged into the same physical location. In the latter case trailing 1940// zeros are removed. 1941// 1942/****************************************************************************************************/ 1943 1944bool AppleUSBIrDADriver::createSuffix( unsigned char *sufKey, int sufMaxLen ) 1945{ 1946 1947 IOReturn rc; 1948 UInt8 serBuf[10]; // arbitrary size > 8 1949 OSNumber *location; 1950 UInt32 locVal; 1951 UInt8 *rlocVal; 1952 UInt16 offs, i, sig = 0; 1953 UInt8 indx; 1954 bool keyOK = false; 1955 1956 ELG( 0, 0, 'cSuf', "createSuffix" ); 1957 1958 indx = fpDevice->GetSerialNumberStringIndex(); 1959 if (indx != 0 ) 1960 { 1961 // Generate suffix key based on the serial number string (if reasonable <= 8 and > 0) 1962 1963 rc = fpDevice->GetStringDescriptor(indx, (char *)&serBuf, sizeof(serBuf)); 1964 if ( !rc ) 1965 { 1966 if ( (strlen((char *)&serBuf) < 9) && (strlen((char *)&serBuf) > 0) ) 1967 { 1968 strlcpy( (char *)sufKey, (const char *)&serBuf, sufMaxLen); 1969 keyOK = true; 1970 } 1971 } else { 1972 ELG( 0, rc, 'Sdt-', "createSuffix error reading serial number string" ); 1973 } 1974 } 1975 1976 if ( !keyOK ) 1977 { 1978 // Generate suffix key based on the location property tag 1979 1980 location = (OSNumber *)fpDevice->getProperty(kUSBDevicePropertyLocationID); 1981 if ( location ) 1982 { 1983 locVal = location->unsigned32BitValue(); 1984 offs = 0; 1985 rlocVal = (UInt8*)&locVal; 1986 for (i=0; i<4; i++) 1987 { 1988 sufKey[offs] = Asciify(rlocVal[i] >> 4); 1989 if ( sufKey[offs++] != '0') 1990 sig = offs; 1991 sufKey[offs] = Asciify(rlocVal[i]); 1992 if ( sufKey[offs++] != '0') 1993 sig = offs; 1994 } 1995 sufKey[sig] = 0x00; 1996 keyOK = true; 1997 } 1998 } 1999 2000 return keyOK; 2001 2002}/* end createSuffix */ 2003 2004/****************************************************************************************************/ 2005// 2006// Method: AppleUSBIrDADriver::createSerialStream 2007// 2008// Inputs: None 2009// 2010// Outputs: return Code - true (created and initialilzed ok), false (it failed) 2011// 2012// Desc: Creates and initializes the nub and port structure 2013// 2014/****************************************************************************************************/ 2015 2016bool AppleUSBIrDADriver::createSerialStream() 2017{ 2018 UInt8 indx; 2019 IOReturn rc; 2020 unsigned char suffix[10]; 2021 2022 ELG( 0, fNub, '=Nub', "createSerialStream" ); 2023 XTRACE(kLogCreateSerialStream, 0, 0); 2024 2025 check(fNub && fPort); 2026 if (!fNub || !fPort) return false; 2027 2028 SetStructureDefaults( fPort, true ); // init the Port structure 2029 2030 // Allocate the request lock 2031 fPort->serialRequestLock = IOLockAlloc(); // init lock used to protect code on MP 2032 if ( !fPort->serialRequestLock ) { 2033 return false; 2034 } 2035 2036 // now the ring buffers 2037 if (!allocateRingBuffer(&(fPort->TX), fPort->TXStats.BufferSize) || 2038 !allocateRingBuffer(&(fPort->RX), fPort->RXStats.BufferSize)) 2039 { 2040 return false; 2041 } 2042 2043 2044 if ( !fTerminate ) 2045 { 2046 // Report the base name to be used for generating device nodes 2047 2048 fNub->setProperty( kIOTTYBaseNameKey, baseName ); 2049 2050 // Create suffix key and set it 2051 2052 if ( createSuffix(suffix, sizeof(suffix) ) ) 2053 { 2054 fNub->setProperty( kIOTTYSuffixKey, (const char *)suffix ); 2055 } 2056 2057 2058 // Save the Product String (at least the first productNameLength's worth). 2059 2060 indx = fpDevice->GetProductStringIndex(); 2061 if ( indx != 0 ) 2062 { 2063 rc = fpDevice->GetStringDescriptor( indx, (char *)&fProductName, sizeof(fProductName) ); 2064 if ( !rc ) 2065 { 2066 if ( strlen((char *)fProductName) == 0 ) // believe it or not this sometimes happens (null string with an index defined???) 2067 { 2068 strlcpy( (char *)fProductName, defaultName, sizeof(fProductName)); 2069 } 2070 fNub->setProperty( (const char *)propertyTag, (const char *)fProductName ); 2071 } 2072 } 2073 2074 fNub->registerService(); 2075 } 2076 2077 return true; 2078 2079}/* end createSerialStream */ 2080 2081// 2082// release things created in createSerialStream 2083// 2084void 2085AppleUSBIrDADriver::destroySerialStream(void) 2086{ 2087 require(fPort, Fail); 2088 2089 if ( fPort->serialRequestLock ) 2090 { 2091 IOLockFree( fPort->serialRequestLock ); // free the Serial Request Lock 2092 fPort->serialRequestLock = NULL; 2093 } 2094 2095 // Remove all the buffers. 2096 2097 freeRingBuffer( &fPort->TX ); 2098 freeRingBuffer( &fPort->RX ); 2099 2100 removeProperty( (const char *)propertyTag ); // unhook from BSD 2101 2102Fail: 2103 return; 2104} 2105 2106// 2107// startIrDA 2108// 2109// assumes createSerialStream is called once at usb start time 2110// calls allocateResources to open endpoints 2111// 2112bool 2113AppleUSBIrDADriver::startIrDA() 2114{ 2115 bool ok; 2116 2117 require(fIrDA == NULL, Fail); 2118 require(fNub, Fail); 2119 require(fUserClientNub, Fail); 2120 2121 Workaround(); // make chip as sane as can be 2122 2123 ok = allocateResources(); // open the pipe endpoints 2124 require(ok, Fail); 2125 2126 startPipes(); // start reading on the usb pipes 2127 2128 fBaudCode = kLinkSpeed9600; // the code for 9600 (see BaudRate above) 2129 fLastChangeByte = 0; // no known state of device, force mode to change on first i/o 2130 fCurrentBaud = 9600; 2131 SetBofCount(10); // start with about 10 bofs (sets fBofsCode) 2132 2133 fIrDA = IrDAComm::irDAComm(fNub, fUserClientNub); // create and init and start IrDA 2134 require(fIrDA, Fail); 2135 2136 return true; 2137 2138Fail: 2139 return false; 2140} 2141 2142void 2143AppleUSBIrDADriver::stopIrDA() 2144{ 2145 require(fIrDA, Fail); 2146 2147 fIrDA->Stop(); 2148 fIrDA->release(); 2149 fIrDA = NULL; 2150 2151 stopPipes(); // stop reading on the usb pipes 2152 2153 if (fpPipeOutMDP != NULL) // better test for releaseResources? 2154 releaseResources( ); 2155 2156Fail: 2157 return; 2158} 2159 2160/****************************************************************************************************/ 2161// 2162// Method: AppleUSBIrDADriver::createNub 2163// 2164// Inputs: 2165// 2166// Outputs: fNub (an AppleUSBIrDA glue object) and fPort 2167// 2168// Desc: allocates and inits, but doesn't publish the BSD info on the nub yet 2169// create serial stream finishes the job later. 2170// 2171/****************************************************************************************************/ 2172bool 2173AppleUSBIrDADriver::createNub(void) 2174{ 2175 bool ret; 2176 2177 if (fNub == NULL) { 2178 fNub = new AppleUSBIrDA; 2179 } 2180 require(fNub, Failed); 2181 check(fNub->getRetainCount() == 1); // testing 2182 2183 if (fPort == NULL) { 2184 fPort = (PortInfo_t*)IOMalloc( sizeof(PortInfo_t) ); 2185 } 2186 require(fPort, Failed); 2187 bzero(fPort, sizeof(PortInfo_t)); 2188 2189 ret = fNub->init(0, fPort); 2190 require(ret == true, Failed); 2191 2192 ret = fNub->attach( this ); 2193 require(ret == true, Failed); 2194 check(fNub->getRetainCount() == 2); // testing 2195 2196 XTRACE(kLogNewNub, 0, fNub); 2197 XTRACE(kLogNewPort, 0, fPort); 2198 2199 // now make the nub to act as a communication point for user-client 2200 if (fUserClientNub == NULL) 2201 fUserClientNub = AppleIrDA::withNub(fNub); // it talks to the serial nub ... 2202 require(fUserClientNub, Failed); 2203 2204 fUserClientNub->attach(this); 2205 2206 return true; 2207 2208Failed: 2209 IOLog("Create nub failed\n"); 2210 // could try and clean up here, but let's start by just not crashing. 2211 return false; 2212} 2213 2214void AppleUSBIrDADriver::destroyNub() 2215{ 2216 if (fPort != NULL) { 2217 IOFree( fPort, sizeof(PortInfo_t) ); 2218 fPort = NULL; 2219 } 2220 2221 if (fUserClientNub) { 2222 XTRACE(kLogDestroyNub, 1, fUserClientNub->getRetainCount()); 2223 fUserClientNub->detach(this); 2224 fUserClientNub->release(); 2225 fUserClientNub = NULL; 2226 } 2227 2228 if (fNub) { 2229 XTRACE(kLogDestroyNub, 2, fNub->getRetainCount()); 2230 fNub->detach(this); 2231 fNub->release(); // crash boom? 2232 fNub = NULL; 2233 } 2234} 2235 2236/****************************************************************************************************/ 2237// 2238// Method: AppleUSBIrDADriver::acquirePort 2239// 2240// Inputs: sleep - true (wait for it), false (don't), refCon - the Port 2241// 2242// Outputs: Return Code - kIOReturnSuccess, kIOReturnExclusiveAccess, kIOReturnIOError and various others 2243// 2244// Desc: acquirePort tests and sets the state of the port object. If the port was 2245// available, then the state is set to busy, and kIOReturnSuccess is returned. 2246// If the port was already busy and sleep is YES, then the thread will sleep 2247// until the port is freed, then re-attempts the acquire. If the port was 2248// already busy and sleep is NO, then kIOReturnExclusiveAccess is returned. 2249// 2250/****************************************************************************************************/ 2251 2252IOReturn AppleUSBIrDADriver::acquirePort( bool sleep, void *refCon ) 2253{ 2254 PortInfo_t *port = (PortInfo_t *) refCon; 2255 UInt32 busyState = 0; 2256 IOReturn rtn = kIOReturnSuccess; 2257 2258 ELG( port, sleep, 'acqP', "acquirePort" ); 2259 XTRACE(kLogAcquirePort, 0, 0); 2260 2261 if ( fTerminate ) { 2262 //int review_fTerminate; 2263 //return kIOReturnOffline; 2264 } 2265 SetStructureDefaults( port, FALSE ); /* Initialize all the structures */ 2266 2267 for (;;) 2268 { 2269 busyState = readPortState( port ) & PD_S_ACQUIRED; 2270 if ( !busyState ) 2271 { 2272 // Set busy bit, and clear everything else 2273 changeState( port, (UInt32)PD_S_ACQUIRED | DEFAULT_STATE, (UInt32)STATE_ALL); 2274 break; 2275 } else { 2276 if ( !sleep ) 2277 { 2278 ELG( 0, 0, 'busy', "acquirePort - Busy exclusive access" ); 2279 return kIOReturnExclusiveAccess; 2280 } else { 2281 busyState = 0; 2282 rtn = watchState( &busyState, PD_S_ACQUIRED, refCon ); 2283 if ( (rtn == kIOReturnIOError) || (rtn == kIOReturnSuccess) ) 2284 { 2285 continue; 2286 } else { 2287 ELG( 0, 0, 'int-', "acquirePort - Interrupted!" ); 2288 return rtn; 2289 } 2290 } 2291 } 2292 } /* end for */ 2293 2294 fSessions++; //bump number of active sessions and turn on clear to send 2295 changeState( port, PD_RS232_S_CTS, PD_RS232_S_CTS); 2296 2297 CheckIrDAState(); // turn irda on/off if appropriate 2298 2299 if (1) { // wait for initial connect 2300 int counter = 0; 2301 //while (fIrDA && fIrDA->Starting()) { 2302 while (counter++ < (10 * 10)) { // sanity check limit of 10 seconds 2303 if (fIrDA && (fIrDA->Starting() == false)) break; 2304 XTRACE(kLogAcquirePort, counter, 1); 2305 IOSleep(100); // wait 1/10 of a second between polls and yield time 2306 } 2307 //IOLog("AppleUSBIrDA: acquire port paused %d ms for initial connection\n", counter*100); 2308 } 2309 2310 return rtn; 2311 2312}/* end acquirePort */ 2313 2314/****************************************************************************************************/ 2315// 2316// Method: AppleUSBIrDADriver::releasePort 2317// 2318// Inputs: refCon - the Port 2319// 2320// Outputs: Return Code - kIOReturnSuccess or kIOReturnNotOpen 2321// 2322// Desc: releasePort returns all the resources and does clean up. 2323// 2324/****************************************************************************************************/ 2325 2326IOReturn AppleUSBIrDADriver::releasePort( void *refCon ) 2327{ 2328 PortInfo_t *port = (PortInfo_t *) refCon; 2329 UInt32 busyState; 2330 2331 ELG( 0, port, 'relP', "releasePort" ); 2332 XTRACE(kLogReleasePort, 0, 0); 2333 2334 busyState = (readPortState( port ) & PD_S_ACQUIRED); 2335 if ( !busyState ) 2336 { 2337 ELG( 0, 0, 'rlP-', "releasePort - NOT OPEN" ); 2338 return kIOReturnNotOpen; 2339 } 2340 2341 changeState( port, 0, (UInt32)STATE_ALL ); // Clear the entire state word which also deactivates the port 2342 2343 fSessions--; // reduce number of active sessions 2344 CheckIrDAState(); // turn irda off if appropriate 2345 2346 if ((fTerminate) && (fSessions == 0)) // if it's the result of a terminate and session count is zero we also need to close things 2347 { 2348 if (0 && fpInterface ) // jdg - this was bogus 2349 { 2350 fpInterface->close( this ); 2351 fpInterface->release(); 2352 fpInterface = NULL; 2353 } 2354 // else IOLog("appleusbirda - would have released fpInteface here\n"); 2355 } 2356 2357 ELG( 0, 0, 'RlP+', "releasePort - OK" ); 2358 2359 return kIOReturnSuccess; 2360 2361}/* end releasePort */ 2362 2363/****************************************************************************************************/ 2364// 2365// Method: AppleUSBIrDADriver::setState 2366// 2367// Inputs: state - state to set, mask - state mask, refCon - the Port 2368// 2369// Outputs: Return Code - kIOReturnSuccess or kIOReturnBadArgument 2370// 2371// Desc: Set the state for the port device. The lower 16 bits are used to set the 2372// state of various flow control bits (this can also be done by enqueueing a 2373// PD_E_FLOW_CONTROL event). If any of the flow control bits have been set 2374// for automatic control, then they can't be changed by setState. For flow 2375// control bits set to manual (that are implemented in hardware), the lines 2376// will be changed before this method returns. The one weird case is if RXO 2377// is set for manual, then an XON or XOFF character may be placed at the end 2378// of the TXQ and transmitted later. 2379// 2380/****************************************************************************************************/ 2381 2382IOReturn AppleUSBIrDADriver::setState( UInt32 state, UInt32 mask, void *refCon ) 2383{ 2384 PortInfo_t *port = (PortInfo_t *) refCon; 2385 2386 ELG( state, mask, 'stSt', "setState" ); 2387 XTRACE(kLogSetState, 0, 0); 2388 2389 if ( mask & (PD_S_ACQUIRED | PD_S_ACTIVE | (~EXTERNAL_MASK)) ) 2390 return kIOReturnBadArgument; 2391 2392 if ( readPortState( port ) & PD_S_ACQUIRED ) 2393 { 2394 // ignore any bits that are read-only 2395 mask &= (~port->FlowControl & PD_RS232_A_MASK) | PD_S_MASK; 2396 2397 if ( mask) 2398 changeState( port, state, mask ); 2399 2400 return kIOReturnSuccess; 2401 } 2402 2403 return kIOReturnNotOpen; 2404 2405}/* end setState */ 2406 2407/****************************************************************************************************/ 2408// 2409// Method: AppleUSBIrDADriver::getState 2410// 2411// Inputs: refCon - the Port 2412// 2413// Outputs: state - port state 2414// 2415// Desc: Get the state for the port. 2416// 2417/****************************************************************************************************/ 2418 2419UInt32 AppleUSBIrDADriver::getState( void *refCon ) 2420{ 2421 PortInfo_t *port = (PortInfo_t *) refCon; 2422 UInt32 state; 2423 2424 ELG( 0, port, 'gtSt', "getState" ); 2425 2426 CheckQueues( port ); 2427 2428 state = readPortState( port ) & EXTERNAL_MASK; 2429 2430 ELG( state, EXTERNAL_MASK, 'gtS-', "getState-->State" ); 2431 XTRACE(kLogGetState, state >> 16, (short)state); 2432 2433 return state; 2434 2435}/* end getState */ 2436 2437/****************************************************************************************************/ 2438// 2439// Method: AppleUSBIrDADriver::watchState 2440// 2441// Inputs: state - state to watch for, mask - state mask bits, refCon - the Port 2442// 2443// Outputs: Return Code - kIOReturnSuccess or value returned from ::watchState 2444// 2445// Desc: Wait for the at least one of the state bits defined in mask to be equal 2446// to the value defined in state. Check on entry then sleep until necessary, 2447// see watchState for more details. 2448// 2449/****************************************************************************************************/ 2450 2451IOReturn AppleUSBIrDADriver::watchState( UInt32 *state, UInt32 mask, void *refCon) 2452{ 2453 PortInfo_t *port = (PortInfo_t *) refCon; 2454 IOReturn ret = kIOReturnNotOpen; 2455 2456 ELG( *state, mask, 'WatS', "watchState" ); 2457 XTRACE(kLogWatchState, 0, 0); 2458 2459 if ( readPortState( port ) & PD_S_ACQUIRED ) 2460 { 2461 ret = kIOReturnSuccess; 2462 mask &= EXTERNAL_MASK; 2463 ret = privateWatchState( port, state, mask ); 2464 *state &= EXTERNAL_MASK; 2465 } 2466 2467 ELG( ret, 0, 'WatS', "watchState --> watchState" ); 2468 XTRACE(kLogWatchState, 0xffff, 0xffff); 2469 return ret; 2470 2471}/* end watchState */ 2472 2473/****************************************************************************************************/ 2474// 2475// Method: AppleUSBIrDADriver::nextEvent 2476// 2477// Inputs: refCon - the Port 2478// 2479// Outputs: Return Code - kIOReturnSuccess 2480// 2481// Desc: Not used by this driver. 2482// 2483/****************************************************************************************************/ 2484 2485UInt32 AppleUSBIrDADriver::nextEvent( void *refCon ) 2486{ 2487 UInt32 ret = kIOReturnSuccess; 2488 2489 ELG( 0, 0, 'NxtE', "nextEvent" ); 2490 2491 return ret; 2492 2493}/* end nextEvent */ 2494 2495/****************************************************************************************************/ 2496// 2497// Method: AppleUSBIrDADriver::executeEvent 2498// 2499// Inputs: event - The event, data - any data associated with the event, refCon - the Port 2500// 2501// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen or kIOReturnBadArgument 2502// 2503// Desc: executeEvent causes the specified event to be processed immediately. 2504// This is primarily used for channel control commands like START & STOP 2505// 2506/****************************************************************************************************/ 2507 2508IOReturn AppleUSBIrDADriver::executeEvent( UInt32 event, UInt32 data, void *refCon ) 2509{ 2510 PortInfo_t *port = (PortInfo_t *) refCon; 2511 IOReturn ret = kIOReturnSuccess; 2512 UInt32 state, delta; 2513 2514 delta = 0; 2515 state = readPortState( port ); 2516 ELG( port, state, 'ExIm', "executeEvent" ); 2517 XTRACE(kLogExecEvent, event >> 16, (short)event); 2518 XTRACE(kLogExecEventData, data >> 16, (short)data); 2519 2520 if ( (state & PD_S_ACQUIRED) == 0 ) 2521 return kIOReturnNotOpen; 2522 2523 switch ( event ) 2524 { 2525 case PD_RS232_E_XON_BYTE: 2526 ELG( data, event, 'ExIm', "executeEvent - PD_RS232_E_XON_BYTE" ); 2527 port->XONchar = data; 2528 break; 2529 case PD_RS232_E_XOFF_BYTE: 2530 ELG( data, event, 'ExIm', "executeEvent - PD_RS232_E_XOFF_BYTE" ); 2531 port->XOFFchar = data; 2532 break; 2533 case PD_E_SPECIAL_BYTE: 2534 ELG( data, event, 'ExIm', "executeEvent - PD_E_SPECIAL_BYTE" ); 2535 port->SWspecial[ data >> SPECIAL_SHIFT ] |= (1 << (data & SPECIAL_MASK)); 2536 break; 2537 2538 case PD_E_VALID_DATA_BYTE: 2539 ELG( data, event, 'ExIm', "executeEvent - PD_E_VALID_DATA_BYTE" ); 2540 port->SWspecial[ data >> SPECIAL_SHIFT ] &= ~(1 << (data & SPECIAL_MASK)); 2541 break; 2542 2543 case PD_E_FLOW_CONTROL: 2544 ELG( data, event, 'ExIm', "executeEvent - PD_E_FLOW_CONTROL" ); 2545 break; 2546 2547 case PD_E_ACTIVE: 2548 ELG( data, event, 'Exlm', "executeEvent - PD_E_ACTIVE" ); 2549 if ( (bool)data ) 2550 { 2551 if ( !(state & PD_S_ACTIVE) ) 2552 { 2553 SetStructureDefaults( port, FALSE ); 2554 changeState( port, (UInt32)PD_S_ACTIVE, (UInt32)PD_S_ACTIVE ); // activate port 2555 } 2556 } else { 2557 if ( (state & PD_S_ACTIVE) ) 2558 { 2559 changeState( port, 0, (UInt32)PD_S_ACTIVE ); 2560 } 2561 } 2562 break; 2563 2564 case PD_E_DATA_LATENCY: 2565 ELG( data, event, 'ExIm', "executeEvent - PD_E_DATA_LATENCY" ); 2566 port->DataLatInterval = long2tval( data * 1000 ); 2567 break; 2568 2569 case PD_RS232_E_MIN_LATENCY: 2570 ELG( data, event, 'ExIm', "executeEvent - PD_RS232_E_MIN_LATENCY" ); 2571 port->MinLatency = bool( data ); 2572 break; 2573 2574 case PD_E_DATA_INTEGRITY: 2575 ELG( data, event, 'Exlm', "executeEvent - PD_E_DATA_INTEGRITY" ); 2576 if ( (data < PD_RS232_PARITY_NONE) || (data > PD_RS232_PARITY_SPACE)) 2577 { 2578 ret = kIOReturnBadArgument; 2579 } 2580 else 2581 { 2582 port->TX_Parity = data; 2583 port->RX_Parity = PD_RS232_PARITY_DEFAULT; 2584 } 2585 break; 2586 2587 case PD_E_DATA_RATE: 2588 ELG( data, event, 'Exlm', "executeEvent - PD_E_DATA_RATE" ); 2589 /* For API compatiblilty with Intel. */ 2590 data >>= 1; 2591 ELG( 0, data, 'Exlm', "executeEvent - actual data rate" ); 2592 if ( (data < kMinBaudRate) || (data > kMaxBaudRate) ) // Do we really care 2593 ret = kIOReturnBadArgument; 2594 else 2595 { 2596 port->BaudRate = data; 2597 } 2598 break; 2599 2600 case PD_E_DATA_SIZE: 2601 ELG( data, event, 'Exlm', "executeEvent - PD_E_DATA_SIZE" ); 2602 /* For API compatiblilty with Intel. */ 2603 data >>= 1; 2604 ELG( 0, data, 'Exlm', "executeEvent - actual data size" ); 2605 if ( (data < 5) || (data > 8) ) 2606 ret = kIOReturnBadArgument; 2607 else 2608 { 2609 port->CharLength = data; 2610 } 2611 break; 2612 2613 case PD_RS232_E_STOP_BITS: 2614 ELG( data, event, 'Exlm', "executeEvent - PD_RS232_E_STOP_BITS" ); 2615 if ( (data < 0) || (data > 20) ) 2616 ret = kIOReturnBadArgument; 2617 else 2618 { 2619 port->StopBits = data; 2620 } 2621 break; 2622 2623 case PD_E_RXQ_FLUSH: 2624 ELG( data, event, 'Exlm', "executeEvent - PD_E_RXQ_FLUSH" ); 2625 break; 2626 2627 case PD_E_RX_DATA_INTEGRITY: 2628 ELG( data, event, 'Exlm', "executeEvent - PD_E_RX_DATA_INTEGRITY" ); 2629 if ( (data != PD_RS232_PARITY_DEFAULT) && (data != PD_RS232_PARITY_ANY) ) 2630 ret = kIOReturnBadArgument; 2631 else 2632 port->RX_Parity = data; 2633 break; 2634 2635 case PD_E_RX_DATA_RATE: 2636 ELG( data, event, 'Exlm', "executeEvent - PD_E_RX_DATA_RATE" ); 2637 if ( data ) 2638 ret = kIOReturnBadArgument; 2639 break; 2640 2641 case PD_E_RX_DATA_SIZE: 2642 ELG( data, event, 'Exlm', "executeEvent - PD_E_RX_DATA_SIZE" ); 2643 if ( data ) 2644 ret = kIOReturnBadArgument; 2645 break; 2646 2647 case PD_RS232_E_RX_STOP_BITS: 2648 ELG( data, event, 'Exlm', "executeEvent - PD_RS232_E_RX_STOP_BITS" ); 2649 if ( data ) 2650 ret = kIOReturnBadArgument; 2651 break; 2652 2653 case PD_E_TXQ_FLUSH: 2654 ELG( data, event, 'Exlm', "executeEvent - PD_E_TXQ_FLUSH" ); 2655 break; 2656 2657 case PD_RS232_E_LINE_BREAK: 2658 ELG( data, event, 'Exlm', "executeEvent - PD_RS232_E_LINE_BREAK" ); 2659 state &= ~PD_RS232_S_BRK; 2660 delta |= PD_RS232_S_BRK; 2661 break; 2662 2663 case PD_E_DELAY: 2664 ELG( data, event, 'Exlm', "executeEvent - PD_E_DELAY" ); 2665 port->CharLatInterval = long2tval(data * 1000); 2666 break; 2667 2668 case PD_E_RXQ_SIZE: 2669 ELG( 0, event, 'Exlm', "executeEvent - PD_E_RXQ_SIZE" ); 2670 break; 2671 2672 case PD_E_TXQ_SIZE: 2673 ELG( 0, event, 'Exlm', "executeEvent - PD_E_TXQ_SIZE" ); 2674 break; 2675 2676 case PD_E_RXQ_HIGH_WATER: 2677 ELG( data, event, 'Exlm', "executeEvent - PD_E_RXQ_HIGH_WATER" ); 2678 break; 2679 2680 case PD_E_RXQ_LOW_WATER: 2681 ELG( data, event, 'Exlm', "executeEvent - PD_E_RXQ_LOW_WATER" ); 2682 break; 2683 2684 case PD_E_TXQ_HIGH_WATER: 2685 ELG( data, event, 'Exlm', "executeEvent - PD_E_TXQ_HIGH_WATER" ); 2686 break; 2687 2688 case PD_E_TXQ_LOW_WATER: 2689 ELG( data, event, 'Exlm', "executeEvent - PD_E_TXQ_LOW_WATER" ); 2690 break; 2691 2692 default: 2693 ELG( data, event, 'Exlm', "executeEvent - unrecognized event" ); 2694 ret = kIOReturnBadArgument; 2695 break; 2696 } 2697 2698 state |= state;/* ejk for compiler warnings. ?? */ 2699 changeState( port, state, delta ); 2700 2701 return ret; 2702 2703}/* end executeEvent */ 2704 2705/****************************************************************************************************/ 2706// 2707// Method: AppleUSBIrDADriver::requestEvent 2708// 2709// Inputs: event - The event, refCon - the Port 2710// 2711// Outputs: Return Code - kIOReturnSuccess, kIOReturnBadArgument, data - any data associated with the event 2712// 2713// Desc: requestEvent processes the specified event as an immediate request and 2714// returns the results in data. This is primarily used for getting link 2715// status information and verifying baud rate and such. 2716// 2717/****************************************************************************************************/ 2718 2719IOReturn AppleUSBIrDADriver::requestEvent( UInt32 event, UInt32 *data, void *refCon ) 2720{ 2721 PortInfo_t *port = (PortInfo_t *) refCon; 2722 IOReturn returnValue = kIOReturnSuccess; 2723 2724 ELG( 0, readPortState( port ), 'ReqE', "requestEvent" ); 2725 XTRACE(kLogReqEvent, event >> 16, (short)event); 2726 2727 if ( data == NULL ) { 2728 ELG( 0, event, 'ReqE', "requestEvent - data is null" ); 2729 returnValue = kIOReturnBadArgument; 2730 } 2731 else 2732 { 2733 XTRACE(kLogReqEventData, (*data) >> 16, (short)*data); 2734 switch ( event ) 2735 { 2736 case PD_E_ACTIVE: 2737 ELG( 0, event, 'ReqE', "requestEvent - PD_E_ACTIVE" ); 2738 *data = bool(readPortState( port ) & PD_S_ACTIVE); 2739 break; 2740 2741 case PD_E_FLOW_CONTROL: 2742 ELG( port->FlowControl, event, 'ReqE', "requestEvent - PD_E_FLOW_CONTROL" ); 2743 *data = port->FlowControl; 2744 break; 2745 2746 case PD_E_DELAY: 2747 ELG( 0, event, 'ReqE', "requestEvent - PD_E_DELAY" ); 2748 *data = tval2long( port->CharLatInterval )/ 1000; 2749 break; 2750 2751 case PD_E_DATA_LATENCY: 2752 ELG( 0, event, 'ReqE', "requestEvent - PD_E_DATA_LATENCY" ); 2753 *data = tval2long( port->DataLatInterval )/ 1000; 2754 break; 2755 2756 case PD_E_TXQ_SIZE: 2757 ELG( 0, event, 'ReqE', "requestEvent - PD_E_TXQ_SIZE" ); 2758 *data = GetQueueSize( &port->TX ); 2759 break; 2760 2761 case PD_E_RXQ_SIZE: 2762 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RXQ_SIZE" ); 2763 *data = GetQueueSize( &port->RX ); 2764 break; 2765 2766 case PD_E_TXQ_LOW_WATER: 2767 ELG( 0, event, 'ReqE', "requestEvent - PD_E_TXQ_LOW_WATER" ); 2768 *data = 0; 2769 returnValue = kIOReturnBadArgument; 2770 break; 2771 2772 case PD_E_RXQ_LOW_WATER: 2773 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RXQ_LOW_WATER" ); 2774 *data = 0; 2775 returnValue = kIOReturnBadArgument; 2776 break; 2777 2778 case PD_E_TXQ_HIGH_WATER: 2779 ELG( 0, event, 'ReqE', "requestEvent - PD_E_TXQ_HIGH_WATER" ); 2780 *data = 0; 2781 returnValue = kIOReturnBadArgument; 2782 break; 2783 2784 case PD_E_RXQ_HIGH_WATER: 2785 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RXQ_HIGH_WATER" ); 2786 *data = 0; 2787 returnValue = kIOReturnBadArgument; 2788 break; 2789 2790 case PD_E_TXQ_AVAILABLE: 2791 ELG( 0, event, 'ReqE', "requestEvent - PD_E_TXQ_AVAILABLE" ); 2792 *data = FreeSpaceinQueue( &port->TX ); 2793 break; 2794 2795 case PD_E_RXQ_AVAILABLE: 2796 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RXQ_AVAILABLE" ); 2797 *data = UsedSpaceinQueue( &port->RX ); 2798 break; 2799 2800 case PD_E_DATA_RATE: 2801 ELG( 0, event, 'ReqE', "requestEvent - PD_E_DATA_RATE" ); 2802 *data = port->BaudRate << 1; 2803 break; 2804 2805 case PD_E_RX_DATA_RATE: 2806 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RX_DATA_RATE" ); 2807 *data = 0x00; 2808 break; 2809 2810 case PD_E_DATA_SIZE: 2811 ELG( 0, event, 'ReqE', "requestEvent - PD_E_DATA_SIZE" ); 2812 *data = port->CharLength << 1; 2813 break; 2814 2815 case PD_E_RX_DATA_SIZE: 2816 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RX_DATA_SIZE" ); 2817 *data = 0x00; 2818 break; 2819 2820 case PD_E_DATA_INTEGRITY: 2821 ELG( 0, event, 'ReqE', "requestEvent - PD_E_DATA_INTEGRITY" ); 2822 *data = port->TX_Parity; 2823 break; 2824 2825 case PD_E_RX_DATA_INTEGRITY: 2826 ELG( 0, event, 'ReqE', "requestEvent - PD_E_RX_DATA_INTEGRITY" ); 2827 *data = port->RX_Parity; 2828 break; 2829 2830 case PD_RS232_E_STOP_BITS: 2831 ELG( 0, event, 'ReqE', "requestEvent - PD_RS232_E_STOP_BITS" ); 2832 *data = port->StopBits << 1; 2833 break; 2834 2835 case PD_RS232_E_RX_STOP_BITS: 2836 ELG( 0, event, 'ReqE', "requestEvent - PD_RS232_E_RX_STOP_BITS" ); 2837 *data = 0x00; 2838 break; 2839 2840 case PD_RS232_E_XON_BYTE: 2841 ELG( 0, event, 'ReqE', "requestEvent - PD_RS232_E_XON_BYTE" ); 2842 *data = port->XONchar; 2843 break; 2844 2845 case PD_RS232_E_XOFF_BYTE: 2846 ELG( 0, event, 'ReqE', "requestEvent - PD_RS232_E_XOFF_BYTE" ); 2847 *data = port->XOFFchar; 2848 break; 2849 2850 case PD_RS232_E_LINE_BREAK: 2851 ELG( 0, event, 'ReqE', "requestEvent - PD_RS232_E_LINE_BREAK" ); 2852 *data = bool(readPortState( port ) & PD_RS232_S_BRK); 2853 break; 2854 2855 case PD_RS232_E_MIN_LATENCY: 2856 ELG( 0, event, 'ReqE', "requestEvent - PD_RS232_E_MIN_LATENCY" ); 2857 *data = bool( port->MinLatency ); 2858 break; 2859 2860 default: 2861 ELG( 0, event, 'ReqE', "requestEvent - unrecognized event" ); 2862 returnValue = kIOReturnBadArgument; 2863 break; 2864 } 2865 } 2866 2867 return kIOReturnSuccess; 2868 2869}/* end requestEvent */ 2870 2871/****************************************************************************************************/ 2872// 2873// Method: AppleUSBIrDADriver::enqueueEvent 2874// 2875// Inputs: event - The event, data - any data associated with the event, 2876// sleep - true (wait for it), false (don't), refCon - the Port 2877// 2878// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen 2879// 2880// Desc: Not used by this driver. 2881// 2882/****************************************************************************************************/ 2883 2884IOReturn AppleUSBIrDADriver::enqueueEvent( UInt32 event, UInt32 data, bool sleep, void *refCon) 2885{ 2886 PortInfo_t *port = (PortInfo_t *) refCon; 2887 2888 ELG( data, event, 'EnqE', "enqueueEvent" ); 2889 2890 if ( readPortState( port ) & PD_S_ACTIVE ) 2891 { 2892 return kIOReturnSuccess; 2893 } 2894 2895 return kIOReturnNotOpen; 2896 2897}/* end enqueueEvent */ 2898 2899/****************************************************************************************************/ 2900// 2901// Method: AppleUSBIrDADriver::dequeueEvent 2902// 2903// Inputs: sleep - true (wait for it), false (don't), refCon - the Port 2904// 2905// Outputs: Return Code - kIOReturnSuccess, kIOReturnNotOpen 2906// 2907// Desc: Not used by this driver. 2908// 2909/****************************************************************************************************/ 2910 2911IOReturn AppleUSBIrDADriver::dequeueEvent( UInt32 *event, UInt32 *data, bool sleep, void *refCon ) 2912{ 2913 PortInfo_t *port = (PortInfo_t *) refCon; 2914 2915 ELG( 0, 0, 'DeqE', "dequeueEvent" ); 2916 2917 if ( (event == NULL) || (data == NULL) ) 2918 return kIOReturnBadArgument; 2919 2920 if ( readPortState( port ) & PD_S_ACTIVE ) 2921 { 2922 return kIOReturnSuccess; 2923 } 2924 2925 return kIOReturnNotOpen; 2926 2927}/* end dequeueEvent */ 2928 2929/****************************************************************************************************/ 2930// 2931// Method: AppleUSBIrDADriver::enqueueData 2932// 2933// Inputs: buffer - the data, size - number of bytes, sleep - true (wait for it), false (don't), 2934// refCon - the Port 2935// 2936// Outputs: Return Code - kIOReturnSuccess or value returned from watchState, count - bytes transferred, 2937// 2938// Desc: enqueueData will attempt to copy data from the specified buffer to 2939// the TX queue as a sequence of VALID_DATA events. The argument 2940// bufferSize specifies the number of bytes to be sent. The actual 2941// number of bytes transferred is returned in count. 2942// If sleep is true, then this method will sleep until all bytes can be 2943// transferred. If sleep is false, then as many bytes as possible 2944// will be copied to the TX queue. 2945// Note that the caller should ALWAYS check the transferCount unless 2946// the return value was kIOReturnBadArgument, indicating one or more 2947// arguments were not valid. Other possible return values are 2948// kIOReturnSuccess if all requirements were met. 2949// 2950/****************************************************************************************************/ 2951 2952IOReturn AppleUSBIrDADriver::enqueueData( UInt8 *buffer, UInt32 size, UInt32 *count, bool sleep, void *refCon ) 2953{ 2954 PortInfo_t *port = (PortInfo_t *) refCon; 2955 UInt32 state = PD_S_TXQ_LOW_WATER; 2956 IOReturn rtn = kIOReturnSuccess; 2957 2958 ELG( 0, sleep, 'eqDt', "enqueData" ); 2959 2960 if ( fTerminate ) 2961 return kIOReturnOffline; 2962 2963 if ( count == NULL || buffer == NULL ) 2964 return kIOReturnBadArgument; 2965 2966 *count = 0; 2967 2968 if ( !(readPortState( port ) & PD_S_ACTIVE) ) 2969 return kIOReturnNotOpen; 2970 2971 ELG( port->State, size, 'eqDt', "enqueData State" ); 2972 LogData( kUSBOut, size, buffer ); 2973 2974 /* OK, go ahead and try to add something to the buffer */ 2975 *count = AddtoQueue( &port->TX, buffer, size ); 2976 CheckQueues( port ); 2977 2978 /* Let the tranmitter know that we have something ready to go */ 2979 SetUpTransmit( ); 2980 2981 /* If we could not queue up all of the data on the first pass and */ 2982 /* the user wants us to sleep until it's all out then sleep */ 2983 2984 while ( (*count < size) && sleep ) 2985 { 2986 state = PD_S_TXQ_LOW_WATER; 2987 rtn = watchState( &state, PD_S_TXQ_LOW_WATER, refCon ); 2988 if ( rtn != kIOReturnSuccess ) 2989 { 2990 ELG( 0, rtn, 'EqD-', "enqueueData - interrupted" ); 2991 return rtn; 2992 } 2993 2994 *count += AddtoQueue( &port->TX, buffer + *count, size - *count ); 2995 CheckQueues( port ); 2996 2997 /* Let the tranmitter know that we have something ready to go. */ 2998 2999 SetUpTransmit( ); 3000 }/* end while */ 3001 3002 ELG( *count, size, 'enqd', "enqueueData - Enqueue" ); 3003 3004 return kIOReturnSuccess; 3005 3006}/* end enqueueData */ 3007 3008/****************************************************************************************************/ 3009// 3010// Method: AppleUSBIrDADriver::dequeueData 3011// 3012// Inputs: size - buffer size, min - minimum bytes required, refCon - the Port 3013// 3014// Outputs: buffer - data returned, min - number of bytes 3015// Return Code - kIOReturnSuccess, kIOReturnBadArgument, kIOReturnNotOpen, or value returned from watchState 3016// 3017// Desc: dequeueData will attempt to copy data from the RX queue to the 3018// specified buffer. No more than bufferSize VALID_DATA events 3019// will be transferred. In other words, copying will continue until 3020// either a non-data event is encountered or the transfer buffer 3021// is full. The actual number of bytes transferred is returned 3022// in count. 3023// The sleep semantics of this method are slightly more complicated 3024// than other methods in this API. Basically, this method will 3025// continue to sleep until either min characters have been 3026// received or a non data event is next in the RX queue. If 3027// min is zero, then this method never sleeps and will return 3028// immediately if the queue is empty. 3029// Note that the caller should ALWAYS check the transferCount 3030// unless the return value was kIOReturnBadArgument, indicating one or 3031// more arguments were not valid. 3032// 3033/****************************************************************************************************/ 3034 3035IOReturn AppleUSBIrDADriver::dequeueData( UInt8 *buffer, UInt32 size, UInt32 *count, UInt32 min, void *refCon ) 3036{ 3037 PortInfo_t *port = (PortInfo_t *) refCon; 3038 IOReturn rtn = kIOReturnSuccess; 3039 UInt32 state = 0; 3040 3041 ELG( size, min, 'dqDt', "dequeueData" ); 3042 3043 /* Check to make sure we have good arguments. */ 3044 if ( (count == NULL) || (buffer == NULL) || (min > size) ) 3045 return kIOReturnBadArgument; 3046 3047 /* If the port is not active then there should not be any chars. */ 3048 *count = 0; 3049 if ( !(readPortState( port ) & PD_S_ACTIVE) ) 3050 return kIOReturnNotOpen; 3051 3052 /* Get any data living in the queue. */ 3053 *count = RemovefromQueue( &port->RX, buffer, size ); 3054 if (fIrDA) 3055 fIrDA->ReturnCredit( *count ); // return credit when room in the queue 3056 3057 CheckQueues( port ); 3058 3059 while ( (min > 0) && (*count < min) ) 3060 { 3061 int count_read; 3062 3063 /* Figure out how many bytes we have left to queue up */ 3064 state = 0; 3065 3066 rtn = watchState( &state, PD_S_RXQ_EMPTY, refCon ); 3067 3068 if ( rtn != kIOReturnSuccess ) 3069 { 3070 ELG( 0, rtn, 'DqD-', "dequeueData - Interrupted!" ); 3071 LogData( kUSBIn, *count, buffer ); 3072 return rtn; 3073 } 3074 /* Try and get more data starting from where we left off */ 3075 count_read = RemovefromQueue( &port->RX, buffer + *count, (size - *count) ); 3076 if (fIrDA) 3077 fIrDA->ReturnCredit(count_read); // return credit when room in the queue 3078 3079 *count += count_read; 3080 CheckQueues( port ); 3081 3082 }/* end while */ 3083 3084 LogData( kUSBIn, *count, buffer ); 3085 3086 ELG( *count, size, 'deqd', "dequeueData -->Out Dequeue" ); 3087 3088 return rtn; 3089 3090}/* end dequeueData */ 3091 3092/****************************************************************************************************/ 3093// 3094// Method: AppleUSBIrDADriver::SetUpTransmit 3095// 3096// Inputs: 3097// 3098// Outputs: return code - true (transmit started), false (transmission already in progress) 3099// 3100// Desc: Setup and then start transmisson on the channel specified 3101// 3102/****************************************************************************************************/ 3103 3104bool AppleUSBIrDADriver::SetUpTransmit( void ) 3105{ 3106 3107 size_t count = 0; 3108 size_t data_Length, tCount; 3109 UInt8 *TempOutBuffer; 3110 3111 ELG( fPort, fPort->AreTransmitting, 'upTx', "SetUpTransmit" ); 3112 XTRACE(kLogSetupTransmit, 0, fPort->AreTransmitting); 3113 3114 // If we are already in the cycle of transmitting characters, 3115 // then we do not need to do anything. 3116 3117 if ( fPort->AreTransmitting == TRUE ) 3118 return false; 3119 3120 // First check if we can actually do anything, also if IrDA has no room we're done for now 3121 3122 //if ( GetQueueStatus( &fPort->TX ) != queueEmpty ) 3123 if (UsedSpaceinQueue(&fPort->TX) > 0) 3124 { 3125 data_Length = fIrDA->TXBufferAvailable(); 3126 if ( data_Length == 0 ) 3127 { 3128 return false; 3129 } 3130 3131 if ( data_Length > MAX_BLOCK_SIZE ) 3132 { 3133 data_Length = MAX_BLOCK_SIZE; 3134 } 3135 3136 TempOutBuffer = (UInt8*)IOMalloc( data_Length ); 3137 if ( !TempOutBuffer ) 3138 { 3139 ELG( 0, 0, 'STA-', "SetUpTransmit - buffer allocation problem" ); 3140 return false; 3141 } 3142 bzero( TempOutBuffer, data_Length ); 3143 3144 // Fill up the buffer with characters from the queue 3145 3146 count = RemovefromQueue( &fPort->TX, TempOutBuffer, data_Length ); 3147 ELG( fPort->State, count, ' Tx+', "SetUpTransmit - Sending to IrDA" ); 3148 3149 fPort->AreTransmitting = TRUE; 3150 changeState( fPort, PD_S_TX_BUSY, PD_S_TX_BUSY ); 3151 3152 tCount = fIrDA->Write( TempOutBuffer, count ); // do the "transmit" -- send to IrCOMM 3153 3154 changeState( fPort, 0, PD_S_TX_BUSY ); 3155 fPort->AreTransmitting = false; 3156 3157 IOFree( TempOutBuffer, data_Length ); 3158 if ( tCount != count ) 3159 { 3160 ELG( tCount, count, 'IrW-', "SetUpTransmit - IrDA write problem, data has been dropped" ); 3161 return false; 3162 } 3163 3164 // We potentially removed a bunch of stuff from the 3165 // queue, so see if we can free some thread(s) 3166 // to enqueue more stuff. 3167 3168 CheckQueues( fPort ); 3169 } 3170 3171 return true; 3172 3173}/* end SetUpTransmit */ 3174 3175/****************************************************************************************************/ 3176// 3177// Method: AppleUSBIrDADriver::StartTransmission 3178// 3179// Inputs: control_length - Length of control data 3180// control_buffer - Control data 3181// data_length - Length of raw data 3182// data_buffer - raw data 3183// 3184// Outputs: Return code - kIOReturnSuccess 3185// 3186// Desc: Start the transmisson. If both control and data length is zero then only 3187// the change byte will be sent. 3188// 3189/****************************************************************************************************/ 3190 3191IOReturn AppleUSBIrDADriver::StartTransmit(UInt32 control_length, UInt8 *control_buffer, UInt32 data_length, UInt8 *data_buffer) 3192{ 3193 IOReturn ior; 3194 UInt8 changeByte; 3195 3196 ELG( 0, fPort, 'StTx', "StartTransmission" ); 3197 check(fWriteActive == false); // bail? 3198 3199 // Sending control and data 3200 3201 changeByte = (fBofsCode << 4) | fBaudCode; // compute new mode byte 3202 fPipeOutBuffer[0] = (changeByte != fLastChangeByte) ? changeByte : 0; // tell hardware new mode if changed 3203 3204 fLastChangeByte = changeByte; // save new mode for next time through 3205 3206 // append the control and data buffers after the mode byte 3207 if ( control_length != 0 ) 3208 { 3209 bcopy(control_buffer, &fPipeOutBuffer[1], control_length); 3210 if ( data_length != 0 ) 3211 { 3212 bcopy(data_buffer, &fPipeOutBuffer[control_length+1], data_length); 3213 } 3214 } 3215 3216 // add up the total length to send off to the device 3217 fCount = control_length + data_length + 1; 3218 fpPipeOutMDP->setLength( fCount ); 3219 3220// LogData( kUSBOut, fCount, fPipeOutBuffer ); 3221 XTRACE(kLogXmitLen, 0, fCount); 3222 fWriteActive = true; 3223 //ior = fpOutPipe->Write( fpPipeOutMDP, &fWriteCompletionInfo ); 3224 ior = fpOutPipe->Write( fpPipeOutMDP, 1000, 1000, &fWriteCompletionInfo ); // 1 second timeouts 3225 3226 return ior; 3227 3228}/* end StartTransmission */ 3229 3230/****************************************************************************************************/ 3231// 3232// Method: AppleUSBIrDADriver::SetStructureDefaults 3233// 3234// Inputs: port - the port to set the defaults, Init - Probe time or not 3235// 3236// Outputs: None 3237// 3238// Desc: Sets the defaults for the specified port structure 3239// 3240/****************************************************************************************************/ 3241 3242void AppleUSBIrDADriver::SetStructureDefaults( PortInfo_t *port, bool Init ) 3243{ 3244 UInt32 tmp; 3245 3246 ELG( 0, 0, 'StSD', "SetStructureDefaults" ); 3247 XTRACE(kLogSetStructureDefaults, 0, Init); 3248 3249 /* These are initialized when the port is created and shouldn't be reinitialized. */ 3250 if ( Init ) 3251 { 3252 port->FCRimage = 0x00; 3253 port->IERmask = 0x00; 3254 3255 port->State = ( PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER ); 3256 port->WatchStateMask = 0x00000000; 3257 // port->serialRequestLock = 0; 3258// port->readActive = false; 3259 } 3260 3261 port->BaudRate = kDefaultBaudRate; // 9600 bps 3262 port->CharLength = 8; // 8 Data bits 3263 port->StopBits = 2; // 1 Stop bit 3264 port->TX_Parity = 1; // No Parity 3265 port->RX_Parity = 1; // --ditto-- 3266 port->MinLatency = false; 3267 port->XONchar = '\x11'; 3268 port->XOFFchar = '\x13'; 3269 port->FlowControl = 0x00000000; 3270 port->RXOstate = IDLE_XO; 3271 port->TXOstate = IDLE_XO; 3272 port->FrameTOEntry = NULL; 3273 3274// port->RXStats.BufferSize = BUFFER_SIZE_DEFAULT; 3275 port->RXStats.BufferSize = kMaxCirBufferSize; 3276// port->RXStats.HighWater = port->RXStats.BufferSize - (DATA_BUFF_SIZE*2); 3277 port->RXStats.HighWater = (port->RXStats.BufferSize << 1) / 3; 3278 port->RXStats.LowWater = port->RXStats.HighWater >> 1; 3279 3280// port->TXStats.BufferSize = BUFFER_SIZE_DEFAULT; 3281 port->TXStats.BufferSize = kMaxCirBufferSize; 3282 port->TXStats.HighWater = (port->RXStats.BufferSize << 1) / 3; 3283 port->TXStats.LowWater = port->RXStats.HighWater >> 1; 3284 3285 port->FlowControl = (DEFAULT_AUTO | DEFAULT_NOTIFY); 3286// port->FlowControl = DEFAULT_NOTIFY; 3287 3288 port->AreTransmitting = FALSE; 3289 3290 for ( tmp=0; tmp < (256 >> SPECIAL_SHIFT); tmp++ ) 3291 port->SWspecial[ tmp ] = 0; 3292 3293 return; 3294 3295}/* end SetStructureDefaults */ 3296 3297/****************************************************************************************************/ 3298// 3299// Method: AppleUSBIrDADriver::freeRingBuffer 3300// 3301// Inputs: Queue - the specified queue to free 3302// 3303// Outputs: None 3304// 3305// Desc: Frees all resources assocated with the queue, then sets all queue parameters 3306// to safe values. 3307// 3308/****************************************************************************************************/ 3309 3310void AppleUSBIrDADriver::freeRingBuffer( CirQueue *Queue ) 3311{ 3312 ELG( 0, Queue, 'f rb', "freeRingBuffer" ); 3313 require(Queue->Start, Bogus); 3314 3315 IOFree( Queue->Start, Queue->Size ); 3316 CloseQueue( Queue ); 3317 3318Bogus: 3319 return; 3320 3321}/* end freeRingBuffer */ 3322 3323/****************************************************************************************************/ 3324// 3325// Method: AppleUSBIrDADriver::allocateRingBuffer 3326// 3327// Inputs: Queue - the specified queue to allocate, BufferSize - size to allocate 3328// 3329// Outputs: return Code - true (buffer allocated), false (it failed) 3330// 3331// Desc: Allocates resources needed by the queue, then sets up all queue parameters. 3332// 3333/****************************************************************************************************/ 3334 3335bool AppleUSBIrDADriver::allocateRingBuffer( CirQueue *Queue, size_t BufferSize ) 3336{ 3337 UInt8 *Buffer; 3338 3339 // Size is ignored and kMaxCirBufferSize, which is 4096, is used. 3340 3341 ELG( 0, BufferSize, 'alrb', "allocateRingBuffer" ); 3342 Buffer = (UInt8*)IOMalloc( kMaxCirBufferSize ); 3343 3344 InitQueue( Queue, Buffer, kMaxCirBufferSize ); 3345 3346 if ( Buffer ) 3347 return true; 3348 3349 return false; 3350 3351}/* end allocateRingBuffer */ 3352 3353/****************************************************************************************************/ 3354// 3355// Method: AppleUSBIrDADriver::message 3356// 3357// Inputs: type - message type, provider - my provider, argument - additional parameters 3358// 3359// Outputs: return Code - kIOReturnSuccess 3360// 3361// Desc: Handles IOKit messages. 3362// 3363/****************************************************************************************************/ 3364 3365IOReturn AppleUSBIrDADriver::message( UInt32 type, IOService *provider, void *argument) 3366{ 3367 3368 ELG( 0, type, 'mess', "message" ); 3369 XTRACE(kLogMessage, type >> 16, (short)type); 3370 3371 switch ( type ) 3372 { 3373 case kIOMessageServiceIsTerminated: 3374 ELG( 0, type, 'mess', "message - kIOMessageServiceIsTerminated" ); 3375 3376#ifdef old // don't need to do stops, will be closed shortly 3377 3378 if (fIrDA) 3379 { 3380 int REVIEW_fTerminate; // this isn't right yet. 3381 stopIrDA(); // stop irda now 3382 } 3383 3384 if ( fSessions ) 3385 { 3386 if ( (fPort != NULL) && (fPort->serialRequestLock != 0) ) 3387 { 3388// changeState( fPort, 0, (UInt32)PD_S_ACTIVE ); 3389 } 3390 3391 KUNCUserNotificationDisplayNotice( 3392 0, // Timeout in seconds 3393 0, // Flags (for later usage) 3394 "", // iconPath (not supported yet) 3395 "", // soundPath (not supported yet) 3396 "", // localizationPath (not supported yet) 3397 "USB IrDA Unplug Notice", // the header 3398 "The USB IrDA Pod has been unplugged while an Application was still active. This can result in loss of data.", 3399 "OK"); 3400 } else { 3401 if ( fpInterface ) 3402 { 3403 fpInterface->close( this ); 3404 fpInterface->release(); 3405 fpInterface = NULL; 3406 } 3407 } 3408 3409 fTerminate = true; // we're being terminated (unplugged) 3410#endif // old 3411 3412 /* We need to disconnect the user client interface */ 3413 messageClients(kIrDACallBack_Unplug, 0, 1); 3414 break; 3415 3416 case kIOMessageServiceIsSuspended: 3417 ELG( 0, type, 'mess', "message - kIOMessageServiceIsSuspended" ); 3418 break; 3419 3420 case kIOMessageServiceIsResumed: 3421 ELG( 0, type, 'mess', "message - kIOMessageServiceIsResumed" ); 3422 break; 3423 3424 case kIOMessageServiceIsRequestingClose: 3425 ELG( 0, type, 'mess', "message - kIOMessageServiceIsRequestingClose" ); 3426 break; 3427 3428 case kIOMessageServiceWasClosed: 3429 ELG( 0, type, 'mess', "message - kIOMessageServiceWasClosed" ); 3430 break; 3431 3432 case kIOMessageServiceBusyStateChange: 3433 ELG( 0, type, 'mess', "message - kIOMessageServiceBusyStateChange" ); 3434 break; 3435 3436 case kIOUSBMessagePortHasBeenResumed: 3437 ELG( 0, type, 'mess', "message - kIOUSBMessagePortHasBeenResumed" ); 3438 DebugLog("message = kIOUSBMessagePortHasBeenResumed" ); 3439 3440 if ( !fIrDAOn ) // We tried to suspend, but it failed 3441 { 3442 fSuspendFail = true; 3443 ELG( 0, 0, 'msS-', "message - Suspend device really failed" ); 3444 } 3445 else { // we're trying to resume, so start irda 3446 if ( !startIrDA() ) 3447 { 3448 fIrDAOn = false; 3449 fTerminate = true; 3450 IOLog("AppleUSBIrDADriver: message - startIrDA failed\n" ); 3451 } else { 3452 ELG( 0, 0, 'msc+', "message - startIrDA successful" ); 3453 //IOLog("AppleUSBIrDADriver: message - startIrDA successful\n" ); 3454 } 3455 } 3456 break; 3457 3458 case kIOUSBMessageHubResumePort: 3459 ELG( 0, type, 'mess', "message - kIOUSBMessageHubResumePort" ); 3460 DebugLog("message = kIOUSBMessageHubResumePort" ); 3461 3462 if ( !fIrDAOn ) // Means the suspend failed 3463 { 3464 fSuspendFail = true; 3465 } 3466 else { // we're being asked to resume 3467 if ( !startIrDA() ) 3468 { 3469 ELG( 0, 0, 'msc-', "message - startIrDA failed" ); 3470#if 0 3471 KUNCUserNotificationDisplayNotice( 3472 0, // Timeout in seconds 3473 0, // Flags (for later usage) 3474 "", // iconPath (not supported yet) 3475 "", // soundPath (not supported yet) 3476 "", // localizationPath (not supported yet) 3477 "USB IrDA Problem Notice", // the header 3478 "The USB IrDA Pod has experienced difficulties. To continue either replug the device (if external) or restart the computer", 3479 "OK"); 3480#endif 3481 3482 fIrDAOn = false; // We're basically sol at this point 3483 fTerminate = true; 3484 } else { 3485 ELG( 0, 0, 'msc+', "message - createSerialStream successful" ); 3486 //IOLog("AppleUSBIrDADriver: message - createSerialStream successful\n" ); 3487 } 3488 } 3489 3490 default: 3491 ELG( 0, type, 'mess', "message - unknown message" ); 3492 break; 3493 } 3494 3495 return kIOReturnSuccess; 3496} 3497 3498/****************************************************************************************************/ 3499// 3500// Method: AppleUSBIrDADriver::readPortState 3501// 3502// Inputs: port - the specified port 3503// 3504// Outputs: returnState - current state of the port 3505// 3506// Desc: Reads the current Port->State. 3507// 3508/****************************************************************************************************/ 3509 3510UInt32 AppleUSBIrDADriver::readPortState( PortInfo_t *port ) 3511{ 3512 UInt32 returnState; 3513 3514// ELG( 0, port, 'rPSt', "readPortState" ); 3515 3516 IOLockLock( port->serialRequestLock ); 3517 3518 returnState = port->State; 3519 3520 IOLockUnlock( port->serialRequestLock); 3521 3522// ELG( returnState, 0, 'rPS-', "readPortState" ); 3523 3524 return returnState; 3525 3526}/* end readPortState */ 3527 3528/****************************************************************************************************/ 3529// 3530// Method: AppleUSBIrDADriver::changeState 3531// 3532// Inputs: port - the specified port, state - new state, mask - state mask (the specific bits) 3533// 3534// Outputs: None 3535// 3536// Desc: Change the current Port->State to state using the mask bits. 3537// if mask = 0 nothing is changed. 3538// delta contains the difference between the new and old state taking the 3539// mask into account and it's used to wake any waiting threads as appropriate. 3540// 3541/****************************************************************************************************/ 3542 3543void AppleUSBIrDADriver::changeState( PortInfo_t *port, UInt32 state, UInt32 mask ) 3544{ 3545 UInt32 delta; 3546 3547// ELG( state, mask, 'chSt', "changeState" ); 3548 3549 IOLockLock( port->serialRequestLock ); 3550 state = (port->State & ~mask) | (state & mask); // compute the new state 3551 delta = state ^ port->State; // keep a copy of the diffs 3552 port->State = state; 3553 3554 // Wake up all threads asleep on WatchStateMask 3555 3556 if ( delta & port->WatchStateMask ) 3557 { 3558 thread_wakeup_with_result( &port->WatchStateMask, THREAD_RESTART ); 3559 } 3560 3561 IOLockUnlock( port->serialRequestLock ); 3562 3563 ELG( port->State, delta, 'chSt', "changeState - exit" ); 3564 return; 3565 3566}/* end changeState */ 3567 3568/****************************************************************************************************/ 3569// 3570// Method: AppleUSBIrDADriver::privateWatchState 3571// 3572// Inputs: port - the specified port, state - state watching for, mask - state mask (the specific bits) 3573// 3574// Outputs: IOReturn - kIOReturnSuccess, kIOReturnIOError or kIOReturnIPCError 3575// 3576// Desc: Wait for the at least one of the state bits defined in mask to be equal 3577// to the value defined in state. Check on entry then sleep until necessary. 3578// A return value of kIOReturnSuccess means that at least one of the port state 3579// bits specified by mask is equal to the value passed in by state. A return 3580// value of kIOReturnIOError indicates that the port went inactive. A return 3581// value of kIOReturnIPCError indicates sleep was interrupted by a signal. 3582// 3583/****************************************************************************************************/ 3584 3585IOReturn AppleUSBIrDADriver::privateWatchState( PortInfo_t *port, UInt32 *state, UInt32 mask ) 3586{ 3587 unsigned watchState, foundStates; 3588 bool autoActiveBit = false; 3589 IOReturn rtn = kIOReturnSuccess; 3590 3591// ELG( mask, *state, 'wsta', "privateWatchState" ); 3592 3593 watchState = *state; 3594 IOLockLock( port->serialRequestLock ); 3595 3596 // hack to get around problem with carrier detection 3597 3598 if ( *state | 0x40 ) /// mlj ??? PD_S_RXQ_FULL? 3599 { 3600 port->State |= 0x40; 3601 } 3602 3603 if ( !(mask & (PD_S_ACQUIRED | PD_S_ACTIVE)) ) 3604 { 3605 watchState &= ~PD_S_ACTIVE; // Check for low PD_S_ACTIVE 3606 mask |= PD_S_ACTIVE; // Register interest in PD_S_ACTIVE bit 3607 autoActiveBit = true; 3608 } 3609 3610 for (;;) 3611 { 3612 // Check port state for any interesting bits with watchState value 3613 // NB. the '^ ~' is a XNOR and tests for equality of bits. 3614 3615 foundStates = (watchState ^ ~port->State) & mask; 3616 3617 if ( foundStates ) 3618 { 3619 *state = port->State; 3620 if ( autoActiveBit && (foundStates & PD_S_ACTIVE) ) 3621 { 3622 rtn = kIOReturnIOError; 3623 } else { 3624 rtn = kIOReturnSuccess; 3625 } 3626// ELG( rtn, foundStates, 'FndS', "privateWatchState - foundStates" ); 3627 break; 3628 } 3629 3630 // Everytime we go around the loop we have to reset the watch mask. 3631 // This means any event that could affect the WatchStateMask must 3632 // wakeup all watch state threads. The two events are an interrupt 3633 // or one of the bits in the WatchStateMask changing. 3634 3635 port->WatchStateMask |= mask; 3636 3637 // note: Interrupts need to be locked out completely here, 3638 // since as assertwait is called other threads waiting on 3639 // &port->WatchStateMask will be woken up and spun through the loop. 3640 // If an interrupt occurs at this point then the current thread 3641 // will end up waiting with a different port state than assumed 3642 // -- this problem was causing dequeueData to wait for a change in 3643 // PD_E_RXQ_EMPTY to 0 after an interrupt had already changed it to 0. 3644 3645 assert_wait( &port->WatchStateMask, true ); /* assert event */ 3646 3647 IOLockUnlock( port->serialRequestLock ); 3648 rtn = thread_block( 0 ); /* block ourselves */ 3649 IOLockLock( port->serialRequestLock ); 3650 3651 if ( rtn == THREAD_RESTART ) 3652 { 3653 continue; 3654 } else { 3655 rtn = kIOReturnIPCError; 3656 break; 3657 } 3658 }/* end for */ 3659 3660 // As it is impossible to undo the masking used by this 3661 // thread, we clear down the watch state mask and wakeup 3662 // every sleeping thread to reinitialize the mask before exiting. 3663 3664 port->WatchStateMask = 0; 3665 3666 thread_wakeup_with_result( &port->WatchStateMask, THREAD_RESTART ); 3667 IOLockUnlock( port->serialRequestLock); 3668 3669 // ELG( rtn, *state, 'wEnd', "privateWatchState end" ); 3670 3671 return rtn; 3672 3673}/* end privateWatchState */ 3674 3675#pragma mark -- hardware workaround 3676 3677/****************************************************************************************************/ 3678// 3679// Workaround: (re)send the device configuration to put the KC hardware back into a known state 3680// 3681/****************************************************************************************************/ 3682 3683void AppleUSBIrDADriver::Workaround(void) 3684{ 3685 IOReturn rc; 3686 IOUSBDevRequest *request; 3687 3688 XTRACE(kLogWorkAround, 0, 0); 3689 //DebugLog("AppleUSBIrDA: workaround called"); 3690 3691 request = (IOUSBDevRequest*)IOMalloc( sizeof(IOUSBDevRequest) ); 3692 require(request, Failed); 3693 bzero( request, sizeof(IOUSBDevRequest) ); 3694 // allocate pData here if needed 3695 3696 //request->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface); 3697 3698 request->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice); // long macro for zero 3699 request->bRequest = kUSBRqSetConfig; // 9 - set configuration 3700 request->wValue = 1; // new configuration #1 3701 request->wIndex = 0; 3702 request->wLength = 0; 3703 3704 check(request->bmRequestType == 0); 3705 check(request->bRequest == 9); // sanity eludes 3706 3707 fRequestCompletionInfo.target = this; 3708 fRequestCompletionInfo.action = workAroundComplete; 3709 fRequestCompletionInfo.parameter = request; 3710 3711 rc = fpDevice->DeviceRequest(request, &fRequestCompletionInfo); 3712 check(rc == kIOReturnSuccess); 3713 3714Failed: 3715 return; 3716}/* end Workaround */ 3717 3718 3719/****************************************************************************************************/ 3720// 3721// Function: AppleUSBCDCDriver::workAroundComplete 3722// 3723// Inputs: obj - me, param - request block 3724// rc - return code, remaining - what's left 3725// 3726// Outputs: None 3727// 3728/****************************************************************************************************/ 3729 3730void AppleUSBIrDADriver::workAroundComplete(void *obj, void *param, IOReturn rc, UInt32 remaining ) 3731{ 3732 //AppleUSBIrDADriver *me = (AppleUSBIrDADriver*)obj; 3733 IOUSBDevRequest *request = (IOUSBDevRequest*)param; 3734 UInt16 dataLen; 3735 3736 XTRACE(kLogWorkAroundComplete, 0, 0); 3737 require(request, Fail); 3738 3739 dataLen = request->wLength; 3740 if ((dataLen != 0) && (request->pData)) { // doesn't happen here 3741 IOFree(request->pData, dataLen); 3742 } 3743 IOFree(request, sizeof(IOUSBDevRequest)); 3744 3745Fail: 3746 return; 3747} /* end workAroundComplete */ 3748 3749 3750#pragma mark -- Glue 3751/****************************************************************************************************/ 3752// Glue to call the actual USB driver over the IOSerialStreamSync hurdle 3753// 3754// todo: see if dynamic cast is slow, if so just check for AppleUSBIrDADriver 3755// once at attach time and maybe save a copy of it. 3756/****************************************************************************************************/ 3757#undef super 3758#define super AppleIrDASerial 3759 OSDefineMetaClassAndStructors( AppleUSBIrDA, AppleIrDASerial ); 3760 3761bool 3762AppleUSBIrDA::attach(AppleUSBIrDADriver *provider) 3763{ 3764 // any reason not to do the type check for AppleUSBIrDADriver at compile time? 3765 return super::attach(provider); 3766} 3767 3768void 3769AppleUSBIrDA::Add_RXBytes( UInt8 *Buffer, size_t Size ) 3770{ 3771 AppleUSBIrDADriver *driver; 3772 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3773 if (driver) 3774 return driver->Add_RXBytes(Buffer, Size); 3775} 3776 3777SInt16 3778AppleUSBIrDA::SetBofCount(SInt16 bof_count) 3779{ 3780 AppleUSBIrDADriver *driver; 3781 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3782 if (driver) 3783 return driver->SetBofCount(bof_count); 3784 else 3785 return -1; 3786} 3787 3788UInt16 3789AppleUSBIrDA::SetSpeed(UInt32 brate) 3790{ 3791 AppleUSBIrDADriver *driver; 3792 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3793 if (driver) 3794 return driver->SetSpeed(brate); 3795 else 3796 return 0; 3797} 3798 3799bool 3800AppleUSBIrDA::SetUpTransmit( void ) 3801{ 3802 AppleUSBIrDADriver *driver; 3803 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3804 if (driver) 3805 return driver->SetUpTransmit(); 3806 else 3807 return false; 3808} 3809 3810IOReturn 3811AppleUSBIrDA::StartTransmit( UInt32 control_length, UInt8 *control_buffer, UInt32 data_length, UInt8 *data_buffer ) 3812{ 3813 AppleUSBIrDADriver *driver; 3814 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3815 if (driver) 3816 return driver->StartTransmit(control_length, control_buffer, data_length, data_buffer); 3817 else 3818 return -1; 3819} 3820 3821USBIrDAQoS * 3822AppleUSBIrDA::GetIrDAQoS( void ) 3823{ 3824 AppleUSBIrDADriver *driver; 3825 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3826 if (driver) 3827 return driver->GetIrDAQoS(); 3828 else 3829 return NULL; 3830} 3831 3832IrDAComm * 3833AppleUSBIrDA::GetIrDAComm( void ) 3834{ 3835 AppleUSBIrDADriver *driver; 3836 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3837 if (driver) 3838 return driver->GetIrDAComm(); 3839 else 3840 return NULL; 3841} 3842 3843void 3844AppleUSBIrDA::GetIrDAStatus( IrDAStatus *status ) 3845{ 3846 AppleUSBIrDADriver *driver; 3847 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3848 if (driver) 3849 return driver->GetIrDAStatus(status); 3850} 3851 3852IOReturn 3853AppleUSBIrDA::SetIrDAUserClientState( bool IrDAOn ) 3854{ 3855 AppleUSBIrDADriver *driver; 3856 driver = OSDynamicCast(AppleUSBIrDADriver, fProvider); 3857 if (driver) 3858 return driver->SetIrDAUserClientState(IrDAOn); 3859 else 3860 return -1; 3861} 3862 3863