|
|
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.