|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: File: uslPipe.c ! 27: ! 28: Contains: xxx put contents here xxx ! 29: ! 30: Version: xxx put version here xxx ! 31: ! 32: Copyright: � 1998 by Apple Computer, Inc., all rights reserved. ! 33: ! 34: File Ownership: ! 35: ! 36: DRI: xxx put dri here xxx ! 37: ! 38: Other Contact: xxx put other contact here xxx ! 39: ! 40: Technology: xxx put technology here xxx ! 41: ! 42: Writers: ! 43: ! 44: (BT) Barry Twycross ! 45: ! 46: Change History (most recent first): ! 47: ! 48: <USB18> 11/16/98 BT Clear pipe state on open ! 49: <USB17> 11/5/98 BT Fix returning noErr instead of pending. ! 50: <USB16> 10/22/98 BT Fix wrong status for deleted devices. ! 51: <USB15> 10/12/98 BT Add addressed device request ! 52: <USB14> 9/29/98 BT Use real frame timing ! 53: <USB13> 8/31/98 BT Add isoc pipes ! 54: <USB12> 8/25/98 BT Isoc name changes ! 55: <USB11> 8/24/98 BT Isoc param block definition ! 56: <USB10> 8/13/98 BT Add multibus support ! 57: <USB9> 8/13/98 BT Allow zero length transactions ! 58: <USB8> 7/23/98 BT Cut annoying message ! 59: <USB7> 7/7/98 BT Avoid control reentrancy problem by making sure they're done at ! 60: secondary interrupt time. ! 61: <USB6> 5/21/98 BT Don't corrupt usbBuffer when diverting to opendevice. ! 62: <USB5> 5/20/98 BT Find implicit dev config ! 63: <USB4> 5/20/98 BT Fix pipe devidx field ! 64: <USB3> 5/17/98 BT Device request doesn't squash reqcount, buffer. Add internal ! 65: open pipe for config interface ! 66: <USB2> 4/28/98 BT Add bulk performance monitoring. ! 67: <USB1> 4/26/98 BT first checked in ! 68: */ ! 69: ! 70: #include "../USB.h" ! 71: #include "../USBpriv.h" ! 72: ! 73: #include "uslpriv.h" ! 74: #include "../uimpriv.h" ! 75: ! 76: #include "../driverservices.h" ! 77: ! 78: ! 79: static pipe pipeZeroZero; // the default pipe to device zero ! 80: ! 81: #if 0 ! 82: static OSStatus uslOpenControlEndpoint(struct USBPB *pb) ! 83: { ! 84: usbDevice *deviceP; ! 85: OSStatus retVal = kUSBInternalErr; ! 86: pipe *newPipe; ! 87: ! 88: do{ /* For error recovery */ ! 89: ! 90: /* Validate device */ ! 91: deviceP = getDevicePtr(pb->usbReference); ! 92: ! 93: if(deviceP == nil) ! 94: { ! 95: retVal = kUSBUnknownDeviceErr; ! 96: break; ! 97: } ! 98: ! 99: #if 0 ! 100: /* Validate endpoint */ ! 101: if(deviceP->numberOfEndpoints >= endpoint) ! 102: { ! 103: retVal = kUSBUnknownEndpointErr; ! 104: break; ! 105: } ! 106: #endif ! 107: ! 108: newPipe = getPipe(deviceP, pb->usbValue2); ! 109: ! 110: if(newPipe != nil) ! 111: { ! 112: retVal = kUSBAlreadyOpenErr; ! 113: break; ! 114: } ! 115: ! 116: /* This endpoint has not yet been opened. */ ! 117: if(pb->usbValue2 == 0) /* Endpoint zero is a control endpoint */ ! 118: { ! 119: retVal = kUSBUnknownEndpointErr; ! 120: break; ! 121: } ! 122: ! 123: ! 124: /* Allocate a new pipe */ ! 125: newPipe = AllocPipe(deviceP, pb->usbValue2); ! 126: if(newPipe == nil) ! 127: { ! 128: retVal = kUSBTooManyPipesErr; ! 129: break; ! 130: } ! 131: /* Fill in pertinent information for this pipe instantiation */ ! 132: newPipe->deviceIdx = makeDeviceIdx(pb->usbReference); ! 133: newPipe->intrfc = pb->usbReference; ! 134: newPipe->endPt = pb->usbValue2; ! 135: newPipe->devAddress = deviceP->usbAddress; ! 136: newPipe->flags = pb->usbFlags; ! 137: newPipe->state = kUSBActive; ! 138: ! 139: #if 0 ! 140: retVal = UIMSetupControlEndpoint(newPipe->addEnd, &newPipe->uimRef, ! 141: newPipe->maxPacket, controlCallBack, newPipe->iflags, newPipe->addEnd /* refCon */); ! 142: #endif ! 143: ! 144: if(retVal != kUSBNoErr) ! 145: { ! 146: deallocPipe(deviceP, pb->usbValue2); ! 147: break; ! 148: } ! 149: ! 150: ! 151: pb->usbReference = newPipe->ref; ! 152: ! 153: /* Just assume you can have an endpoint zero for now. */ ! 154: /* Shouldn't this be already open */ ! 155: ! 156: #if 0 ! 157: /* XXXXXXXX In real version should add something here */ ! 158: if(pipeH->type != kUSBControlType) ! 159: { ! 160: retVal = kUSBIncorrectTypeErr; ! 161: break; ! 162: } ! 163: #endif ! 164: ! 165: ! 166: retVal = kUSBNoErr; ! 167: ! 168: break; ! 169: }while(0); /* End error checking */ ! 170: ! 171: return(retVal); ! 172: } ! 173: #endif ! 174: ! 175: static OSStatus uslOpenInterruptEndpoint(USBPB *pb) ! 176: { ! 177: usbDevice *deviceP; ! 178: OSStatus retVal = kUSBInternalErr; ! 179: pipe *newPipe; ! 180: ! 181: do{ /* For error recovery */ ! 182: ! 183: /* Validate device */ ! 184: deviceP = getDevicePtr(pb->usbReference); ! 185: ! 186: if(deviceP == nil) ! 187: { ! 188: retVal = kUSBUnknownDeviceErr; ! 189: break; ! 190: } ! 191: ! 192: #if 0 ! 193: /* Validate endpoint */ ! 194: if(deviceP->numberOfEndpoints >= endpoint) ! 195: { ! 196: retVal = kUSBUnknownEndpointErr; ! 197: break; ! 198: } ! 199: #endif ! 200: ! 201: newPipe = getPipe(deviceP, pb->usbOther, kUSBIn); ! 202: ! 203: if(newPipe != nil) ! 204: { ! 205: retVal = kUSBAlreadyOpenErr; ! 206: break; ! 207: } ! 208: ! 209: /* This endpoint has not yet been opened. */ ! 210: if(pb->usbOther == 0) /* Int pipe can't be zero */ ! 211: { ! 212: retVal = kUSBIncorrectTypeErr; ! 213: break; ! 214: } ! 215: ! 216: ! 217: /* Allocate a new pipe */ ! 218: newPipe = AllocPipe(deviceP, pb->usbOther, kUSBIn); ! 219: if(newPipe == nil) ! 220: { ! 221: retVal = kUSBTooManyPipesErr; ! 222: break; ! 223: } ! 224: ! 225: /* Fill in pertinent information for this pipe instantiation */ ! 226: newPipe->bus = deviceP->bus; ! 227: newPipe->devIntfRef = pb->usbReference; ! 228: newPipe->endPt = pb->usbOther; ! 229: newPipe->direction = kUSBIn; ! 230: newPipe->devAddress = deviceP->usbAddress; ! 231: newPipe->flags = pb->usbFlags; ! 232: newPipe->type = kUSBInterrupt; ! 233: newPipe->maxPacket = pb->usb.cntl.WValue; ! 234: newPipe->state = kUSBActive; ! 235: pb->usbReference = 0; ! 236: ! 237: retVal = UIMInterruptEDCreate(newPipe->bus, ! 238: newPipe->devAddress, ! 239: pb->usbOther, /* User gives Endpoint number here */ ! 240: pb->usb.cntl.WValue, /* System fills in Max packet size here */ ! 241: deviceP->speed); ! 242: ! 243: pb->usbStatus = retVal; ! 244: if(retVal != kUSBNoErr) ! 245: { ! 246: deallocPipe(deviceP, pb->usbOther, kUSBIn); ! 247: break; ! 248: } ! 249: ! 250: pb->usbReference = newPipe->ref; ! 251: if(pb->usbCompletion != nil) ! 252: { ! 253: (*pb->usbCompletion)(pb); ! 254: } ! 255: ! 256: break; ! 257: }while(0); /* End error checking */ ! 258: ! 259: return(retVal); ! 260: } ! 261: ! 262: ! 263: static OSStatus uslOpenIsocEndpoint(USBPB *pb) ! 264: { ! 265: usbDevice *deviceP; ! 266: OSStatus retVal = kUSBInternalErr; ! 267: pipe *newPipe; ! 268: USBDirection usbDirection; ! 269: ! 270: do{ /* For error recovery */ ! 271: ! 272: /* Validate device */ ! 273: deviceP = getDevicePtr(pb->usbReference); ! 274: ! 275: if(deviceP == nil) ! 276: { ! 277: retVal = kUSBUnknownDeviceErr; ! 278: break; ! 279: } ! 280: ! 281: #if 0 ! 282: /* Validate endpoint */ ! 283: if(deviceP->numberOfEndpoints >= endpoint) ! 284: { ! 285: retVal = kUSBUnknownEndpointErr; ! 286: break; ! 287: } ! 288: #endif ! 289: ! 290: usbDirection = pb->usbFlags & 0xff; ! 291: newPipe = getPipe(deviceP, pb->usbOther, usbDirection); ! 292: ! 293: if(newPipe != nil) ! 294: { ! 295: retVal = kUSBAlreadyOpenErr; ! 296: break; ! 297: } ! 298: ! 299: /* This endpoint has not yet been opened. */ ! 300: if(pb->usbOther == 0) /* Isoc pipe can't be zero */ ! 301: { ! 302: retVal = kUSBIncorrectTypeErr; ! 303: break; ! 304: } ! 305: ! 306: ! 307: /* Allocate a new pipe */ ! 308: newPipe = AllocPipe(deviceP, pb->usbOther, usbDirection); ! 309: if(newPipe == nil) ! 310: { ! 311: retVal = kUSBTooManyPipesErr; ! 312: break; ! 313: } ! 314: ! 315: /* Fill in pertinent information for this pipe instantiation */ ! 316: newPipe->bus = deviceP->bus; ! 317: newPipe->devIntfRef = pb->usbReference; ! 318: newPipe->endPt = pb->usbOther; ! 319: newPipe->direction = usbDirection; ! 320: newPipe->devAddress = deviceP->usbAddress; ! 321: newPipe->flags = pb->usbFlags; ! 322: newPipe->type = kUSBIsoc; ! 323: newPipe->maxPacket = pb->usb.cntl.WValue; ! 324: newPipe->state = kUSBActive; ! 325: pb->usbReference = 0; ! 326: ! 327: retVal = UIMIsocEDCreate(newPipe->bus, ! 328: newPipe->devAddress, ! 329: pb->usbOther, /* User gives Endpoint number here */ ! 330: usbDirection, ! 331: pb->usb.cntl.WValue); /* System fills in Max packet size here */ ! 332: ! 333: pb->usbStatus = retVal; ! 334: if(retVal != kUSBNoErr) ! 335: { ! 336: deallocPipe(deviceP, pb->usbOther, usbDirection); ! 337: break; ! 338: } ! 339: ! 340: pb->usbReference = newPipe->ref; ! 341: if(pb->usbCompletion != nil) ! 342: { ! 343: (*pb->usbCompletion)(pb); ! 344: } ! 345: ! 346: break; ! 347: }while(0); /* End error checking */ ! 348: ! 349: return(retVal); ! 350: } ! 351: ! 352: ! 353: static OSStatus uslOpenBulkEndpoint(USBPB *pb) ! 354: { ! 355: usbDevice *deviceP; ! 356: OSStatus retVal = kUSBInternalErr; ! 357: pipe *newPipe; ! 358: USBDirection usbDirection; ! 359: ! 360: do{ /* For error recovery */ ! 361: ! 362: /* Validate device */ ! 363: deviceP = getDevicePtr(pb->usbReference); ! 364: ! 365: if(deviceP == nil) ! 366: { ! 367: retVal = kUSBUnknownDeviceErr; ! 368: break; ! 369: } ! 370: ! 371: #if 0 ! 372: /* Validate endpoint */ ! 373: if(deviceP->numberOfEndpoints >= endpoint) ! 374: { ! 375: retVal = kUSBUnknownEndpointErr; ! 376: break; ! 377: } ! 378: #endif ! 379: ! 380: usbDirection = pb->usbFlags & 0xff; ! 381: ! 382: newPipe = getPipe(deviceP, pb->usbOther, usbDirection); ! 383: ! 384: if(newPipe != nil) ! 385: { ! 386: retVal = kUSBAlreadyOpenErr; ! 387: break; ! 388: } ! 389: ! 390: /* This endpoint has not yet been opened. */ ! 391: if(pb->usbOther == 0) /* Not default pipe */ ! 392: { ! 393: retVal = kUSBIncorrectTypeErr; ! 394: break; ! 395: } ! 396: ! 397: ! 398: /* Allocate a new pipe */ ! 399: newPipe = AllocPipe(deviceP, pb->usbOther, usbDirection ); ! 400: if(newPipe == nil) ! 401: { ! 402: retVal = kUSBTooManyPipesErr; ! 403: break; ! 404: } ! 405: /* Fill in pertinent information for this pipe instantiation */ ! 406: newPipe->bus = deviceP->bus; ! 407: newPipe->devIntfRef = pb->usbReference; ! 408: newPipe->endPt = pb->usbOther; ! 409: newPipe->direction = usbDirection; ! 410: newPipe->devAddress = deviceP->usbAddress; ! 411: newPipe->flags = pb->usbFlags; ! 412: newPipe->type = kUSBBulk; ! 413: newPipe->maxPacket = pb->usb.cntl.WValue; ! 414: newPipe->state = kUSBActive; ! 415: ! 416: retVal = UIMBulkEDCreate(newPipe->bus, ! 417: newPipe->devAddress, ! 418: pb->usbOther, /* User gives Endpoint number here */ ! 419: usbDirection, ! 420: pb->usb.cntl.WValue); ! 421: ! 422: if(retVal != kUSBNoErr) ! 423: { ! 424: deallocPipe(deviceP, pb->usbOther, usbDirection ); ! 425: break; ! 426: } ! 427: ! 428: pb->usbReference = newPipe->ref; ! 429: ! 430: retVal = kUSBNoErr; ! 431: if(pb->usbCompletion != nil) ! 432: { ! 433: (*pb->usbCompletion)(pb); ! 434: } ! 435: ! 436: break; ! 437: }while(0); /* End error checking */ ! 438: ! 439: return(retVal); ! 440: } ! 441: ! 442: static OSStatus usbSIControlPacket(void *p1, void *addrEp) ! 443: { // p1 is pointer to paramblock ! 444: // second param has addr and endpoint munged together ! 445: UInt32 p2; ! 446: UInt8 addr, endPt; ! 447: OSStatus err; ! 448: USBPB *pb; ! 449: UInt32 bus; ! 450: ! 451: p2 = (UInt32)addrEp; ! 452: bus = p2 >> 16; ! 453: addr = (p2>>8) & 0xff; ! 454: endPt = p2 & 0xf; ! 455: ! 456: err = usbControlPacket(bus, p1, addr, endPt); ! 457: if(err != noErr) ! 458: { ! 459: pb = p1; ! 460: if( (pb->usbCompletion != nil) && (pb->usbCompletion != (void *)-1) ) ! 461: { ! 462: pb->usbStatus = err; ! 463: (*pb->usbCompletion)(pb); ! 464: } ! 465: } ! 466: return(noErr); ! 467: } ! 468: ! 469: /* We need to make sure these are queued as well */ ! 470: OSStatus xUSLControlRequest(UInt32 bus, USBPB *pb, pipe *thisPipe) ! 471: { ! 472: setupPacket *packet; ! 473: OSStatus err = kUSBPending; ! 474: ! 475: USBDirection direction; ! 476: USBRqType type; ! 477: USBRqRecipient recipient; ! 478: USBRequest request; ! 479: UInt16 transferSize; ! 480: //kprintf("xUSLControlRequest:ref=0x%x,device=%d\n",thisPipe->ref,thisPipe->devAddress); ! 481: do{ ! 482: direction = pb->usb.cntl.BMRequestType >> 7; ! 483: type = (pb->usb.cntl.BMRequestType >> 5) & 3; ! 484: recipient = pb->usb.cntl.BMRequestType & 31; ! 485: request = pb->usb.cntl.BRequest; ! 486: ! 487: /* FInd the packet in the param block */ ! 488: packet = (void *)&pb->usb.cntl.BMRequestType; ! 489: ! 490: /* Check the direction flag */ ! 491: if(kUSBNone == direction || pb->usbReqCount == 0 || pb->usbBuffer == nil) ! 492: { ! 493: transferSize = 0; /* Don't sit on reqcount and buffer */ ! 494: direction = kUSBOut; ! 495: } ! 496: else ! 497: { ! 498: transferSize = pb->usbReqCount; ! 499: } ! 500: ! 501: /* Put together the bitmap request type byte */ ! 502: if(packet->byte[bmRqType] == 0xff) ! 503: { ! 504: err = kUSBRqErr; ! 505: break; ! 506: } ! 507: ! 508: /* Check the request is a valid one */ ! 509: if( (type == kUSBStandard) && ! 510: (request < kUSBRqGetStatus || request > kUSBRqSyncFrame || ! 511: request == kUSBRqReserved1 || request == kUSBRqReserved2) ) ! 512: { ! 513: err = kUSBUnknownRequestErr; ! 514: break; ! 515: } ! 516: ! 517: /* Put together the rest of the packet */ ! 518: packet->word[wValue] = HostToUSBWord(pb->usb.cntl.WValue); ! 519: packet->word[wIndex] = HostToUSBWord(pb->usb.cntl.WIndex); ! 520: packet->word[wLength] = HostToUSBWord(transferSize); ! 521: ! 522: pb->usbStatus = kUSBPending; ! 523: if(CurrentExecutionLevel() == kSecondaryInterruptLevel) ! 524: { ! 525: err = usbControlPacket(bus, pb, thisPipe->devAddress, thisPipe->endPt); ! 526: } ! 527: else ! 528: { ! 529: #if 0 ! 530: static pipe *rootHub; ! 531: // temp hack. ! 532: // If we're not being called at secondary int, avoid reentrancy prob ! 533: // by arranging to be called at secondary int. ! 534: ! 535: // First try to suppress root hub messages ! 536: if(rootHub == nil) // assume first seen pipe is root hub ! 537: { ! 538: rootHub = thisPipe; ! 539: } ! 540: if(thisPipe != rootHub) ! 541: { ! 542: USBExpertStatus(-1, "\pUSL - Queueing secondary interrupt Control", thisPipe->devAddress); ! 543: } ! 544: #endif ! 545: // now queue the call back. address and endpoint munged into second parameter ! 546: err = QueueSecondaryInterruptHandler(usbSIControlPacket, nil, pb, ! 547: (void *)( ! 548: (bus << 16) + ! 549: ((UInt32)thisPipe->devAddress << 8) + ! 550: ((UInt32)thisPipe->endPt) ! 551: ) ); ! 552: } ! 553: ! 554: /* Processing now continues in controlCallBack */ ! 555: ! 556: ! 557: }while(0); ! 558: ! 559: if(err == noErr) ! 560: { ! 561: err = kUSBPending; ! 562: } ! 563: else ! 564: { ! 565: pb->usbStatus = err; ! 566: } ! 567: return(err); ! 568: } ! 569: ! 570: OSStatus uslDeviceRequest(USBPB *pb) ! 571: { ! 572: USBReference ref0, ref; ! 573: pipe *thisPipe; ! 574: OSStatus retVal = noErr; ! 575: UInt32 bus=0; ! 576: ! 577: do{ ! 578: ref = pb->usbReference; ! 579: ! 580: if((pb->usbFlags & kUSBAddressRequest) != 0) ! 581: { ! 582: USBRqRecipient recipient; ! 583: recipient = pb->usb.cntl.BMRequestType & 31; ! 584: if(recipient == kUSBInterface) ! 585: { ! 586: uslInterface *ifc; ! 587: retVal = findInterface(ref, &ifc); ! 588: if(ifc != nil) ! 589: { ! 590: pb->usb.cntl.WIndex = ifc->interfaceNum; ! 591: } ! 592: } ! 593: else if(recipient == kUSBEndpoint) ! 594: { ! 595: thisPipe = GetPipePtr(ref); ! 596: if(thisPipe != 0) ! 597: { ! 598: ref = thisPipe->devIntfRef; ! 599: pb->usb.cntl.WIndex = thisPipe->endPt; ! 600: if(thisPipe->direction == kUSBIn) ! 601: { ! 602: pb->usb.cntl.WIndex |= 0x80; ! 603: } ! 604: } ! 605: else ! 606: { ! 607: retVal = kUSBUnknownPipeErr; ! 608: } ! 609: } ! 610: else ! 611: { ! 612: retVal = paramErr; ! 613: } ! 614: if(retVal != noErr) ! 615: { ! 616: pb->usbStatus = retVal; ! 617: break; ! 618: } ! 619: } ! 620: ! 621: ref0 = getPipeZero(ref); ! 622: if(ref0 == nil) ! 623: { ! 624: if(uslHubValidateDevZero(ref, &bus)) ! 625: { ! 626: thisPipe = &pipeZeroZero; ! 627: thisPipe->bus = bus; ! 628: } ! 629: else ! 630: { ! 631: retVal = kUSBUnknownDeviceErr; ! 632: break; ! 633: } ! 634: } ! 635: else ! 636: { ! 637: thisPipe = GetPipePtr(ref0); ! 638: if(thisPipe == nil) ! 639: { ! 640: pb->usbStatus = kUSBUnknownPipeErr; ! 641: break; ! 642: } ! 643: } ! 644: retVal = xUSLControlRequest(thisPipe->bus, pb, thisPipe); ! 645: if(retVal != kUSBPending) ! 646: { ! 647: break; ! 648: } ! 649: ! 650: }while(0); ! 651: return(retVal); ! 652: } ! 653: ! 654: ! 655: ! 656: OSStatus USBDeviceRequest(USBPB *pb) ! 657: { ! 658: if(!checkPBVersion(pb, kUSBAddressRequest)) ! 659: { ! 660: return(pb->usbStatus); ! 661: } ! 662: ! 663: /* Short circuit config device requests */ ! 664: if( (pb->pbVersion != 1) && // requires 0.02 PB ! 665: (pb->usb.cntl.BMRequestType == 0) && ! 666: (pb->usb.cntl.BRequest == kUSBRqSetConfig) ) ! 667: { ! 668: pb->usbReqCount = 0; ! 669: pb->usbActCount = 0; ! 670: ! 671: pb->addrStash = (UInt32)pb->usbBuffer; ! 672: pb->usbBuffer = 0; ! 673: return(uslOpenDevice(pb)); ! 674: } ! 675: ! 676: return(uslDeviceRequest(pb)); ! 677: } ! 678: ! 679: ! 680: /* xxxx do checking that params are correct, now we have config desc */ ! 681: ! 682: /* xxxx do checking that params are correct, now we have config desc */ ! 683: static OSStatus uslOpenPipe(USBPB *pb) ! 684: { ! 685: ! 686: switch(pb->usbClassType) ! 687: { ! 688: case kUSBBulk: ! 689: return(uslOpenBulkEndpoint(pb)); ! 690: break; ! 691: ! 692: case kUSBInterrupt: ! 693: return(uslOpenInterruptEndpoint(pb)); ! 694: break; ! 695: ! 696: case kUSBIsoc: ! 697: return(uslOpenIsocEndpoint(pb)); ! 698: break; ! 699: ! 700: case kUSBControl: ! 701: //OSStatus uslOpenControlEndpoint(USBPB *pb); ! 702: return(kUSBIncorrectTypeErr); ! 703: break; ! 704: ! 705: default: ! 706: return(kUSBIncorrectTypeErr); ! 707: break; ! 708: ! 709: } ! 710: } ! 711: ! 712: OSStatus USBOpenPipe(USBPB *pb) ! 713: { ! 714: if(!checkPBVersion(pb, kUSBAnyDirn)) ! 715: { ! 716: return(pb->usbStatus); ! 717: } ! 718: ! 719: return(uslOpenPipe(pb)); ! 720: ! 721: } ! 722: ! 723: ! 724: OSStatus uslOpenPipeImmed(USBInterfaceRef intrfc, USBEndPointDescriptor *endp) ! 725: { ! 726: /* this relies on USBOpenPipe, and the bulk and interrupt opens */ ! 727: /* completing immediatly and not caring if the completion is zero */ ! 728: USBPB pb; ! 729: ! 730: pb.usbReference = intrfc; ! 731: pb.usbCompletion = nil; ! 732: ! 733: if((endp->endpointAddress & 0x80) == 0) ! 734: { ! 735: pb.usbFlags = kUSBOut; ! 736: } ! 737: else ! 738: { ! 739: pb.usbFlags = kUSBIn; ! 740: } ! 741: ! 742: pb.usbClassType = endp->attributes&3; // endpoint type ! 743: pb.usbOther = endp->endpointAddress & 0xf; ! 744: pb.usb.cntl.WValue = USBToHostWord(endp->maxPacketSize); ! 745: return(uslOpenPipe(&pb)); ! 746: } ! 747: ! 748: ! 749: void resolvePerformance(USBPB *pb) ! 750: { ! 751: pipe *thisPipe; ! 752: OSStatus err; ! 753: ! 754: err = findPipe(pb->usbReference, &thisPipe); ! 755: if( (thisPipe != nil) && (thisPipe->monitorPerformance) ) ! 756: { ! 757: pb->usbFrame = deltaFrames(pb->usbFrame, thisPipe->bus); ! 758: AddAtomic(pb->usbFrame, (void *)&thisPipe->transferTime); ! 759: AddAtomic(pb->usbActCount, (void *)&thisPipe->bytesTransfered); ! 760: pb->usbFlags = 0; ! 761: } ! 762: } ! 763: ! 764: OSStatus USBBulkRead(USBPB *pb) ! 765: { ! 766: pipe *thisPipe; ! 767: OSStatus retVal; ! 768: if(!checkPBVersion(pb, 0)) ! 769: { ! 770: return(pb->usbStatus); ! 771: } ! 772: ! 773: retVal = kUSBPending; ! 774: pb->usbStatus = retVal; ! 775: do{ ! 776: /* Find our pipe structure for this */ ! 777: retVal = findPipe(pb->usbReference, &thisPipe); ! 778: if(retVal != noErr) ! 779: { ! 780: break; ! 781: } ! 782: ! 783: if(thisPipe->monitorPerformance) ! 784: { ! 785: pb->usbFlags = 1; ! 786: pb->usbFrame = deltaFrames(0, thisPipe->bus); ! 787: } ! 788: ! 789: /* Validate its a bulk out pipe */ ! 790: if( (thisPipe->direction != kUSBIn) || (thisPipe->type != kUSBBulk) ) ! 791: { ! 792: retVal = kUSBIncorrectTypeErr; ! 793: break; ! 794: } ! 795: ! 796: /* BT 13Aug98, allow zero length transactions, they're valid. */ ! 797: ! 798: retVal = usbBulkPacket(thisPipe->bus, pb, thisPipe->devAddress, thisPipe->endPt, kUSBIn); ! 799: /* Processing now continues in bulkCallBack */ ! 800: ! 801: ! 802: }while(0); ! 803: ! 804: if(retVal == noErr) ! 805: { ! 806: retVal = kUSBPending; ! 807: } ! 808: else ! 809: { ! 810: pb->usbStatus = retVal; ! 811: } ! 812: return(retVal); ! 813: } ! 814: ! 815: OSStatus USBIntRead(USBPB *pb) ! 816: { ! 817: pipe *thisPipe; ! 818: OSStatus retVal; ! 819: ! 820: if(!checkPBVersion(pb, 0)) ! 821: { ! 822: return(pb->usbStatus); ! 823: } ! 824: ! 825: retVal = kUSBPending; ! 826: pb->usbStatus = retVal; ! 827: do{ ! 828: /* Find our pipe structure for this */ ! 829: retVal = findPipe(pb->usbReference, &thisPipe); ! 830: if(retVal != noErr) ! 831: { ! 832: break; ! 833: } ! 834: ! 835: if(thisPipe->monitorPerformance) ! 836: { ! 837: pb->usbFrame = deltaFrames(0, thisPipe->bus); ! 838: } ! 839: ! 840: /* Validate its a bulk out pipe */ ! 841: if( (thisPipe->direction != kUSBIn) || (thisPipe->type != kUSBInterrupt) ) ! 842: { ! 843: retVal = kUSBIncorrectTypeErr; ! 844: break; ! 845: } ! 846: ! 847: /* BT 13Aug98, allow zero length transactions, they're valid. */ ! 848: ! 849: kprintf("USBIntRead:calling usbIntPacket\n"); ! 850: retVal = usbIntPacket(thisPipe->bus, pb, thisPipe->devAddress, thisPipe->endPt, kUSBIn); ! 851: /* Processing now continues in intCallBack */ ! 852: ! 853: ! 854: }while(0); ! 855: if(retVal == noErr) ! 856: { ! 857: retVal = kUSBPending; ! 858: } ! 859: else ! 860: { ! 861: pb->usbStatus = retVal; ! 862: } ! 863: return(retVal); ! 864: } ! 865: ! 866: OSStatus USBIsocRead(USBPB *pb) ! 867: { ! 868: pipe *thisPipe; ! 869: OSStatus retVal; ! 870: ! 871: if(!checkPBVersionIsoc(pb, 0)) ! 872: { ! 873: return(pb->usbStatus); ! 874: } ! 875: ! 876: retVal = kUSBPending; ! 877: pb->usbStatus = retVal; ! 878: do{ ! 879: /* Find our pipe structure for this */ ! 880: retVal = findPipe(pb->usbReference, &thisPipe); ! 881: if(retVal != noErr) ! 882: { ! 883: break; ! 884: } ! 885: ! 886: /* Validate its a bulk out pipe */ ! 887: if( (thisPipe->direction != kUSBIn) || (thisPipe->type != kUSBIsoc) ) ! 888: { ! 889: retVal = kUSBIncorrectTypeErr; ! 890: break; ! 891: } ! 892: ! 893: retVal = usbIsocPacket(thisPipe->bus, pb, thisPipe->devAddress, thisPipe->endPt, kUSBIn); ! 894: /* Processing now continues in bulkCallBack */ ! 895: ! 896: ! 897: }while(0); ! 898: if(retVal == noErr) ! 899: { ! 900: retVal = kUSBPending; ! 901: } ! 902: else ! 903: { ! 904: pb->usbStatus = retVal; ! 905: } ! 906: return(retVal); ! 907: } ! 908: ! 909: OSStatus USBBulkWrite(USBPB *pb) ! 910: { ! 911: pipe *thisPipe; ! 912: OSStatus retVal; ! 913: if(!checkPBVersion(pb, 0)) ! 914: { ! 915: return(pb->usbStatus); ! 916: } ! 917: ! 918: retVal = kUSBPending; ! 919: pb->usbStatus = retVal; ! 920: do{ ! 921: /* Find our pipe structure for this */ ! 922: retVal = findPipe(pb->usbReference, &thisPipe); ! 923: if(retVal != noErr) ! 924: { ! 925: break; ! 926: } ! 927: ! 928: if(thisPipe->monitorPerformance) ! 929: { ! 930: pb->usbFlags = 1; ! 931: pb->usbFrame = deltaFrames(0, thisPipe->bus); ! 932: } ! 933: ! 934: /* Validate its a bulk out pipe */ ! 935: if( (thisPipe->direction != kUSBOut) || (thisPipe->type != kUSBBulk) ) ! 936: { ! 937: retVal = kUSBIncorrectTypeErr; ! 938: break; ! 939: } ! 940: ! 941: /* BT 13Aug98, allow zero length transactions, they're valid. */ ! 942: ! 943: retVal = usbBulkPacket(thisPipe->bus, pb, thisPipe->devAddress, thisPipe->endPt, kUSBOut); ! 944: /* Processing now continues in controlCallBack */ ! 945: ! 946: ! 947: }while(0); ! 948: if(retVal == noErr) ! 949: { ! 950: retVal = kUSBPending; ! 951: } ! 952: else ! 953: { ! 954: pb->usbStatus = retVal; ! 955: } ! 956: return(retVal); ! 957: } ! 958: ! 959: OSStatus USBIsocWrite(USBPB *pb) ! 960: { ! 961: pipe *thisPipe; ! 962: OSStatus retVal; ! 963: if(!checkPBVersionIsoc(pb, 0)) ! 964: { ! 965: return(pb->usbStatus); ! 966: } ! 967: ! 968: retVal = kUSBPending; ! 969: pb->usbStatus = retVal; ! 970: do{ ! 971: /* Find our pipe structure for this */ ! 972: retVal = findPipe(pb->usbReference, &thisPipe); ! 973: if(retVal != noErr) ! 974: { ! 975: break; ! 976: } ! 977: ! 978: /* Validate its a bulk out pipe */ ! 979: if( (thisPipe->direction != kUSBOut) || (thisPipe->type != kUSBIsoc) ) ! 980: { ! 981: retVal = kUSBIncorrectTypeErr; ! 982: break; ! 983: } ! 984: ! 985: retVal = usbIsocPacket(thisPipe->bus, pb, thisPipe->devAddress, thisPipe->endPt, kUSBOut); ! 986: /* Processing now continues in controlCallBack */ ! 987: ! 988: ! 989: }while(0); ! 990: if(retVal == noErr) ! 991: { ! 992: retVal = kUSBPending; ! 993: } ! 994: else ! 995: { ! 996: pb->usbStatus = retVal; ! 997: } ! 998: return(retVal); ! 999: } ! 1000: ! 1001: OSStatus uslMonitorBulkPerformanceByReference(USBPipeRef ref, UInt32 what, ! 1002: UInt32 *lastRead, UInt32 *bytesTransfered, UInt32 *transferTime) ! 1003: { ! 1004: pipe *thisPipe; ! 1005: OSStatus err = noErr; ! 1006: ! 1007: do{ ! 1008: /* Note this can't be a device ref, they're automatically cleared */ ! 1009: /* Find the pipe struct */ ! 1010: err = findPipe(ref, &thisPipe); ! 1011: if(thisPipe == nil) ! 1012: { ! 1013: break; ! 1014: } ! 1015: ! 1016: /* Do something here */ ! 1017: switch(what) ! 1018: { ! 1019: case 0: ! 1020: /* stop monitoring this pipe */ ! 1021: if(thisPipe->monitorPerformance) ! 1022: { ! 1023: thisPipe->monitorPerformance = false; ! 1024: } ! 1025: else ! 1026: { ! 1027: err = kUSBNotFound; ! 1028: } ! 1029: break; ! 1030: ! 1031: case 1: ! 1032: /* Start monitoring pipe */ ! 1033: if(thisPipe->monitorPerformance) ! 1034: { ! 1035: err = kUSBAlreadyOpenErr; ! 1036: } ! 1037: else ! 1038: { ! 1039: thisPipe->monitorPerformance = true; ! 1040: thisPipe->lastRead = deltaFrames(0, thisPipe->bus); ! 1041: } ! 1042: break; ! 1043: ! 1044: case 2: ! 1045: /* Get stats, don't clear */ ! 1046: if(thisPipe->monitorPerformance) ! 1047: { ! 1048: *lastRead = thisPipe->lastRead; ! 1049: thisPipe->lastRead = deltaFrames(0, thisPipe->bus); ! 1050: *bytesTransfered = thisPipe->bytesTransfered; ! 1051: *transferTime = thisPipe->transferTime; ! 1052: } ! 1053: else ! 1054: { ! 1055: err = kUSBNotFound; ! 1056: } ! 1057: break; ! 1058: ! 1059: case 3: ! 1060: /* Get stats clear */ ! 1061: if(thisPipe->monitorPerformance) ! 1062: { ! 1063: thisPipe->monitorPerformance = true; ! 1064: } ! 1065: *lastRead = thisPipe->lastRead; ! 1066: thisPipe->lastRead = deltaFrames(0, thisPipe->bus); ! 1067: *bytesTransfered = thisPipe->bytesTransfered; ! 1068: *transferTime = thisPipe->transferTime; ! 1069: ! 1070: AddAtomic(-*bytesTransfered, (void *)&thisPipe->bytesTransfered); ! 1071: AddAtomic(-*transferTime, (void *)&thisPipe->transferTime); ! 1072: ! 1073: break; ! 1074: ! 1075: } ! 1076: ! 1077: }while(0); ! 1078: ! 1079: return(err); ! 1080: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.