1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1998-2003 Apple Computer, Inc.  All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25    /* AppleUSBCDCACMControl.cpp - MacOSX implementation of			*/
26    /* USB Communication Device Class (CDC) Driver, ACM Control Interface.	*/
27
28#include <machine/limits.h>			/* UINT_MAX */
29#include <libkern/OSByteOrder.h>
30
31#include <IOKit/assert.h>
32#include <IOKit/IOLib.h>
33#include <IOKit/IOService.h>
34#include <IOKit/IOBufferMemoryDescriptor.h>
35#include <IOKit/IOMessage.h>
36
37#include <IOKit/pwr_mgt/RootDomain.h>
38
39#if !TARGET_OS_IPHONE
40#include <IOKit/usb/IOUSBBus.h>
41#endif /* TARGET_OS_IPHONE */
42
43#include <IOKit/usb/IOUSBNub.h>
44#include <IOKit/usb/IOUSBDevice.h>
45#include <IOKit/usb/IOUSBLog.h>
46#include <IOKit/usb/IOUSBPipe.h>
47#include <IOKit/usb/USB.h>
48#include <IOKit/usb/IOUSBInterface.h>
49
50#include <IOKit/serial/IOSerialKeys.h>
51#include <IOKit/serial/IOSerialDriverSync.h>
52#include <IOKit/serial/IOModemSerialStreamSync.h>
53#include <IOKit/serial/IORS232SerialStreamSync.h>
54
55#include <UserNotification/KUNCUserNotifications.h>
56
57#define DEBUG_NAME "AppleUSBCDCACMControl"
58
59#include "AppleUSBCDCACM.h"
60#include "AppleUSBCDCACMControl.h"
61
62#define MIN_BAUD (50 << 1)
63
64    // Globals
65
66//AppleUSBCDCACMData		*gDataDriver = NULL;
67
68static IOPMPowerState gOurPowerStates[kNumCDCStates] =
69{
70    {1,0,0,0,0,0,0,0,0,0,0,0},
71    {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0}
72};
73
74#define super IOService
75
76OSDefineMetaClassAndStructors(AppleUSBCDCACMControl, IOService);
77
78/****************************************************************************************************/
79//
80//		Function:	findCDCDriverAC
81//
82//		Inputs:		controlAddr - my address
83//
84//		Outputs:
85//
86//		Desc:		Finds the initiating CDC driver
87//
88/****************************************************************************************************/
89
90AppleUSBCDC *findCDCDriverAC(void *controlAddr, IOReturn *retCode)
91{
92    AppleUSBCDCACMControl	*me = (AppleUSBCDCACMControl *)controlAddr;
93    AppleUSBCDC		*CDCDriver = NULL;
94    bool		driverOK = false;
95    OSIterator		*iterator = NULL;
96    OSDictionary	*matchingDictionary = NULL;
97
98    XTRACE(me, 0, 0, "findCDCDriverAC");
99
100        // Get matching dictionary
101
102    matchingDictionary = IOService::serviceMatching("AppleUSBCDC");
103    if (!matchingDictionary)
104    {
105        XTRACE(me, 0, 0, "findCDCDriverAC - Couldn't create a matching dictionary");
106		*retCode = kIOReturnError;
107        return NULL;
108    }
109
110	// Get an iterator
111
112    iterator = IOService::getMatchingServices(matchingDictionary);
113    if (!iterator)
114    {
115        XTRACE(me, 0, 0, "findCDCDriverAC - No AppleUSBCDC driver found!");
116        matchingDictionary->release();
117		*retCode = kIOReturnError;
118        return NULL;
119    }
120
121    	// Iterate until we find our matching CDC driver
122
123    CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
124    while (CDCDriver)
125    {
126        XTRACEP(me, 0, CDCDriver, "findCDCDriverAC - CDC driver candidate");
127
128        if (me->fControlInterface->GetDevice() == CDCDriver->getCDCDevice())
129        {
130            XTRACEP(me, 0, CDCDriver, "findCDCDriverAC - Found our CDC driver");
131            driverOK = CDCDriver->confirmControl(kUSBAbstractControlModel, me->fControlInterface);
132            break;
133        }
134        CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
135    }
136
137    matchingDictionary->release();
138    iterator->release();
139
140    if (!CDCDriver)
141    {
142        XTRACE(me, 0, 0, "findCDCDriverAC - CDC driver not found");
143		*retCode = kIOReturnNotReady;
144        return NULL;
145    }
146
147    if (!driverOK)
148    {
149        XTRACE(me, kUSBAbstractControlModel, 0, "findCDCDriverAC - Not my interface");
150		*retCode = kIOReturnError;
151        return NULL;
152    }
153
154	*retCode = kIOReturnSuccess;
155
156    return CDCDriver;
157
158}/* end findCDCDriverAC */
159
160	// Encode the 4 modem status bits (so we only make one call to setState)
161
162#if 0
163static UInt32 sMapModemStates[16] =
164{
165	             0 |              0 |              0 |              0, // 0000
166	             0 |              0 |              0 | PD_RS232_S_DCD, // 0001
167	             0 |              0 | PD_RS232_S_DSR |              0, // 0010
168	             0 |              0 | PD_RS232_S_DSR | PD_RS232_S_DCD, // 0011
169	             0 | PD_RS232_S_BRK |              0 |              0, // 0100
170	             0 | PD_RS232_S_BRK |              0 | PD_RS232_S_DCD, // 0101
171	             0 | PD_RS232_S_BRK | PD_RS232_S_DSR |              0, // 0110
172	             0 | PD_RS232_S_BRK | PD_RS232_S_DSR | PD_RS232_S_DCD, // 0111
173	PD_RS232_S_RNG |              0 |              0 |              0, // 1000
174	PD_RS232_S_RNG |              0 |              0 | PD_RS232_S_DCD, // 1001
175	PD_RS232_S_RNG |              0 | PD_RS232_S_DSR |              0, // 1010
176	PD_RS232_S_RNG |              0 | PD_RS232_S_DSR | PD_RS232_S_DCD, // 1011
177	PD_RS232_S_RNG | PD_RS232_S_BRK |              0 |              0, // 1100
178	PD_RS232_S_RNG | PD_RS232_S_BRK |              0 | PD_RS232_S_DCD, // 1101
179	PD_RS232_S_RNG | PD_RS232_S_BRK | PD_RS232_S_DSR |              0, // 1110
180	PD_RS232_S_RNG | PD_RS232_S_BRK | PD_RS232_S_DSR | PD_RS232_S_DCD, // 1111
181};
182#endif
183
184/****************************************************************************************************/
185//
186//		Method:		AppleUSBCDCACMControl::commReadComplete
187//
188//		Inputs:		obj - me
189//				rc - return code
190//				remaining - what's left
191//
192//		Outputs:	None
193//
194//		Desc:		Interrupt pipe (Comm interface) read completion routine
195//
196/****************************************************************************************************/
197
198void AppleUSBCDCACMControl::commReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
199{
200    AppleUSBCDCACMControl	*me = (AppleUSBCDCACMControl*)obj;
201    IOReturn			ior;
202    UInt32			dLen;
203    UInt16			*tState;
204    UInt32			tempS, value, mask;
205
206    XTRACE(me, rc, 0, "commReadComplete");
207
208    if (me->fStopping)
209        return;
210
211    if (rc == kIOReturnSuccess)					// If operation returned ok
212    {
213        dLen = COMM_BUFF_SIZE - remaining;
214        XTRACE(me, 0, dLen, "commReadComplete - data length");
215
216            // Now look at the state stuff
217
218        if ((dLen > 7) && (me->fCommPipeBuffer[1] == kUSBSERIAL_STATE))
219        {
220            tState = (UInt16 *)&me->fCommPipeBuffer[8];
221            tempS = USBToHostWord(*tState);
222            XTRACE(me, 0, tempS, "commReadComplete - kUSBSERIAL_STATE");
223			if (tempS & kUSBbRxCarrier)
224			{
225				value = PD_RS232_S_DCD;
226				mask = PD_RS232_S_DCD;
227			}
228			if (tempS & kUSBbTxCarrier)
229			{
230				value |= PD_RS232_S_DSR;
231				mask |= PD_RS232_S_DSR;
232			}
233			if (tempS & kUSBbBreak)
234			{
235				value |= PD_RS232_S_BRK;
236				mask |= PD_RS232_S_BRK;
237			}
238			if (tempS & kUSBbRingSignal)
239			{
240				value |= PD_RS232_S_RNG;
241				mask |= PD_RS232_S_RNG;
242			}
243
244//            mask = sMapModemStates[15];				// All 4 on
245//            value = sMapModemStates[tempS & 15];		// now the status bits
246            if (me->fDataDriver)
247            {
248                me->fDataDriver->setState(value, mask, NULL);
249            }
250        } else {
251			XTRACE(me, 0, me->fCommPipeBuffer[1], "commReadComplete - Unhandled notification");
252		}
253    } else {
254        XTRACE(me, 0, rc, "commReadComplete - error");
255        if (rc != kIOReturnAborted)
256        {
257			if ((rc == kIOUSBPipeStalled) || (rc = kIOUSBHighSpeedSplitError))
258			{
259				rc = me->checkPipe(me->fCommPipe, true);
260			} else {
261				rc = me->checkPipe(me->fCommPipe, false);
262			}
263            if (rc != kIOReturnSuccess)
264            {
265                XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)");
266            }
267        }
268    }
269
270        // Queue the next read only if not aborted
271
272    if (rc != kIOReturnAborted)
273    {
274        ior = me->fCommPipe->Read(me->fCommPipeMDP, &me->fCommCompletionInfo, NULL);
275        if (ior != kIOReturnSuccess)
276        {
277            XTRACE(me, 0, rc, "commReadComplete - Read io error");
278			me->fReadDead = true;
279        }
280    } else {
281		me->fReadDead = true;
282	}
283
284}/* end commReadComplete */
285
286/****************************************************************************************************/
287//
288//		Method:		AppleUSBCDCACMControl::merWriteComplete
289//
290//		Inputs:		obj - me
291//				param - MER
292//				rc - return code
293//				remaining - what's left
294//
295//		Outputs:	None
296//
297//		Desc:		Management Element Request write completion routine
298//
299/****************************************************************************************************/
300
301void AppleUSBCDCACMControl::merWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
302{
303    AppleUSBCDCACMControl	*me = (AppleUSBCDCACMControl *)obj;
304    IOUSBDevRequest		*MER = (IOUSBDevRequest *)param;
305    UInt16			dataLen;
306
307    XTRACE(me, 0, remaining, "merWriteComplete");
308
309    if (me->fStopping)
310    {
311        if (MER)
312        {
313            dataLen = MER->wLength;
314            if ((dataLen != 0) && (MER->pData))
315            {
316                IOFree(MER->pData, dataLen);
317            }
318            IOFree(MER, sizeof(IOUSBDevRequest));
319        }
320        return;
321    }
322
323    if (MER)
324    {
325        if (rc == kIOReturnSuccess)
326        {
327            XTRACE(me, MER->bRequest, remaining, "merWriteComplete - request");
328        } else {
329            XTRACE(me, MER->bRequest, rc, "merWriteComplete - io err");
330			if ((rc == kIOUSBPipeStalled) || (rc == kIOUSBHighSpeedSplitError))
331			{
332				rc = me->checkPipe(me->fCommPipe, false);
333			}
334        }
335
336        dataLen = MER->wLength;
337        XTRACE(me, 0, dataLen, "merWriteComplete - data length");
338        if ((dataLen != 0) && (MER->pData))
339        {
340            IOFree(MER->pData, dataLen);
341        }
342        IOFree(MER, sizeof(IOUSBDevRequest));
343
344    } else {
345        if (rc == kIOReturnSuccess)
346        {
347            XTRACE(me, 0, remaining, "merWriteComplete (request unknown)");
348        } else {
349            XTRACE(me, 0, rc, "merWriteComplete (request unknown) - io err");
350			if ((rc == kIOUSBPipeStalled) || (rc == kIOUSBHighSpeedSplitError))
351			{
352				rc = me->checkPipe(me->fCommPipe, false);
353			}
354        }
355    }
356
357}/* end merWriteComplete */
358
359/****************************************************************************************************/
360//
361//		Method:		AppleUSBCDCACMControl::probe
362//
363//		Inputs:		provider - my provider
364//
365//		Outputs:	IOService - from super::probe, score - probe score
366//
367//		Desc:		Modify the probe score if necessary (we don't  at the moment)
368//
369/****************************************************************************************************/
370
371IOService* AppleUSBCDCACMControl::probe( IOService *provider, SInt32 *score )
372{
373    IOService   *res;
374
375		// If our IOUSBInterface has a "do not match" property, it means that we should not match and need
376		// to bail.  See rdar://3716623
377
378    OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface"));
379    if (boolObj && boolObj->isTrue())
380    {
381        XTRACE(this, 0, 0, "probe - provider doesn't want us to match");
382        return NULL;
383    }
384
385    res = super::probe(provider, score);
386
387    return res;
388
389}/* end probe */
390
391/****************************************************************************************************/
392//
393//		Method:		AppleUSBCDCACMControl::start
394//
395//		Inputs:		provider - my provider
396//
397//		Outputs:	Return code - true (it's me), false (sorry it probably was me, but I can't configure it)
398//
399//		Desc:		This is called once it has beed determined I'm probably the best
400//				driver for this interface.
401//
402/****************************************************************************************************/
403
404bool AppleUSBCDCACMControl::start(IOService *provider)
405{
406	IOReturn	rtn;
407	UInt16		devDriverCount = 0;
408
409    fTerminate = false;
410    fStopping = false;
411    fdataAcquired = false;
412	fCDCDriver = NULL;
413    fCommPipeMDP = NULL;
414    fCommPipe = NULL;
415    fCommPipeBuffer = NULL;
416	fReadDead = false;
417
418    XTRACE(this, 0, 0, "start");
419
420    if(!super::start(provider))
421    {
422        ALERT(0, 0, "start - super failed");
423        return false;
424    }
425
426	// Get my USB provider - the interface
427
428    fControlInterface = OSDynamicCast(IOUSBInterface, provider);
429    if(!fControlInterface)
430    {
431        ALERT(0, 0, "start - provider invalid");
432        return false;
433    }
434
435		// See if we can find/wait for the CDC driver
436
437	while (!fCDCDriver)
438	{
439		rtn = kIOReturnSuccess;
440		fCDCDriver = findCDCDriverAC(this, &rtn);
441		if (fCDCDriver)
442		{
443			XTRACE (this, 0, fControlInterface->GetInterfaceNumber(), "start: Found the CDC device driver");
444			break;
445		} else {
446			if (rtn == kIOReturnNotReady)
447			{
448				devDriverCount++;
449				XTRACE(this, devDriverCount, fControlInterface->GetInterfaceNumber(), "start - Waiting for CDC device driver...");
450				if (devDriverCount > 9)
451				{
452					break;
453				}
454				IOSleep(100);
455			} else {
456				break;
457			}
458		}
459	}
460
461		// If we didn't find him then we have to bail
462
463	if (!fCDCDriver)
464	{
465		ALERT(0, fControlInterface->GetInterfaceNumber(), "start - Failed to find the CDC driver");
466        return false;
467	}
468
469    if (!configureACM())
470    {
471        ALERT(0, 0, "start - configureACM failed");
472        return false;
473    }
474
475    if (!allocateResources())
476    {
477		fControlInterface = NULL; //rs Since we did not retain it as yet.
478        ALERT(0, 0, "start - allocateResources failed");
479		releaseResources();
480        return false;
481    }
482
483    if (!initForPM(provider))
484    {
485        ALERT(0, 0, "start - initForPM failed");
486		releaseResources();
487        return false;
488    }
489
490    fControlInterface->retain();
491
492    registerService();
493
494    XTRACE(this, 0, 0, "start - successful");
495
496    return true;
497
498}/* end start */
499
500/****************************************************************************************************/
501//
502//		Method:		AppleUSBCDCACMControl::stop
503//
504//		Inputs:		provider - my provider
505//
506//		Outputs:	None
507//
508//		Desc:		Stops the driver
509//
510/****************************************************************************************************/
511
512void AppleUSBCDCACMControl::stop(IOService *provider)
513{
514
515    XTRACE(this, 0, 0, "stop");
516
517    fStopping = true;
518
519	if (!fTerminate)				// If we're terminated this has already been done
520	{
521		releaseResources();
522	}
523
524	PMstop();
525
526    super::stop(provider);
527
528	XTRACE(this, 0, 0, "stop - Exit");
529
530}/* end stop */
531
532/****************************************************************************************************/
533//
534//		Method:		AppleUSBCDCACMControl::configureACM
535//
536//		Inputs:
537//
538//		Outputs:	return Code - true (configured), false (not configured)
539//
540//		Desc:		Configures the Abstract Control Model interface etc.
541//
542/****************************************************************************************************/
543
544bool AppleUSBCDCACMControl::configureACM()
545{
546    UInt8	protocol;
547
548    XTRACE(this, 0, 0, "configureACM");
549
550	fCommInterfaceNumber = fControlInterface->GetInterfaceNumber();
551    XTRACE(this, 0, fCommInterfaceNumber, "configureACM - Comm interface number.");
552
553    protocol = fControlInterface->GetInterfaceProtocol();
554    if (protocol == kUSBVendorSpecificProtocol)
555    {
556        ALERT(fCommInterfaceNumber, protocol, "configureACM - ACM Control interface has vendor specific protocol");
557        return false;
558    }
559
560    if (!getFunctionalDescriptors())
561    {
562        XTRACE(this, 0, 0, "configureACM - getFunctionalDescriptors failed");
563        return false;
564    }
565
566    return true;
567
568}/* end configureACM */
569
570/****************************************************************************************************/
571//
572//		Method:		AppleUSBCDCACMControl::getFunctionalDescriptors
573//
574//		Inputs:
575//
576//		Outputs:	return - true (descriptors ok), false (somethings not right or not supported)
577//
578//		Desc:		Finds all the functional descriptors for the specific interface
579//
580/****************************************************************************************************/
581
582bool AppleUSBCDCACMControl::getFunctionalDescriptors()
583{
584    bool				gotDescriptors = false;
585    UInt16				vers;
586    UInt16				*hdrVers;
587    const FunctionalDescriptorHeader 	*funcDesc = NULL;
588    HDRFunctionalDescriptor		*HDRFDesc;		// hearder functional descriptor
589    CMFunctionalDescriptor		*CMFDesc;		// call management functional descriptor
590    ACMFunctionalDescriptor		*ACMFDesc;		// abstract control management functional descriptor
591    UnionFunctionalDescriptor		*UNNFDesc;		// union functional descriptor
592//	AppleUSBCDC				*CDCDriver = NULL;
593
594    XTRACE(this, 0, 0, "getFunctionalDescriptors");
595
596        // Set some defaults just in case and then get the associated functional descriptors
597
598    fCMCapabilities = CM_ManagementData + CM_ManagementOnData;
599    fACMCapabilities = ACM_DeviceSuppControl + ACM_DeviceSuppBreak;
600    fDataInterfaceNumber = 0xFF;
601
602    do
603    {
604        funcDesc = (const FunctionalDescriptorHeader *)fControlInterface->FindNextAssociatedDescriptor((void*)funcDesc, CS_INTERFACE);
605        if (!funcDesc)
606        {
607            gotDescriptors = true;				// We're done
608        } else {
609            switch (funcDesc->bDescriptorSubtype)
610            {
611                case Header_FunctionalDescriptor:
612                    HDRFDesc = (HDRFunctionalDescriptor *)funcDesc;
613                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Header Functional Descriptor");
614                    hdrVers = (UInt16 *)&HDRFDesc->bcdCDC1;
615                    vers = USBToHostWord(*hdrVers);
616                    if (vers > kUSBRel11)
617                    {
618                        XTRACE(this, vers, kUSBRel11, "getFunctionalDescriptors - Header descriptor version number is incorrect");
619                    }
620                    break;
621                case CM_FunctionalDescriptor:
622                    CMFDesc = (CMFunctionalDescriptor *)funcDesc;
623                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - CM Functional Descriptor");
624                    if (fDataInterfaceNumber != 0xFF)
625                    {
626                        if (fDataInterfaceNumber != CMFDesc->bDataInterface)
627                        {
628                            XTRACE(this, fDataInterfaceNumber, CMFDesc->bDataInterface, "getFunctionalDescriptors - CMF and UNNF disagree");
629                        }
630                    }
631                    if (CMFDesc->bmCapabilities & CM_ManagementData)
632                    {
633                        fDataInterfaceNumber = CMFDesc->bDataInterface;	// This will be the default if CM on data is set
634                    }
635                    fCMCapabilities = CMFDesc->bmCapabilities;
636
637                        // Check the configuration supports data management on the data interface (that's all we support)
638
639                    XTRACE(this, 0, CMFDesc->bmCapabilities, "getFunctionalDescriptors - CMFDesc->bmCapabilities");
640
641                   if (!(fCMCapabilities & CM_ManagementData))
642                    {
643                        XTRACE(this, 0, 0, "getFunctionalDescriptors - Interface doesn't support Call Management");
644                        // return false;				// We'll relax this check too
645                    }
646                    if (!(fCMCapabilities & CM_ManagementOnData))
647                    {
648                        XTRACE(this, 0, 0, "getFunctionalDescriptors - Interface doesn't support Call Management on Data Interface");
649                       //  return false;				// Some devices get this wrong so we'll let it slide
650                    }
651                    break;
652                case ACM_FunctionalDescriptor:
653                    ACMFDesc = (ACMFunctionalDescriptor *)funcDesc;
654                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - ACM Functional Descriptor");
655                    fACMCapabilities = ACMFDesc->bmCapabilities;
656                    break;
657                case Union_FunctionalDescriptor:
658                    UNNFDesc = (UnionFunctionalDescriptor *)funcDesc;
659                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Union Functional Descriptor");
660                    if (UNNFDesc->bFunctionLength > sizeof(FunctionalDescriptorHeader))
661                    {
662						if (fCommInterfaceNumber != UNNFDesc->bMasterInterface)
663                        {
664                            XTRACE(this, fCommInterfaceNumber, UNNFDesc->bMasterInterface, "getFunctionalDescriptors - Master interface incorrect");
665                        }
666
667						if (fDataInterfaceNumber == 0xFF)
668                        {
669                            fDataInterfaceNumber = UNNFDesc->bSlaveInterface[0];	// Use the first slave (may get overwritten by CMF)
670                        }
671                        if (fDataInterfaceNumber != UNNFDesc->bSlaveInterface[0])
672                        {
673                            XTRACE(this, fDataInterfaceNumber, UNNFDesc->bSlaveInterface[1], "getFunctionalDescriptors - Slave interface incorrect");
674                        }
675                    } else {
676                        XTRACE(this, UNNFDesc->bFunctionLength, 0, "getFunctionalDescriptors - Union descriptor length error");
677                    }
678                    break;
679                case CS_FunctionalDescriptor:
680                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - CS Functional Descriptor");
681                    break;
682                default:
683                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - unknown Functional Descriptor");
684                    break;
685            }
686        }
687    } while(!gotDescriptors);
688
689        // If we get this far and actually have a data interface number we're good to go (maybe...)
690		// If not ask the CDC driver if there's only one data interface so we can assume that one
691
692    if (fDataInterfaceNumber == 0xFF)
693    {
694        XTRACE(this, 0, 0, "getFunctionalDescriptors - No data interface specified");
695//		fCDCDriver = findCDCDriverAC(this);
696		if (fCDCDriver)
697		{
698			if (fCDCDriver->fDataInterfaceNumber != 0xFF)
699			{
700				fDataInterfaceNumber = fCDCDriver->fDataInterfaceNumber;
701				XTRACE(this, fACMCapabilities, fDataInterfaceNumber, "getFunctionalDescriptors - Data interface number (assumed from CDC driver)");
702			} else {
703				return false;
704			}
705		} else {
706			return false;
707		}
708    } else {
709        XTRACE(this, fACMCapabilities, fDataInterfaceNumber, "getFunctionalDescriptors - Data interface number");
710
711			// If these two are equal then this is probably the Conexant Functional descriptor problem
712
713		if (fCommInterfaceNumber == fDataInterfaceNumber)
714		{
715			ALERT(fCommInterfaceNumber, fDataInterfaceNumber, "getFunctionalDescriptors - Descriptors are incorrect, checking...");
716			if (UNNFDesc)
717			{
718				fDataInterfaceNumber = UNNFDesc->bMasterInterface;
719			} else {
720				ALERT(fCommInterfaceNumber, fDataInterfaceNumber, "getFunctionalDescriptors - unable to continue");
721				return false;
722			}
723		}
724    }
725
726    return true;
727
728}/* end getFunctionalDescriptors */
729
730/****************************************************************************************************/
731//
732//		Method:		AppleUSBCDCACMControl::dataAcquired
733//
734//		Inputs:		None
735//
736//		Outputs:	return Code - true (it worked), false (it didn't)
737//
738//		Desc:		Tells this driver the data driver's port has been acquired
739//
740/****************************************************************************************************/
741
742bool AppleUSBCDCACMControl::dataAcquired()
743{
744    IOReturn 	rtn = kIOReturnSuccess;
745
746    XTRACE(this, 0, 0, "dataAcquired");
747
748            // Read the comm interrupt pipe for status
749
750    fCommCompletionInfo.target = this;
751    fCommCompletionInfo.action = commReadComplete;
752    fCommCompletionInfo.parameter = NULL;
753
754    rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL);
755    if (rtn == kIOReturnSuccess)
756    {
757
758            // Set up the management Element Request completion routine
759
760        fMERCompletionInfo.target = this;
761        fMERCompletionInfo.action = merWriteComplete;
762        fMERCompletionInfo.parameter = NULL;
763    } else {
764        XTRACE(this, 0, rtn, "dataAcquired - Reading the interrupt pipe failed");
765        return false;
766    }
767
768    fdataAcquired = true;
769    return true;
770
771}/* end dataAcquired */
772
773/****************************************************************************************************/
774//
775//		Method:		AppleUSBCDCACMControl::dataReleased
776//
777//		Inputs:		None
778//
779//		Outputs:	None
780//
781//		Desc:		Tells this driver the data driver's port has been released
782//
783/****************************************************************************************************/
784
785void AppleUSBCDCACMControl::dataReleased()
786{
787
788    XTRACE(this, 0, 0, "dataReleased");
789
790	if (fCommPipe)
791	{
792		fCommPipe->Abort();
793	}
794    fdataAcquired = false;
795
796}/* end dataReleased */
797
798/****************************************************************************************************/
799//
800//		Method:		AppleUSBCDCACMControl::USBSendSetLineCoding
801//
802//		Inputs:		The line coding parameters
803//
804//		Outputs:
805//
806//		Desc:		Set up and send SetLineCoding Management Element Request(MER) for all settings.
807//
808/****************************************************************************************************/
809
810void AppleUSBCDCACMControl::USBSendSetLineCoding(UInt32 BaudRate, UInt8 StopBits, UInt8 TX_Parity, UInt8 CharLength)
811{
812    LineCoding		*lineParms;
813    UInt16		lcLen = sizeof(LineCoding)-1;
814    IOUSBDevRequest	*MER;
815    IOReturn		rc;
816
817    XTRACE(this, 0, 0, "USBSendSetLineCoding");
818
819	if (!fControlInterface)
820	{
821		XTRACE(this, 0, 0, "USBSendSetLineCoding - Control interface has gone");
822        return;
823	}
824
825	// First check that Set Line Coding is supported
826
827    if (!(fACMCapabilities & ACM_DeviceSuppControl))
828    {
829        XTRACE(this, 0, 0, "USBSendSetLineCoding - SetLineCoding not supported");
830        return;
831    }
832
833    lineParms = (LineCoding *)IOMalloc(lcLen);
834    if (!lineParms)
835    {
836        XTRACE(this, 0, 0, "USBSendSetLineCoding - allocate lineParms failed");
837        return;
838    }
839    bzero(lineParms, lcLen);
840
841        // Convert BaudRate - intel format doubleword (32 bits)
842
843    OSWriteLittleInt32(lineParms, dwDTERateOffset, BaudRate);
844    lineParms->bCharFormat = StopBits - 2;
845    lineParms->bParityType = TX_Parity - 1;
846    lineParms->bDataBits = CharLength;
847
848    MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest));
849    if (!MER)
850    {
851        XTRACE(this, 0, 0, "USBSendSetLineCoding - allocate MER failed");
852        return;
853    }
854    bzero(MER, sizeof(IOUSBDevRequest));
855
856        // now build the Management Element Request
857
858    MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
859    MER->bRequest = kUSBSET_LINE_CODING;
860    MER->wValue = 0;
861    MER->wIndex = fCommInterfaceNumber;
862    MER->wLength = lcLen;
863    MER->pData = lineParms;
864
865    fMERCompletionInfo.parameter = MER;
866
867    rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo);
868    if (rc != kIOReturnSuccess)
869    {
870        XTRACE(this, MER->bRequest, rc, "USBSendSetLineCoding - error issueing DeviceRequest");
871        IOFree(MER->pData, lcLen);
872        IOFree(MER, sizeof(IOUSBDevRequest));
873    }
874
875}/* end USBSendSetLineCoding */
876
877/****************************************************************************************************/
878//
879//		Method:		AppleUSBCDCACMControl::USBSendSetControlLineState
880//
881//		Inputs:		RTS - true(set RTS), false(clear RTS)
882//				DTR - true(set DTR), false(clear DTR)
883//
884//		Outputs:
885//
886//		Desc:		Set up and send SetControlLineState Management Element Request(MER).
887//
888/****************************************************************************************************/
889
890void AppleUSBCDCACMControl::USBSendSetControlLineState(bool RTS, bool DTR)
891{
892    IOReturn		rc;
893    IOUSBDevRequest	*MER;
894    UInt16		CSBitmap = 0;
895
896    XTRACE(this, 0, 0, "USBSendSetControlLineState");
897
898	if (!fControlInterface)
899	{
900		XTRACE(this, 0, 0, "USBSendSetControlLineState - Control interface has gone");
901        return;
902	}
903
904	// First check that Set Control Line State is supported
905
906    if (!(fACMCapabilities & ACM_DeviceSuppControl))
907    {
908        XTRACE(this, 0, 0, "USBSendSetControlLineState - SetControlLineState not supported");
909        return;
910    }
911
912    MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest));
913    if (!MER)
914    {
915        XTRACE(this, 0, 0, "USBSendSetControlLineState - allocate MER failed");
916        return;
917    }
918    bzero(MER, sizeof(IOUSBDevRequest));
919
920        // now build the Management Element Request
921
922    MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
923    MER->bRequest = kUSBSET_CONTROL_LINE_STATE;
924    if (RTS)
925        CSBitmap |= kRTSOn;
926    if (DTR)
927        CSBitmap |= kDTROn;
928    MER->wValue = CSBitmap;
929    MER->wIndex = fCommInterfaceNumber;
930    MER->wLength = 0;
931    MER->pData = NULL;
932
933    fMERCompletionInfo.parameter = MER;
934
935    rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo);
936    if (rc != kIOReturnSuccess)
937    {
938        XTRACE(this, MER->bRequest, rc, "USBSendSetControlLineState - error issueing DeviceRequest");
939        IOFree(MER, sizeof(IOUSBDevRequest));
940    }
941
942}/* end USBSendSetControlLineState */
943
944/****************************************************************************************************/
945//
946//		Method:		AppleUSBCDCACMControl::USBSendBreak
947//
948//		Inputs:		sBreak - true(set Break), false(clear Break)
949//
950//		Outputs:
951//
952//		Desc:		Set up and send SendBreak Management Element Request(MER).
953//
954/****************************************************************************************************/
955
956void AppleUSBCDCACMControl::USBSendBreak(bool sBreak)
957{
958    IOReturn		rc;
959    IOUSBDevRequest	*MER;
960
961    XTRACE(this, 0, 0, "USBSendBreak");
962
963	if (!fControlInterface)
964	{
965		XTRACE(this, 0, 0, "USBSendBreak - Control interface has gone");
966        return;
967	}
968
969	// First check that Send Break is supported
970
971    if (!(fACMCapabilities & ACM_DeviceSuppBreak))
972    {
973        XTRACE(this, 0, 0, "USBSendBreak - SendBreak not supported");
974        return;
975    }
976
977    MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest));
978    if (!MER)
979    {
980        XTRACE(this, 0, 0, "USBSendBreak - allocate MER failed");
981        return;
982    }
983    bzero(MER, sizeof(IOUSBDevRequest));
984
985        // now build the Management Element Request
986
987    MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
988    MER->bRequest = kUSBSEND_BREAK;
989    if (sBreak)
990    {
991        MER->wValue = 0xFFFF;
992    } else {
993        MER->wValue = 0;
994    }
995    MER->wIndex = fCommInterfaceNumber;
996    MER->wLength = 0;
997    MER->pData = NULL;
998
999    fMERCompletionInfo.parameter = MER;
1000
1001    rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo);
1002    if (rc != kIOReturnSuccess)
1003    {
1004        XTRACE(this, MER->bRequest, rc, "USBSendBreak - error issueing DeviceRequest");
1005        IOFree(MER, sizeof(IOUSBDevRequest));
1006    }
1007
1008}/* end USBSendBreak */
1009
1010/****************************************************************************************************/
1011//
1012//		Method:		AppleUSBCDCACMControl::checkPipe
1013//
1014//		Inputs:		thePipe - the pipe
1015//				devReq - true(send CLEAR_FEATURE), false(only if status returns stalled)
1016//
1017//		Outputs:
1018//
1019//		Desc:		Clear a stall on the specified pipe. If ClearPipeStall is issued
1020//				all outstanding I/O is returned with kIOUSBTransactionReturned and
1021//				a CLEAR_FEATURE Endpoint stall is sent.
1022//
1023/****************************************************************************************************/
1024
1025IOReturn AppleUSBCDCACMControl::checkPipe(IOUSBPipe *thePipe, bool devReq)
1026{
1027    IOReturn 	rtn = kIOReturnSuccess;
1028
1029    XTRACEP(this, 0, thePipe, "checkPipe");
1030
1031    if (!devReq)
1032    {
1033        rtn = thePipe->GetPipeStatus();
1034        if (rtn != kIOUSBPipeStalled)
1035        {
1036            XTRACE(this, 0, 0, "checkPipe - Pipe not stalled");
1037			return rtn;
1038        }
1039    }
1040
1041    rtn = thePipe->ClearPipeStall(true);
1042    if (rtn == kIOReturnSuccess)
1043    {
1044        XTRACE(this, 0, 0, "checkPipe - ClearPipeStall Successful");
1045    } else {
1046        XTRACE(this, 0, rtn, "checkPipe - ClearPipeStall Failed");
1047    }
1048
1049    return rtn;
1050
1051}/* end checkPipe */
1052
1053/****************************************************************************************************/
1054//
1055//		Method:		AppleUSBCDCACMControl::allocateResources
1056//
1057//		Inputs:
1058//
1059//		Outputs:	return code - true (allocate was successful), false (it failed)
1060//
1061//		Desc:		Finishes up the rest of the configuration and gets all the endpoints open etc.
1062//
1063/****************************************************************************************************/
1064
1065bool AppleUSBCDCACMControl::allocateResources()
1066{
1067    IOUSBFindEndpointRequest	epReq;
1068
1069    XTRACE(this, 0, 0, "allocateResources.");
1070
1071        // Open the end point and get the buffers
1072
1073    if (!fControlInterface->open(this))
1074    {
1075        XTRACE(this, 0, 0, "allocateResources - open comm interface failed.");
1076        return false;
1077    }
1078        // Interrupt pipe
1079
1080    epReq.type = kUSBInterrupt;
1081    epReq.direction = kUSBIn;
1082    fCommPipe = fControlInterface->FindNextPipe(0, &epReq);
1083    if (!fCommPipe)
1084    {
1085        XTRACE(this, 0, 0, "allocateResources - no comm pipe.");
1086        return false;
1087    }
1088    XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - comm pipe.");
1089
1090        // Allocate Memory Descriptor Pointer with memory for the Interrupt pipe:
1091
1092    fCommPipeMDP = IOBufferMemoryDescriptor::withCapacity(COMM_BUFF_SIZE, kIODirectionIn);
1093    if (!fCommPipeMDP)
1094    {
1095        XTRACE(this, 0, 0, "allocateResources - Couldn't allocate MDP for interrupt pipe");
1096        return false;
1097    }
1098
1099    fCommPipeBuffer = (UInt8*)fCommPipeMDP->getBytesNoCopy();
1100    XTRACEP(this, 0, fCommPipeBuffer, "allocateResources - comm buffer");
1101
1102    return true;
1103
1104}/* end allocateResources */
1105
1106/****************************************************************************************************/
1107//
1108//		Method:		AppleUSBCDCACMControl::releaseResources
1109//
1110//		Inputs:
1111//
1112//		Outputs:
1113//
1114//		Desc:		Frees up the resources allocated in allocateResources
1115//
1116/****************************************************************************************************/
1117
1118void AppleUSBCDCACMControl::releaseResources()
1119{
1120    XTRACE(this, 0, 0, "releaseResources");
1121
1122    if (fControlInterface)
1123    {
1124        fControlInterface->close(this);
1125        fControlInterface->release();
1126        fControlInterface = NULL;
1127    }
1128
1129    if (fCommPipeMDP)
1130    {
1131        fCommPipeMDP->release();
1132        fCommPipeMDP = 0;
1133    }
1134
1135}/* end releaseResources */
1136
1137/****************************************************************************************************/
1138//
1139//		Method:		AppleUSBCDCACMControl::checkInterfaceNumber
1140//
1141//		Inputs:		dataDriver - the data driver enquiring
1142//
1143//		Outputs:
1144//
1145//		Desc:		Called by the data driver to ask if this is the correct
1146//				control interface driver.
1147//
1148/****************************************************************************************************/
1149
1150bool AppleUSBCDCACMControl::checkInterfaceNumber(AppleUSBCDCACMData *dataDriver)
1151{
1152    IOUSBInterface	*dataInterface;
1153
1154    XTRACEP(this, 0, dataDriver, "checkInterfaceNumber");
1155
1156        // First check we have the same provider (Device)
1157
1158    dataInterface = OSDynamicCast(IOUSBInterface, dataDriver->getProvider());
1159    if (dataInterface == NULL)
1160    {
1161        XTRACE(this, 0, 0, "checkInterfaceNumber - Error getting Data provider");
1162        return FALSE;
1163    }
1164
1165    XTRACEP(this, dataInterface->GetDevice(), fControlInterface->GetDevice(), "checkInterfaceNumber - Checking device");
1166    if (dataInterface->GetDevice() == fControlInterface->GetDevice())
1167    {
1168
1169            // Then check to see if it's the correct data interface number
1170
1171        if (dataDriver->fPort.DataInterfaceNumber == fDataInterfaceNumber)
1172        {
1173            this->fDataDriver = dataDriver;
1174            return true;
1175        } else {
1176            XTRACE(this, 0, 0, "checkInterfaceNumber - Not correct interface number");
1177        }
1178    } else {
1179        XTRACE(this, 0, 0, "checkInterfaceNumber - Not correct device");
1180    }
1181
1182    return false;
1183
1184}/* end checkInterfaceNumber */
1185
1186/****************************************************************************************************/
1187//
1188//		Method:		AppleUSBCDCACMControl::resetDevice
1189//
1190//		Inputs:
1191//
1192//		Outputs:
1193//
1194//		Desc:		Check to see if we need to reset the device on wakeup.
1195//
1196/****************************************************************************************************/
1197
1198void AppleUSBCDCACMControl::resetDevice(void)
1199{
1200    IOReturn 	rtn = kIOReturnSuccess;
1201    USBStatus	status;
1202    bool	reset = false;
1203	bool	reenum = false;
1204
1205    XTRACE(this, 0, 0, "resetDevice");
1206
1207	if ((fStopping) || (fControlInterface == NULL) || (fTerminate))
1208	{
1209		XTRACE(this, 0, 0, "resetDevice - returning early");
1210		return;
1211	}
1212
1213		// Let everything settle down first
1214
1215//	IOSleep(100);
1216
1217    rtn = fControlInterface->GetDevice()->GetDeviceStatus(&status);
1218    if (rtn != kIOReturnSuccess)
1219    {
1220        XTRACE(this, 0, rtn, "resetDevice - Error getting device status");
1221        reset = true;
1222    } else {
1223        status = USBToHostWord(status);
1224        XTRACE(this, 0, status, "resetDevice - Device status");
1225        if (status & kDeviceSelfPowered)			// Self powered devices that need "reset on close" will also be reset
1226        {
1227			if (fDataDriver)
1228			{
1229				if (fDataDriver->fResetOnClose)
1230				{
1231					reset = true;
1232				}
1233				if (fDataDriver->fEnumOnWake)
1234				{
1235					reenum = true;
1236				}
1237			}
1238        }
1239    }
1240
1241	if ((fControlInterface) && (fDataDriver))			// Make sure the interface and data driver are still around
1242	{
1243		if (reenum)										// Enumeration takes precedent
1244		{
1245			fDataDriver->fTerminate = true;				// Warn the data driver early
1246			XTRACE(this, 0, 0, "resetDevice - Device is being re-enumerated");
1247			rtn = fControlInterface->GetDevice()->ReEnumerateDevice(0);
1248			if (rtn != kIOReturnSuccess)
1249			{
1250				XTRACE(this, 0, rtn, "resetDevice - ReEnumerateDevice failed");
1251			}
1252		} else {
1253			fDataDriver->fTerminate = false;
1254			if (reset)
1255			{
1256				XTRACE(this, 0, 0, "resetDevice - Device is being reset");
1257				rtn = fControlInterface->GetDevice()->ResetDevice();
1258				if (rtn != kIOReturnSuccess)
1259				{
1260					XTRACE(this, 0, rtn, "resetDevice - ResetDevice failed");
1261				}
1262			}
1263		}
1264    } else {
1265		XTRACE(this, 0, 0, "resetDevice - Control interface or Data driver has gone");
1266	}
1267
1268}/* end resetDevice */
1269
1270/****************************************************************************************************/
1271//
1272//		Method:		AppleUSBCDCACMControl::message
1273//
1274//		Inputs:		type - message type
1275//				provider - my provider
1276//				argument - additional parameters
1277//
1278//		Outputs:	return Code - kIOReturnSuccess
1279//
1280//		Desc:		Handles IOKit messages.
1281//
1282/****************************************************************************************************/
1283
1284IOReturn AppleUSBCDCACMControl::message(UInt32 type, IOService *provider, void *argument)
1285{
1286	IOReturn	rtn;
1287
1288    XTRACE(this, 0, type, "message");
1289
1290    switch (type)
1291    {
1292        case kIOMessageServiceIsTerminated:
1293            XTRACE(this, 0, type, "message - kIOMessageServiceIsTerminated");
1294            fTerminate = true;		// We're being terminated (unplugged)
1295            releaseResources();
1296            return kIOReturnSuccess;
1297        case kIOMessageServiceIsSuspended:
1298            XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended");
1299            break;
1300        case kIOMessageServiceIsResumed:
1301            XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed");
1302            break;
1303        case kIOMessageServiceIsRequestingClose:
1304            XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose");
1305            break;
1306        case kIOMessageServiceWasClosed:
1307            XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed");
1308            break;
1309        case kIOMessageServiceBusyStateChange:
1310            XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange");
1311            break;
1312        case kIOUSBMessagePortHasBeenResumed:
1313            XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed");
1314			if (fReadDead)
1315			{
1316				rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL);
1317				if (rtn != kIOReturnSuccess)
1318				{
1319					XTRACE(this, 0, rtn, "message - Read for interrupt-in pipe failed, still dead");
1320				} else {
1321					fReadDead = false;
1322				}
1323			}
1324            return kIOReturnSuccess;
1325        case kIOUSBMessageHubResumePort:
1326            XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort");
1327            break;
1328		case kIOUSBMessagePortHasBeenReset:
1329            XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenReset");
1330			if (fReadDead)
1331			{
1332				rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL);
1333				if (rtn != kIOReturnSuccess)
1334				{
1335					XTRACE(this, 0, rtn, "message - Read for interrupt-in pipe failed, still dead");
1336				} else {
1337					fReadDead = false;
1338				}
1339			}
1340            return kIOReturnSuccess;
1341        default:
1342            XTRACE(this, 0, type, "message - unknown message");
1343            break;
1344    }
1345
1346    return super::message(type, provider, argument);
1347
1348}/* end message */
1349
1350/****************************************************************************************************/
1351//
1352//		Method:		AppleUSBCDCACMControl::initForPM
1353//
1354//		Inputs:		provider - my provider
1355//
1356//		Outputs:	return code - true(initialized), false(failed)
1357//
1358//		Desc:		Add ourselves to the power management tree so we can do
1359//				the right thing on sleep/wakeup.
1360//
1361/****************************************************************************************************/
1362
1363bool AppleUSBCDCACMControl::initForPM(IOService *provider)
1364{
1365    XTRACE(this, 0, 0, "initForPM");
1366
1367    fPowerState = kCDCPowerOnState;				// init our power state to be 'on'
1368    PMinit();							// init power manager instance variables
1369    provider->joinPMtree(this);					// add us to the power management tree
1370    if (pm_vars != NULL)
1371    {
1372
1373            // register ourselves with ourself as policy-maker
1374
1375        registerPowerDriver(this, gOurPowerStates, kNumCDCStates);
1376        return true;
1377    } else {
1378        XTRACE(this, 0, 0, "initForPM - Initializing power manager failed");
1379    }
1380
1381    return false;
1382
1383}/* end initForPM */
1384
1385/****************************************************************************************************/
1386//
1387//		Method:		AppleUSBCDCACMControl::initialPowerStateForDomainState
1388//
1389//		Inputs:		flags -
1390//
1391//		Outputs:	return code - Current power state
1392//
1393//		Desc:		Request for our initial power state.
1394//
1395/****************************************************************************************************/
1396
1397unsigned long AppleUSBCDCACMControl::initialPowerStateForDomainState(IOPMPowerFlags flags)
1398{
1399
1400    XTRACE(this, 0, flags, "initialPowerStateForDomainState");
1401
1402    return fPowerState;
1403
1404}/* end initialPowerStateForDomainState */
1405
1406/****************************************************************************************************/
1407//
1408//		Method:		AppleUSBCDCACMControl::setPowerState
1409//
1410//		Inputs:		powerStateOrdinal - on/off
1411//
1412//		Outputs:	return code - IOPMNoErr, IOPMAckImplied or IOPMNoSuchState
1413//
1414//		Desc:		Request to turn device on or off.
1415//
1416/****************************************************************************************************/
1417
1418IOReturn AppleUSBCDCACMControl::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice)
1419{
1420
1421    XTRACE(this, 0, powerStateOrdinal, "setPowerState");
1422
1423	if (powerStateOrdinal != fPowerState)
1424	{
1425		fPowerState = powerStateOrdinal;
1426		switch (fPowerState)
1427		{
1428			case kCDCPowerOffState:
1429
1430					// Warn our data driver and clean up any threads, if we can
1431
1432				if (fDataDriver)
1433				{
1434                     fControlInterface->GetDevice()->SuspendDevice(true);
1435				}
1436
1437				break;
1438
1439			case kCDCPowerOnState:
1440                fControlInterface->GetDevice()->SuspendDevice(false);
1441				break;
1442
1443			default:
1444				return IOPMNoSuchState;
1445		}
1446	}
1447
1448	return IOPMAckImplied;
1449
1450}/* end setPowerState */