|
|
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: CompositeClassDriver.c
27:
28: Contains: Core functionality to Composite Class Driver
29:
30: Version: xxx put version here xxx
31:
32: Copyright: � 1997-1998 by Apple Computer, Inc., all rights reserved.
33:
34: File Ownership:
35:
36: DRI: Craig Keithley
37:
38: Other Contact: xxx put other contact here xxx
39:
40: Technology: xxx put technology here xxx
41:
42: Writers:
43:
44: (DF) David Ferguson
45: (BT) Barry Twycross
46: (CJK) Craig Keithley
47:
48: Change History (most recent first):
49:
50: <USB12> 8/25/98 BT Isoc name changes
51: <USB11> 8/11/98 CJK add error checking to GetInterfaceDescriptor. If
52: GetInterfaceDescriptor has a problem then the Composite class
53: driver won't try to load an interface driver for the device.
54: <USB10> 6/11/98 CJK add reserved params to USBExpertSetDevicePowerStatus. Wanted to
55: get it into the USB.i before freezing C1. pass 0 for right now.
56: <USB9> 6/8/98 CJK add check of power required against power available
57: <USB8> 6/6/98 DF Increment the InterfaceIndex before checking to see if it's
58: valid, pass the deviceRef to InstallInterfaceDriver
59: <USB7> 6/5/98 CJK implement finalize routine (which disposes of the interface refs
60: and removes the interface drivers)
61: <USB6> 5/20/98 BT Set pbVersion correctly
62: <USB5> 5/12/98 BT New name for add interface
63: <USB4> 5/2/98 DF use pascal strings for errors
64: <USB3> 4/9/98 CJK change to use USB.h
65: <USB2> 4/9/98 DF Massaged to work with MasterInterfaces
66: <1> 4/7/98 CJK first checked in
67: <36> 3/31/98 CJK start out at config 0
68: <35> 3/27/98 CJK set default config to be 1, then step back to 0, if that doesn't
69: work.
70: <34> 3/26/98 CJK check for config #0 & config #1 when setting up the Composite
71: device. Some devices respond to 1, others to 0.
72: <33> 3/17/98 CJK Replace "};" with just "}". Used ExtractPrototypes to create
73: function prototypes for this file (placed the in the header
74: files).
75: <32> 2/26/98 CJK change to use USL's GetFullConfiguration function.
76: <31> 2/17/98 CJK replace debugstrs with notify expert calls.
77: <30> 2/17/98 CJK Change get configuration to byte swap the length
78: <29> 2/10/98 CJK Change call to USBExpertNewDevice to use the USL's add interface
79: call.
80: <28> 2/9/98 CJK add back in set configuration
81: <27> 2/9/98 CJK remove HID Emulation related items (no more include of
82: HIDEmulation.h, etc.)
83: <26> 2/9/98 CJK remove unneeded HID support. Now in mouse & keyboard modules.
84: The add new interface call now properly loads the HID Modules
85: for mouse & keyboard.
86: <25> 2/8/98 BT Power allocation stuff
87: <24> 2/6/98 CJK add call to InitUSBKeyboard. (Disabled for now)
88: <23> 2/6/98 CJK Crank delay back down to 10ms.
89: <22> 2/4/98 BT Add ref/port info to expert notify]
90: <21> 2/3/98 CJK Change set configuration USB Direction to "USBOut". Changed
91: sequence of states to be "get configuration, set configuration,
92: set protocol, get HID descriptor"
93: <20> 2/2/98 CJK change retry to simply abort if limit is reached. Also changed
94: sequence of getting the configuration data & then setting the
95: selected configuration. Used to do a set configuration before
96: reading the first one.
97: <19> 2/2/98 CJK change readhidreport state to only copy the new hid data to the
98: old hid data *after* doing a hid notification.
99: <18> 1/30/98 CJK rework test for mouse/keyboard device types
100: <17> 1/27/98 CJK Fixed change history... Previously said something about
101: commenting out code
102: <16> 1/27/98 CJK Work on interface set protocol & get report handling. Wasn't
103: setting the direction or target properly.
104: <15> 1/26/98 CJK Add call to USBExpertNewDevice routine
105: <14> 1/26/98 BT Mangle names after design review
106: <13> 1/23/98 CJK Change to use USBServicesLib USBDelay function.
107: <12> 1/23/98 CJK Implement HID data change detection
108: <11> 1/23/98 CJK Add call to configuration parser.
109: <10> 1/22/98 CJK Work on get configuration code.
110: <9> 1/22/98 CJK Change state tag to async operation
111: <8> 1/20/98 CJK Add states to handle reading the configuration (both the base
112: size and full size).
113: <7> 1/15/98 CJK Change ClassDrivers.h to USBClassDrivers.h
114: <6> 1/14/98 BT Remove superceded expert stuff
115: <5> 1/14/98 CJK Add setup of version field
116: <4> 1/8/98 CJK Moved initialize & finalize routines over to
117: CompositeClassDescription.c
118: <3> 1/6/98 CJK Add tasktime and expert entry procs
119: <2> 12/17/97 CJK Add basic functionality for mouse and keyboard.
120: <1> 12/17/97 CJK First time checkin
121: */
122:
123: //naga#include "../types.h"
124: //naga#include "../devices.h"
125: //naga#include "../processes.h"
126: #include "../driverservices.h"
127: #include "../USB.h"
128:
129: #include "CompositeClassDriver.h"
130: extern usbCompositePBStruct myCompositePBRecord;
131:
132:
133: void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
134: {
135: paramblock->usbReference = theDeviceRef;
136: paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
137: paramblock->pbLength = sizeof(usbCompositePBStruct);
138: paramblock->pbVersion = kUSBCurrentPBVersion;
139: paramblock->usb.cntl.WIndex = 0;
140: paramblock->usbBuffer = nil;
141: paramblock->usbStatus = kUSBNoErr;
142: paramblock->usbReqCount = 0;
143: paramblock->usbActCount = 0;
144: paramblock->usb.cntl.WValue = 0;
145: paramblock->usbFlags = 0;
146: }
147:
148:
149: static Boolean immediateError(OSStatus err)
150: {
151: return((err != kUSBPending) && (err != kUSBNoErr) );
152: }
153:
154: void CompositeDeviceInitiateTransaction(USBPB *pb)
155: {
156: register usbCompositePBStruct *pCompositePB;
157: OSStatus myErr;
158:
159: pCompositePB = (usbCompositePBStruct *)(pb);
160: pCompositePB->transDepth++;
161: if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
162: {
163:
164: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
165: }
166: do
167: {
168: switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
169: {
170: case kGetFullConfiguration0:
171: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
172: pCompositePB->pb.usb.cntl.WIndex = 0; /* First try configuration 0, if it doesn't succeed, then try config 1*/
173:
174: pCompositePB->pb.usbRefcon |= kCompletionPending;
175: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
176: myErr = USBGetFullConfigurationDescriptor(pb);
177: if(immediateError(myErr))
178: {
179: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: USBGetFullConfiguration (#0) - immediate error", myErr);
180: }
181: break;
182:
183: case kGetFullConfiguration1:
184: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
185: pCompositePB->pb.usb.cntl.WIndex = 1; /* Try configuration 1 (some devices seem to expect config 0, others config 1 */
186: pCompositePB->pb.usbRefcon |= kCompletionPending;
187:
188: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
189: myErr = USBGetFullConfigurationDescriptor(pb);
190: if(immediateError(myErr))
191: {
192: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: USBGetFullConfiguration (#1) - immediate error", myErr);
193: }
194: break;
195:
196: case kSetConfig:
197: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
198: pCompositePB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
199:
200: pCompositePB->pb.usb.cntl.BRequest = kUSBRqSetConfig;
201: pCompositePB->pb.usb.cntl.WValue = pCompositePB->pFullConfigDescriptor->configValue; /* Use configuration ID value from descriptor */
202:
203: pCompositePB->pb.usbRefcon |= kCompletionPending;
204:
205: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
206: myErr = USBDeviceRequest(pb);
207: if(immediateError(myErr))
208: {
209: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: kSetConfig - immediate error", myErr);
210: }
211: break;
212:
213: case kNewInterfaceRef:
214: InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
215: // Note: pCompositePB->usb.cntl.WIndex will be set to zero by InitParamBlock
216: // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
217: pCompositePB->pb.usb.cntl.WIndex = pCompositePB->interfaceIndex;
218: pCompositePB->pb.usbRefcon |= kCompletionPending;
219: pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
220:
221: myErr = USBNewInterfaceRef(pb);
222: if(immediateError(myErr))
223: {
224: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: kNewInterfaceRef - immediate error", myErr);
225: }
226: break;
227:
228: default:
229: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
230: pCompositePB->pb.usbRefcon = kUndefined + kExitDriver;
231: break;
232: }
233: } while (false);
234:
235: // At this point the control is returned to the system. If a USB transaction
236: // has been initiated, then it will call the Complete procs
237: // (below) to handle the results of the transaction.
238: }
239:
240: void CompositeDeviceCompletionProc(USBPB *pb)
241: {
242: OSStatus myErr;
243: register usbCompositePBStruct *pCompositePB;
244: USBInterfaceDescriptorPtr pInterfaceDescriptor;
245: UInt32 i;
246:
247: pCompositePB = (usbCompositePBStruct *)(pb);
248: pCompositePB->transDepth--;
249: if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
250: {
251: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver - Illegal Transaction Depth", pCompositePB->transDepth);
252: }
253:
254: if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
255: {
256: USBExpertStatus(pCompositePB->pb.usbReference, "Composite Driver: Completion Error", pCompositePB->pb.usbStatus);
257: pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver);
258: pCompositePB->pb.usbRefcon |= kRetryTransaction;
259: pCompositePB->retryCount--;
260: if (!pCompositePB->retryCount)
261: {
262: if (pCompositePB->pb.usbRefcon == kGetFullConfiguration1)
263: {
264: pCompositePB->pb.usbRefcon = kGetFullConfiguration0;
265: }
266: else
267: {
268: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: Too many retries", pCompositePB->pb.usbRefcon);
269: pCompositePB->pb.usbRefcon = kExitDriver;
270: return;
271: }
272: }
273: }
274: else
275: {
276: pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
277: pCompositePB->retryCount = kCompositeRetryCount;
278: }
279:
280: if (pCompositePB->pb.usbRefcon & kCompletionPending)
281: {
282: pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver);
283: switch(pCompositePB->pb.usbRefcon)
284: {
285: case kGetFullConfiguration0:
286: case kGetFullConfiguration1:
287: // DebugStr("Check power");
288: pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer;
289: if (pCompositePB->pFullConfigDescriptor == nil)
290: {
291: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver: USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon);
292: pCompositePB->pb.usbRefcon = kExitDriver;
293: break;
294: }
295:
296: BlockCopy( (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) ) );
297: if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable)
298: {
299: pCompositePB->pb.usbRefcon = kSetConfig;
300: }
301: else
302: {
303: USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower);
304: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, "Composite Driver - Insufficient power for device", pCompositePB->pb.usbRefcon);
305: pCompositePB->pb.usbRefcon = kExitDriver;
306: }
307: break;
308:
309: case kSetConfig: /* get all the interface descriptors and save them */
310: for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++)
311: {
312: pCompositePB->interfaceRefArray[i] = 0;
313: myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor);
314: if (kUSBNoErr == myErr)
315: {
316: BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length));
317: }
318: else /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */
319: {
320: pCompositePB->interfaceDescriptors[i].length = 0;
321: }
322: }
323: pCompositePB->interfaceIndex = 0;
324: pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces;
325: pCompositePB->pb.usbRefcon = kNewInterfaceRef;
326: break;
327:
328: case kNewInterfaceRef:
329: /* save the new interface ref for this interface */
330: pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference;
331:
332: /* only install the interface driver if we had a valid interface descriptor */
333: if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0)
334: {
335: USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0);
336: }
337:
338: /* advance to the next interface */
339: pCompositePB->interfaceIndex++;
340:
341: /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */
342: if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
343: {
344: pCompositePB->pb.usbRefcon = kNewInterfaceRef;
345: }
346: else
347: {
348: pCompositePB->pb.usbRefcon = kExitDriver;
349: }
350: break;
351:
352: default:
353: USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "Composite Driver - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
354: pCompositePB->pb.usbRefcon = kExitDriver;
355: break;
356: }
357: }
358: if (!(pCompositePB->pb.usbRefcon & kExitDriver))
359: CompositeDeviceInitiateTransaction(pb);
360:
361: pCompositePB->okayToFinalizeFlag = true;
362: pCompositePB->disposeCompletedFlag = true;
363: }
364:
365:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.