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