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    /* AppleUSBCDCECMControl.cpp - MacOSX implementation of			*/
26    /* USB Communication Device Class (CDC) Driver, Ethernet Control Interface.	*/
27
28#include <machine/limits.h>			/* UINT_MAX */
29#include <libkern/OSByteOrder.h>
30
31#include <IOKit/network/IOEthernetController.h>
32#include <IOKit/network/IOEthernetInterface.h>
33#include <IOKit/network/IOGatedOutputQueue.h>
34
35#include <IOKit/IOTimerEventSource.h>
36#include <IOKit/assert.h>
37#include <IOKit/IOLib.h>
38#include <IOKit/IOService.h>
39#include <IOKit/IOBufferMemoryDescriptor.h>
40#include <IOKit/IOMessage.h>
41
42#include <IOKit/pwr_mgt/RootDomain.h>
43
44#if !TARGET_OS_IPHONE
45#include <IOKit/usb/IOUSBBus.h>
46#endif /* TARGET_OS_IPHONE */
47
48#include <IOKit/usb/IOUSBNub.h>
49#include <IOKit/usb/IOUSBDevice.h>
50#include <IOKit/usb/IOUSBPipe.h>
51#include <IOKit/usb/USB.h>
52#include <IOKit/usb/IOUSBInterface.h>
53
54#include <UserNotification/KUNCUserNotifications.h>
55
56extern "C"
57{
58    #include <sys/param.h>
59    #include <sys/mbuf.h>
60}
61
62#define DEBUG_NAME "AppleUSBCDCECMControl"
63
64#include "AppleUSBCDCECM.h"
65#include "AppleUSBCDCECMControl.h"
66#include "AppleUSBCDCECMData.h"
67
68#if 0
69static IOPMPowerState gOurPowerStates[kNumCDCStates] =
70{
71    {1,0,0,0,0,0,0,0,0,0,0,0},
72    {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0}
73};
74#endif
75
76#define	numStats	13
77UInt16	stats[numStats] = { kXMIT_OK_REQ,
78                            kRCV_OK_REQ,
79                            kXMIT_ERROR_REQ,
80                            kRCV_ERROR_REQ,
81                            kRCV_CRC_ERROR_REQ,
82                            kRCV_ERROR_ALIGNMENT_REQ,
83                            kXMIT_ONE_COLLISION_REQ,
84                            kXMIT_MORE_COLLISIONS_REQ,
85                            kXMIT_DEFERRED_REQ,
86                            kXMIT_MAX_COLLISION_REQ,
87                            kRCV_OVERRUN_REQ,
88                            kXMIT_TIMES_CARRIER_LOST_REQ,
89                            kXMIT_LATE_COLLISIONS_REQ
90                        };
91
92#define super IOService
93
94OSDefineMetaClassAndStructors(AppleUSBCDCECMControl, IOService);
95
96/****************************************************************************************************/
97//
98//		Function:	findCDCDriverEC
99//
100//		Inputs:		controlAddr - my address
101//
102//		Outputs:
103//
104//		Desc:		Finds the initiating CDC driver
105//
106/****************************************************************************************************/
107
108AppleUSBCDC *findCDCDriverEC(void *controlAddr, IOReturn *retCode)
109{
110    AppleUSBCDCECMControl	*me = (AppleUSBCDCECMControl *)controlAddr;
111    AppleUSBCDC		*CDCDriver = NULL;
112    bool		driverOK = false;
113    OSIterator		*iterator = NULL;
114    OSDictionary	*matchingDictionary = NULL;
115
116    XTRACE(me, 0, 0, "findCDCDriverEC");
117
118        // Get matching dictionary
119
120    matchingDictionary = IOService::serviceMatching("AppleUSBCDC");
121    if (!matchingDictionary)
122    {
123        XTRACE(me, 0, 0, "findCDCDriverEC - Couldn't create a matching dictionary");
124		*retCode = kIOReturnError;
125        return NULL;
126    }
127
128	// Get an iterator
129
130    iterator = IOService::getMatchingServices(matchingDictionary);
131    if (!iterator)
132    {
133        XTRACE(me, 0, 0, "findCDCDriverEC - No AppleUSBCDC driver found!");
134        matchingDictionary->release();
135		*retCode = kIOReturnError;
136        return NULL;
137    }
138
139    	// Iterate until we find our matching CDC driver
140
141    CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
142    while (CDCDriver)
143    {
144        XTRACEP(me, 0, CDCDriver, "findCDCDriverEC - CDC driver candidate");
145
146        if (me->fControlInterface->GetDevice() == CDCDriver->getCDCDevice())
147        {
148            XTRACEP(me, 0, CDCDriver, "findCDCDriverEC - Found our CDC driver");
149            driverOK = CDCDriver->confirmControl(kUSBEthernetControlModel, me->fControlInterface);
150            break;
151        }
152        CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
153    }
154
155    matchingDictionary->release();
156    iterator->release();
157
158    if (!CDCDriver)
159    {
160        XTRACE(me, 0, 0, "findCDCDriverEC - CDC driver not found");
161		*retCode = kIOReturnNotReady;
162        return NULL;
163    }
164
165    if (!driverOK)
166    {
167        XTRACE(me, kUSBEthernetControlModel, 0, "findCDCDriverEC - Not my interface");
168		*retCode = kIOReturnError;
169        return NULL;
170    }
171
172	*retCode = kIOReturnSuccess;
173
174    return CDCDriver;
175
176}/* end findCDCDriverAC */
177
178/****************************************************************************************************/
179//
180//		Function:	AppleUSBCDCECMControl::Asciihex_to_binary
181//
182//		Inputs:		c - Ascii character
183//
184//		Outputs:	return byte - binary byte
185//
186//		Desc:		Converts to hex (binary).
187//
188/****************************************************************************************************/
189
190UInt8 AppleUSBCDCECMControl::Asciihex_to_binary(char c)
191{
192
193    if ('0' <= c && c <= '9')
194        return(c-'0');
195
196    if ('A' <= c && c <= 'F')
197        return((c-'A')+10);
198
199    if ('a' <= c && c <= 'f')
200        return((c-'a')+10);
201
202      // Not a hex digit, do whatever
203
204    return(0);
205
206}/* end Asciihex_to_binary */
207
208/****************************************************************************************************/
209//
210//		Method:		AppleUSBCDCECMControl::commReadComplete
211//
212//		Inputs:		obj - me
213//				param - unused
214//				rc - return code
215//				remaining - what's left
216//
217//		Outputs:
218//
219//		Desc:		Interrupt pipe (Comm interface) read completion routine
220//
221/****************************************************************************************************/
222//This method rolled back to the one from 4.1.17 due to radar://11946906
223void AppleUSBCDCECMControl::commReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
224{
225    AppleUSBCDCECMControl	*me = (AppleUSBCDCECMControl*)obj;
226    IOReturn			ior;
227    UInt32			dLen;
228    UInt8			notif;
229 	ConnectionSpeedChange	*speedChange;
230
231    if (rc == kIOReturnSuccess)	// If operation returned ok
232    {
233        dLen = COMM_BUFF_SIZE - remaining;
234        XTRACE(me, rc, dLen, "commReadComplete");
235
236        // Now look at the state stuff
237
238        notif = me->fCommPipeBuffer[1];
239        if (dLen > 7)
240        {
241            switch(notif)
242            {
243                case kUSBNETWORK_CONNECTION:
244                    me->fLinkStatus = me->fCommPipeBuffer[2];
245                    XTRACE(me, 0, me->fLinkStatus, "commReadComplete - kNetwork_Connection");
246					if (me->fDataDriver)
247					{
248						me->fDataDriver->linkStatusChange(me->fLinkStatus);
249					}
250                    break;
251                case kUSBCONNECTION_SPEED_CHANGE:
252                    speedChange = (ConnectionSpeedChange *)me->fCommPipeBuffer;
253					me->fUpSpeed = USBToHostLong(speedChange->USBitRate);
254					me->fDownSpeed = USBToHostLong(speedChange->DSBitRate);
255
256                    XTRACE(me, me->fUpSpeed, me->fDownSpeed, "commReadComplete - kConnection_Speed_Change");
257					if (me->fDataDriver)
258					{
259						me->fDataDriver->linkSpeedChange(me->fUpSpeed, me->fDownSpeed);
260					}
261                    break;
262                default:
263                    XTRACE(me, 0, notif, "commReadComplete - Unknown notification");
264                    break;
265            }
266        } else {
267            XTRACE(me, 0, notif, "commReadComplete - Invalid notification");
268        }
269    } else {
270        XTRACE(me, 0, rc, "commReadComplete - IO error");
271        if (rc != kIOReturnAborted)
272        {
273            rc = me->checkPipe(me->fCommPipe, false);
274            if (rc != kIOReturnSuccess)
275            {
276                XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)");
277            }
278        }
279    }
280
281    // Queue the next read, only if not aborted
282
283    if (rc != kIOReturnAborted)
284    {
285        ior = me->fCommPipe->Read(me->fCommPipeMDP, &me->fCommCompletionInfo, NULL);
286        if (ior != kIOReturnSuccess)
287        {
288            XTRACE(me, 0, rc, "commReadComplete - Read io error");
289            me->fCommDead = true;
290        }
291    }
292
293    return;
294
295}/* end commReadComplete */
296
297/****************************************************************************************************/
298//
299//		Method:		AppleUSBCDCECMControl::merWriteComplete
300//
301//		Inputs:		obj - me
302//				param - MER (may or may not be present depending on request)
303//				rc - return code
304//				remaining - what's left
305//
306//		Outputs:
307//
308//		Desc:		Management element request write completion routine
309//
310/****************************************************************************************************/
311
312void AppleUSBCDCECMControl::merWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
313{
314#if LDEBUG
315    AppleUSBCDCECMControl	*me = (AppleUSBCDCECMControl *)obj;
316#endif
317    IOUSBDevRequest		*MER = (IOUSBDevRequest*)param;
318    UInt16			dataLen;
319
320    if (MER)
321    {
322        if (rc == kIOReturnSuccess)
323        {
324            XTRACE(me, MER->bRequest, remaining, "merWriteComplete");
325        } else {
326            XTRACE(me, MER->bRequest, rc, "merWriteComplete - io err");
327        }
328
329        dataLen = MER->wLength;
330        XTRACE(me, 0, dataLen, "merWriteComplete - data length");
331        if ((dataLen != 0) && (MER->pData))
332        {
333            IOFree(MER->pData, dataLen);
334        }
335        IOFree(MER, sizeof(IOUSBDevRequest));
336
337    } else {
338        if (rc == kIOReturnSuccess)
339        {
340            XTRACE(me, 0, remaining, "merWriteComplete (request unknown)");
341        } else {
342            XTRACE(me, 0, rc, "merWriteComplete (request unknown) - io err");
343        }
344    }
345
346    return;
347
348}/* end merWriteComplete */
349
350/****************************************************************************************************/
351//
352//		Method:		AppleUSBCDCECMControl::statsWriteComplete
353//
354//		Inputs:		obj - me
355//				param - parameter block
356//				rc - return code
357//				remaining - what's left
358//
359//		Outputs:
360//
361//		Desc:		Ethernet statistics request write completion routine
362//
363/****************************************************************************************************/
364
365void AppleUSBCDCECMControl::statsWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
366{
367    AppleUSBCDCECMControl	*me = (AppleUSBCDCECMControl *)obj;
368    IOUSBDevRequest		*STREQ = (IOUSBDevRequest*)param;
369    UInt16			currStat;
370
371    if (STREQ)
372    {
373        if (rc == kIOReturnSuccess)
374        {
375            XTRACE(me, STREQ->bRequest, remaining, "statsWriteComplete");
376            currStat = STREQ->wValue;
377            switch(currStat)
378            {
379                case kXMIT_OK_REQ:
380                    me->fpNetStats->outputPackets = USBToHostLong(me->fStatValue);
381                    break;
382                case kRCV_OK_REQ:
383                    me->fpNetStats->inputPackets = USBToHostLong(me->fStatValue);
384                    break;
385                case kXMIT_ERROR_REQ:
386                    me->fpNetStats->outputErrors = USBToHostLong(me->fStatValue);
387                    break;
388                case kRCV_ERROR_REQ:
389                    me->fpNetStats->inputErrors = USBToHostLong(me->fStatValue);
390                    break;
391                case kRCV_CRC_ERROR_REQ:
392                    me->fpEtherStats->dot3StatsEntry.fcsErrors = USBToHostLong(me->fStatValue);
393                    break;
394                case kRCV_ERROR_ALIGNMENT_REQ:
395                    me->fpEtherStats->dot3StatsEntry.alignmentErrors = USBToHostLong(me->fStatValue);
396                    break;
397                case kXMIT_ONE_COLLISION_REQ:
398                    me->fpEtherStats->dot3StatsEntry.singleCollisionFrames = USBToHostLong(me->fStatValue);
399                    break;
400                case kXMIT_MORE_COLLISIONS_REQ:
401                    me->fpEtherStats->dot3StatsEntry.multipleCollisionFrames = USBToHostLong(me->fStatValue);
402                    break;
403                case kXMIT_DEFERRED_REQ:
404                    me->fpEtherStats->dot3StatsEntry.deferredTransmissions = USBToHostLong(me->fStatValue);
405                    break;
406                case kXMIT_MAX_COLLISION_REQ:
407                    me->fpNetStats->collisions = USBToHostLong(me->fStatValue);
408                    break;
409                case kRCV_OVERRUN_REQ:
410                    me->fpEtherStats->dot3StatsEntry.frameTooLongs = USBToHostLong(me->fStatValue);
411                    break;
412                case kXMIT_TIMES_CARRIER_LOST_REQ:
413                    me->fpEtherStats->dot3StatsEntry.carrierSenseErrors = USBToHostLong(me->fStatValue);
414                    break;
415                case kXMIT_LATE_COLLISIONS_REQ:
416                    me->fpEtherStats->dot3StatsEntry.lateCollisions = USBToHostLong(me->fStatValue);
417                    break;
418                default:
419                    XTRACE(me, currStat, rc, "statsWriteComplete - Invalid stats code");
420                    break;
421            }
422
423        } else {
424            XTRACE(me, STREQ->bRequest, rc, "statsWriteComplete - io err");
425        }
426
427        IOFree(STREQ, sizeof(IOUSBDevRequest));
428    } else {
429        if (rc == kIOReturnSuccess)
430        {
431            XTRACE(me, 0, remaining, "statsWriteComplete (request unknown)");
432        } else {
433            XTRACE(me, 0, rc, "statsWriteComplete (request unknown) - io err");
434        }
435    }
436
437    me->fStatValue = 0;
438    me->fStatInProgress = false;
439    return;
440
441}/* end statsWriteComplete */
442
443/****************************************************************************************************/
444//
445//		Method:		AppleUSBCDCECMControl::probe
446//
447//		Inputs:		provider - my provider
448//
449//		Outputs:	IOService - from super::probe, score - probe score
450//
451//		Desc:		Modify the probe score if necessary (we don't  at the moment)
452//
453/****************************************************************************************************/
454
455IOService* AppleUSBCDCECMControl::probe(IOService *provider, SInt32 *score)
456{
457    IOService   *res;
458
459		// If our IOUSBInterface has a "do not match" property, it means that we should not match and need
460		// to bail.  See rdar://3716623
461
462    OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface"));
463    if (boolObj && boolObj->isTrue())
464    {
465        XTRACE(this, 0, 0, "probe - provider doesn't want us to match");
466        return NULL;
467    }
468
469    res = super::probe(provider, score);
470
471    return res;
472
473}/* end probe */
474
475/****************************************************************************************************/
476//
477//		Method:		AppleUSBCDCECMControl::start
478//
479//		Inputs:		provider - my provider
480//
481//		Outputs:	Return code - true (it's me), false (sorry it probably was me, but I can't configure it)
482//
483//		Desc:		This is called once it has beed determined I'm probably the best
484//				driver for this device.
485//
486/****************************************************************************************************/
487
488bool AppleUSBCDCECMControl::start(IOService *provider)
489{
490	IOReturn	rtn;
491	UInt16		devDriverCount = 0;
492
493    XTRACE(this, 0, 0, "start");
494
495    fCurrStat = 0;
496	fCDCDriver = NULL;
497    fStatInProgress = false;
498    fMax_Block_Size = MAX_BLOCK_SIZE;
499    fCommDead = false;
500    fPacketFilter = kPACKET_TYPE_DIRECTED | kPACKET_TYPE_BROADCAST | kPACKET_TYPE_MULTICAST;
501    fpNetStats = NULL;
502    fpEtherStats = NULL;
503	fDataDriver = NULL;
504
505    if(!super::start(provider))
506    {
507        ALERT(0, 0, "start - super failed");
508        return false;
509    }
510
511    	// Get my USB provider - the interface
512
513    fControlInterface = OSDynamicCast(IOUSBInterface, provider);
514    if(!fControlInterface)
515    {
516        ALERT(0, 0, "start - provider invalid");
517        return false;
518    }
519
520		// See if we can find/wait for the CDC driver
521
522	while (!fCDCDriver)
523	{
524		rtn = kIOReturnSuccess;
525		fCDCDriver = findCDCDriverEC(this, &rtn);
526		if (fCDCDriver)
527		{
528			XTRACE (this, 0, fControlInterface->GetInterfaceNumber(), "start: Found the CDC device driver");
529			break;
530		} else {
531			if (rtn == kIOReturnNotReady)
532			{
533				devDriverCount++;
534				XTRACE(this, devDriverCount, fControlInterface->GetInterfaceNumber(), "start - Waiting for CDC device driver...");
535				if (devDriverCount > 9)
536				{
537					break;
538				}
539				IOSleep(100);
540			} else {
541				break;
542			}
543		}
544	}
545
546		// If we didn't find him then we have to bail
547
548	if (!fCDCDriver)
549	{
550		ALERT(0, fControlInterface->GetInterfaceNumber(), "start - Failed to find the CDC driver");
551        return false;
552	}
553
554    if (!configureECM())
555    {
556        ALERT(0, 0, "start - configureECM failed");
557        return false;
558    }
559
560    if (!allocateResources())
561    {
562        ALERT(0, 0, "start - allocateResources failed");
563        return false;
564    }
565
566	fControlInterface->retain();
567
568#if 0
569    if (!initForPM(provider))
570    {
571        ALERT(0, 0, "start - initForPM failed");
572        return false;
573    }
574#endif
575
576    registerService();
577
578    XTRACE(this, 0, 0, "start - successful");
579
580    return true;
581
582}/* end start */
583
584/****************************************************************************************************/
585//
586//		Method:		AppleUSBCDCECMControl::stop
587//
588//		Inputs:		provider - my provider
589//
590//		Outputs:
591//
592//		Desc:		Stops the driver
593//
594/****************************************************************************************************/
595
596void AppleUSBCDCECMControl::stop(IOService *provider)
597{
598
599    XTRACE(this, 0, 0, "stop");
600
601    releaseResources();
602
603//	PMstop();
604
605    super::stop(provider);
606
607    return;
608
609}/* end stop */
610
611/****************************************************************************************************/
612//
613//		Method:		AppleUSBCDCECMControl::configureECM
614//
615//		Inputs:
616//
617//		Outputs:	return Code - true (device configured), false (device not configured)
618//
619//		Desc:		Finds the configurations and then the appropriate interfaces etc.
620//
621/****************************************************************************************************/
622
623bool AppleUSBCDCECMControl::configureECM()
624{
625
626    XTRACE(this, 0, 0, "configureECM");
627
628    fCommInterfaceNumber = fControlInterface->GetInterfaceNumber();
629    XTRACE(this, 0, fCommInterfaceNumber, "configureECM - Comm interface number.");
630
631    if (!getFunctionalDescriptors())
632    {
633        ALERT(0, 0, "configureECM - getFunctionalDescriptors failed");
634//        releaseResources();
635        return false;
636    }
637
638    return true;
639
640}/* end configureECM */
641
642/****************************************************************************************************/
643//
644//		Method:		AppleUSBCDCECMControl::getFunctionalDescriptors
645//
646//		Inputs:
647//
648//		Outputs:	return - true (descriptors ok), false (somethings not right or not supported)
649//
650//		Desc:		Finds all the functional descriptors for the specific interface
651//
652/****************************************************************************************************/
653
654bool AppleUSBCDCECMControl::getFunctionalDescriptors()
655{
656    bool				gotDescriptors = false;
657    bool				configok = true;
658    bool				enet = false;
659    IOReturn				ior;
660    const HDRFunctionalDescriptor 	*funcDesc = NULL;
661    ECMFunctionalDescriptor		*ENETFDesc;
662    UnionFunctionalDescriptor		*UNNFDesc;
663    UInt8				serString;
664    char 				ascii_mac[14];
665    UInt16 				i;
666
667    XTRACE(this, 0, 0, "getFunctionalDescriptors");
668
669    do
670    {
671        funcDesc = (const HDRFunctionalDescriptor *)fControlInterface->FindNextAssociatedDescriptor((void*)funcDesc, CS_INTERFACE);
672        if (!funcDesc)
673        {
674            gotDescriptors = true;
675        } else {
676            switch (funcDesc->bDescriptorSubtype)
677            {
678                case Header_FunctionalDescriptor:
679                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Header Functional Descriptor");
680                    break;
681                case ECM_Functional_Descriptor:
682                    ENETFDesc = (ECMFunctionalDescriptor *)funcDesc;
683                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Ethernet Functional Descriptor");
684                    enet = true;
685                    break;
686                case Union_FunctionalDescriptor:
687                    UNNFDesc = (UnionFunctionalDescriptor *)funcDesc;
688                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - Union Functional Descriptor");
689                    if (UNNFDesc->bFunctionLength > sizeof(FunctionalDescriptorHeader))
690                    {
691                        fDataInterfaceNumber = UNNFDesc->bSlaveInterface[0];		// Use the first slave (may need to revisit)
692                    } else {
693                        XTRACE(this, UNNFDesc->bFunctionLength, 0, "getFunctionalDescriptors - Union descriptor length error");
694                    }
695                    break;
696                default:
697                    XTRACE(this, funcDesc->bDescriptorType, funcDesc->bDescriptorSubtype, "getFunctionalDescriptors - unknown Functional Descriptor");
698                    break;
699            }
700        }
701    } while(!gotDescriptors);
702
703    if (!enet)
704    {
705//        configok = false;					// The Enet Func. Desc.  must be present
706
707            // We're going to make some assumptions for now
708
709        fOutputPktsOK = true;
710        fInputPktsOK = true;
711        fOutputErrsOK = true;
712        fInputErrsOK = true;
713
714        fEthernetStatistics[0] = 0;
715        fEthernetStatistics[1] = 0;
716        fEthernetStatistics[2] = 0;
717        fEthernetStatistics[3] = 0;
718
719        fMcFilters = 0;
720
721        serString = fControlInterface->GetDevice()->GetSerialNumberStringIndex();	// Default to the serial number string
722        ior = fControlInterface->GetDevice()->GetStringDescriptor(serString, (char *)&ascii_mac, 13);
723        if (ior == kIOReturnSuccess)
724        {
725            for (i = 0; i < 6; i++)
726            {
727                fEaddr[i] = (Asciihex_to_binary(ascii_mac[i*2]) << 4) | Asciihex_to_binary(ascii_mac[i*2+1]);
728            }
729        } else {
730                ALERT(0, 0, "getFunctionalDescriptors - Error retrieving Ethernet address (serial string)");
731                configok = false;
732        }
733    } else {
734
735            // Determine who is collecting the input/output network stats.
736
737        if (!(ENETFDesc->bmEthernetStatistics[0] & kXMIT_OK))
738        {
739            fOutputPktsOK = true;
740        } else {
741            fOutputPktsOK = false;
742        }
743        if (!(ENETFDesc->bmEthernetStatistics[0] & kRCV_OK))
744        {
745            fInputPktsOK = true;
746        } else {
747            fInputPktsOK = false;
748        }
749        if (!(ENETFDesc->bmEthernetStatistics[0] & kXMIT_ERROR))
750        {
751            fOutputErrsOK = true;
752        } else {
753            fOutputErrsOK = false;
754        }
755        if (!(ENETFDesc->bmEthernetStatistics[0] & kRCV_ERROR))
756        {
757            fInputErrsOK = true;
758        } else {
759            fInputErrsOK = false;
760        }
761
762            // Save the stats (it's bit mapped)
763
764        fEthernetStatistics[0] = ENETFDesc->bmEthernetStatistics[0];
765        fEthernetStatistics[1] = ENETFDesc->bmEthernetStatistics[1];
766        fEthernetStatistics[2] = ENETFDesc->bmEthernetStatistics[2];
767        fEthernetStatistics[3] = ENETFDesc->bmEthernetStatistics[3];
768
769            // Save the multicast filters (remember it's intel format)
770
771        fMcFilters = USBToHostWord(ENETFDesc->wNumberMCFilters);
772
773            // Get the Ethernet address
774
775        if (ENETFDesc->iMACAddress != 0)
776        {
777            ior = fControlInterface->GetDevice()->GetStringDescriptor(ENETFDesc->iMACAddress, (char *)&ascii_mac, 13);
778            if (ior == kIOReturnSuccess)
779            {
780                for (i = 0; i < 6; i++)
781                {
782                    fEaddr[i] = (Asciihex_to_binary(ascii_mac[i*2]) << 4) | Asciihex_to_binary(ascii_mac[i*2+1]);
783                }
784                fMax_Block_Size = USBToHostWord(ENETFDesc->wMaxSegmentSize);
785                XTRACE(this, 0, fMax_Block_Size, "getFunctionalDescriptors - Maximum segment size");
786            } else {
787                ALERT(0, 0, "getFunctionalDescriptors - Error retrieving Ethernet address");
788                configok = false;
789            }
790        } else {
791            ALERT(0, 0, "getFunctionalDescriptors - Ethernet address is zero");
792            configok = false;
793        }
794    }
795
796    return configok;
797
798}/* end getFunctionalDescriptors */
799
800/****************************************************************************************************/
801//
802//		Method:		AppleUSBCDCECMControl::dataAcquired
803//
804//		Inputs:		netStats - Network statistics structure address
805//				etherStats - Ethernet statistics structure address
806//
807//		Outputs:	return Code - true (it worked), false (it didn't)
808//
809//		Desc:		Tells this driver the data driver's port has been acquired
810//
811/****************************************************************************************************/
812
813bool AppleUSBCDCECMControl::dataAcquired(IONetworkStats *netStats, IOEthernetStats *etherStats)
814{
815    IOReturn 	rtn = kIOReturnSuccess;
816
817    XTRACE(this, 0, 0, "dataAcquired");
818
819            // Read the comm interrupt pipe for status (if we have one)
820
821    fCommCompletionInfo.target = this;
822    fCommCompletionInfo.action = commReadComplete;
823    fCommCompletionInfo.parameter = NULL;
824
825    if (fCommPipe)
826    {
827        rtn = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL);
828    }
829    //radar://11946906
830    /*
831    else {
832		if (fDataDriver)
833		{
834			fDataDriver->fLinkStatus = fLinkStatus;
835		}
836	}
837    */
838    if (rtn == kIOReturnSuccess)
839    {
840
841            // Set up the management Element Request completion routine
842
843        fMERCompletionInfo.target = this;
844        fMERCompletionInfo.action = merWriteComplete;
845        fMERCompletionInfo.parameter = NULL;
846
847            // Set up the statistics request completion routine:
848
849        fStatsCompletionInfo.target = this;
850        fStatsCompletionInfo.action = statsWriteComplete;
851        fStatsCompletionInfo.parameter = NULL;
852
853     } else {
854        XTRACE(this, 0, rtn, "dataAcquired - Reading the interrupt pipe failed");
855        return false;
856    }
857
858    fpNetStats = netStats;
859    fpEtherStats = etherStats;
860
861    fdataAcquired = true;
862
863    return true;
864
865}/* end dataAcquired */
866
867/****************************************************************************************************/
868//
869//		Method:		AppleUSBCDCECMControl::dataReleased
870//
871//		Inputs:		None
872//
873//		Outputs:	None
874//
875//		Desc:		Tells this driver the data driver's port has been released
876//
877/****************************************************************************************************/
878
879void AppleUSBCDCECMControl::dataReleased()
880{
881
882    XTRACE(this, 0, 0, "dataReleased");
883
884	if (fCommPipe)
885	{
886		fCommPipe->Abort();
887	}
888    fdataAcquired = false;
889
890}/* end dataReleased */
891
892/****************************************************************************************************/
893//
894//		Method:		AppleUSBCDCECMControl::allocateResources
895//
896//		Inputs:
897//
898//		Outputs:	return code - true (allocate was successful), false (it failed)
899//
900//		Desc:		Finishes up the rest of the configuration and gets all the endpoints open etc.
901//
902/****************************************************************************************************/
903
904bool AppleUSBCDCECMControl::allocateResources()
905{
906    IOUSBFindEndpointRequest	epReq;
907
908    XTRACE(this, 0, 0, "allocateResources.");
909
910        // Open the end point and get the buffers
911
912    if (!fControlInterface->open(this))
913    {
914        ALERT(0, 0, "allocateResources - open comm interface failed.");
915        return false;
916    }
917        // Interrupt pipe
918
919    epReq.type = kUSBInterrupt;
920    epReq.direction = kUSBIn;
921    fCommPipe = fControlInterface->FindNextPipe(0, &epReq);
922    if (!fCommPipe)
923    {
924        XTRACE(this, 0, 0, "allocateResources - no interrupt in pipe.");
925        fCommPipeMDP = NULL;
926        fCommPipeBuffer = NULL;
927        fLinkStatus = 1;					// Mark it active cause we'll never get told
928    } else {
929        XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - comm pipe.");
930
931            // Allocate Memory Descriptor Pointer with memory for the Interrupt pipe:
932
933        fCommPipeMDP = IOBufferMemoryDescriptor::withCapacity(COMM_BUFF_SIZE, kIODirectionIn);
934        if (!fCommPipeMDP)
935        {
936            XTRACE(this, 0, 0, "allocateResources - Couldn't allocate MDP for interrupt pipe");
937            return false;
938        }
939
940        fCommPipeBuffer = (UInt8*)fCommPipeMDP->getBytesNoCopy();
941        XTRACEP(this, 0, fCommPipeBuffer, "allocateResources - comm buffer");
942    }
943
944    return true;
945
946}/* end allocateResources */
947
948/****************************************************************************************************/
949//
950//		Method:		AppleUSBCDCECMControl::releaseResources
951//
952//		Inputs:
953//
954//		Outputs:
955//
956//		Desc:		Frees up the resources allocated in allocateResources
957//
958/****************************************************************************************************/
959
960void AppleUSBCDCECMControl::releaseResources()
961{
962    XTRACE(this, 0, 0, "releaseResources");
963
964    if (fControlInterface)
965    {
966        fControlInterface->close(this);
967        fControlInterface->release();
968        fControlInterface = NULL;
969    }
970
971    if (fCommPipeMDP)
972    {
973        fCommPipeMDP->release();
974        fCommPipeMDP = 0;
975    }
976
977}/* end releaseResources */
978
979/****************************************************************************************************/
980//
981//		Method:		AppleUSBCDCECMControl::USBSetMulticastFilter
982//
983//		Inputs:		addrs - the list of addresses
984//				count - How many
985//
986//		Outputs:
987//
988//		Desc:		Set up and send SetMulticastFilter Management Element Request(MER).
989//
990/****************************************************************************************************/
991
992bool AppleUSBCDCECMControl::USBSetMulticastFilter(IOEthernetAddress *addrs, UInt32 count)
993{
994    IOReturn		rc;
995    IOUSBDevRequest	*MER;
996    UInt8		*eaddrs;
997    UInt32		eaddLen;
998    UInt32		i,j,rnum;
999
1000    XTRACE(this, fMcFilters, count, "USBSetMulticastFilter");
1001
1002    if (!fControlInterface)
1003    {
1004        XTRACE(this, fMcFilters, count, "USBSetMulticastFilter - Control interface has gone");
1005        return true;
1006    }
1007
1008    if (count > (UInt32)(fMcFilters & kFiltersSupportedMask))
1009    {
1010        XTRACE(this, 0, 0, "USBSetMulticastFilter - No multicast filters supported");
1011        return false;
1012    }
1013
1014    MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest));
1015    if (!MER)
1016    {
1017        XTRACE(this, 0, 0, "USBSetMulticastFilter - allocate MER failed");
1018        return false;
1019    }
1020    bzero(MER, sizeof(IOUSBDevRequest));
1021
1022    eaddLen = count * kIOEthernetAddressSize;
1023    eaddrs = (UInt8 *)IOMalloc(eaddLen);
1024    if (!eaddrs)
1025    {
1026        XTRACE(this, 0, 0, "USBSetMulticastFilter - allocate address buffer failed");
1027        return false;
1028    }
1029    bzero(eaddrs, eaddLen);
1030
1031        // Build the filter address buffer
1032
1033    rnum = 0;
1034    for (i=0; i<count; i++)
1035    {
1036        if (rnum > eaddLen)				// Just in case
1037        {
1038            break;
1039        }
1040        for (j=0; j<kIOEthernetAddressSize; j++)
1041        {
1042            eaddrs[rnum++] = addrs[i].bytes[j];
1043        }
1044    }
1045
1046        // Now build the Management Element Request
1047
1048    MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
1049    MER->bRequest = kSet_Ethernet_Multicast_Filter;
1050    MER->wValue = count;
1051    MER->wIndex = fCommInterfaceNumber;
1052    MER->wLength = eaddLen;
1053    MER->pData = eaddrs;
1054
1055    fMERCompletionInfo.parameter = MER;
1056
1057    rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo);
1058    if (rc != kIOReturnSuccess)
1059    {
1060        XTRACE(this, MER->bRequest, rc, "USBSetMulticastFilter - Error issueing DeviceRequest");
1061        IOFree(MER->pData, eaddLen);
1062        IOFree(MER, sizeof(IOUSBDevRequest));
1063        return false;
1064    }
1065
1066    return true;
1067
1068}/* end USBSetMulticastFilter */
1069
1070/****************************************************************************************************/
1071//
1072//		Method:		AppleUSBCDCECMControl::USBSetPacketFilter
1073//
1074//		Inputs:
1075//
1076//		Outputs:
1077//
1078//		Desc:		Set up and send SetEthernetPackettFilters Management Element Request(MER).
1079//
1080/****************************************************************************************************/
1081
1082bool AppleUSBCDCECMControl::USBSetPacketFilter()
1083{
1084    IOReturn		rc;
1085    IOUSBDevRequest	*MER;
1086
1087    XTRACE(this, 0, fPacketFilter, "USBSetPacketFilter");
1088
1089    if (!fControlInterface)
1090    {
1091        XTRACE(this, 0, fPacketFilter, "USBSetPacketFilter - Control interface has gone");
1092        return true;
1093    }
1094
1095    MER = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest));
1096    if (!MER)
1097    {
1098        XTRACE(this, 0, 0, "USBSetPacketFilter - allocate MER failed");
1099        return false;
1100    }
1101    bzero(MER, sizeof(IOUSBDevRequest));
1102
1103        // Now build the Management Element Request
1104
1105    MER->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
1106    MER->bRequest = kSet_Ethernet_Packet_Filter;
1107    MER->wValue = fPacketFilter;
1108    MER->wIndex = fCommInterfaceNumber;
1109    MER->wLength = 0;
1110    MER->pData = NULL;
1111
1112    fMERCompletionInfo.parameter = MER;
1113
1114    rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo);
1115    if (rc != kIOReturnSuccess)
1116    {
1117        XTRACE(this, MER->bRequest, rc, "USBSetPacketFilter - DeviceRequest error");
1118        if (rc == kIOUSBPipeStalled)
1119        {
1120
1121            // Clear the stall and try it once more
1122
1123            fControlInterface->GetDevice()->GetPipeZero()->ClearPipeStall(false);
1124            rc = fControlInterface->GetDevice()->DeviceRequest(MER, &fMERCompletionInfo);
1125            if (rc != kIOReturnSuccess)
1126            {
1127                XTRACE(this, MER->bRequest, rc, "USBSetPacketFilter - DeviceRequest, error a second time");
1128                IOFree(MER, sizeof(IOUSBDevRequest));
1129                return false;
1130            }
1131        }
1132    }
1133
1134    return true;
1135
1136}/* end USBSetPacketFilter */
1137
1138/****************************************************************************************************/
1139//
1140//		Method:		AppleUSBCDCECMControl::checkInterfaceNumber
1141//
1142//		Inputs:		dataDriver - the data driver enquiring
1143//
1144//		Outputs:
1145//
1146//		Desc:		Called by the data driver to ask if this is the correct
1147//				control interface driver.
1148//
1149/****************************************************************************************************/
1150
1151bool AppleUSBCDCECMControl::checkInterfaceNumber(AppleUSBCDCECMData *dataDriver)
1152{
1153    IOUSBInterface	*dataInterface;
1154
1155    XTRACEP(this, 0, dataDriver, "checkInterfaceNumber");
1156
1157        // First check we have the same provider (Device)
1158
1159    dataInterface = OSDynamicCast(IOUSBInterface, dataDriver->getProvider());
1160    if (dataInterface == NULL)
1161    {
1162        XTRACE(this, 0, 0, "checkInterfaceNumber - Error getting Data provider");
1163        return FALSE;
1164    }
1165
1166    XTRACEP(this, dataInterface->GetDevice(), fControlInterface->GetDevice(), "checkInterfaceNumber - Checking device");
1167    if (dataInterface->GetDevice() == fControlInterface->GetDevice())
1168    {
1169
1170            // Then check to see if it's the correct data interface number
1171
1172        if (dataDriver->fDataInterfaceNumber == fDataInterfaceNumber)
1173        {
1174            fDataDriver = dataDriver;
1175            return true;
1176        } else {
1177            XTRACE(this, dataDriver->fDataInterfaceNumber, fDataInterfaceNumber, "checkInterfaceNumber - Not correct interface number");
1178        }
1179    } else {
1180        XTRACE(this, 0, 0, "checkInterfaceNumber - Not correct device");
1181    }
1182
1183    return false;
1184
1185}/* end checkInterfaceNumber */
1186
1187/****************************************************************************************************/
1188//
1189//		Method:		AppleUSBCDCECMControl::checkPipe
1190//
1191//		Inputs:		thePipe - the pipe
1192//				devReq - true(send CLEAR_FEATURE), false(only if status returns stalled)
1193//
1194//		Outputs:
1195//
1196//		Desc:		Clear a stall on the specified pipe. If ClearPipeStall is issued
1197//				all outstanding I/O is returned with kIOUSBTransactionReturned and
1198//				a CLEAR_FEATURE Endpoint stall is sent.
1199//
1200/****************************************************************************************************/
1201
1202IOReturn AppleUSBCDCECMControl::checkPipe(IOUSBPipe *thePipe, bool devReq)
1203{
1204    IOReturn 	rtn = kIOReturnSuccess;
1205
1206    XTRACEP(this, 0, thePipe, "checkPipe");
1207
1208    if (!devReq)
1209    {
1210        rtn = thePipe->GetPipeStatus();
1211        if (rtn != kIOUSBPipeStalled)
1212        {
1213            XTRACE(this, 0, 0, "checkPipe - Pipe not stalled");
1214            return rtn;
1215        }
1216    }
1217
1218    rtn = thePipe->ClearPipeStall(true);
1219    if (rtn == kIOReturnSuccess)
1220    {
1221        XTRACE(this, 0, 0, "checkPipe - ClearPipeStall Successful");
1222    } else {
1223        XTRACE(this, 0, rtn, "checkPipe - ClearPipeStall Failed");
1224    }
1225
1226    return rtn;
1227
1228}/* end checkPipe */
1229
1230/****************************************************************************************************/
1231//
1232//		Method:		AppleUSBCDCECMControl::statsProcessing
1233//
1234//		Inputs:
1235//
1236//		Outputs:
1237//
1238//		Desc:		Handles stats gathering.
1239//
1240/****************************************************************************************************/
1241
1242bool AppleUSBCDCECMControl::statsProcessing()
1243{
1244    UInt32		*enetStats;
1245    UInt16		currStat;
1246    IOReturn		rc;
1247    IOUSBDevRequest	*STREQ;
1248    bool		statOk = false;
1249
1250//    XTRACE(this, 0, 0, "statsProcessing");
1251
1252    enetStats = (UInt32 *)&fEthernetStatistics;
1253    if (*enetStats == 0)
1254    {
1255        XTRACE(this, 0, 0, "statsProcessing - No Ethernet statistics defined");
1256        return false;						// and don't bother us again
1257    }
1258
1259    if ((fpNetStats == NULL) || (fpEtherStats == NULL))		// Means we're not ready yet
1260    {
1261        XTRACE(this, 0, 0, "statsProcessing - Not ready");
1262        return true;
1263    }
1264
1265    if (fReady == false)
1266    {
1267        XTRACE(this, 0, 0, "statsProcessing - Spurious");
1268    } else {
1269
1270            // Only do it if it's not already in progress
1271
1272        if (!fStatInProgress)
1273        {
1274
1275                // Check if the stat we're currently interested in is supported
1276
1277            currStat = stats[fCurrStat++];
1278            if (fCurrStat >= numStats)
1279            {
1280                fCurrStat = 0;
1281            }
1282            switch(currStat)
1283            {
1284                case kXMIT_OK_REQ:
1285                    if (fEthernetStatistics[0] & kXMIT_OK)
1286                    {
1287                        statOk = true;
1288                    }
1289                    break;
1290                case kRCV_OK_REQ:
1291                    if (fEthernetStatistics[0] & kRCV_OK)
1292                    {
1293                        statOk = true;
1294                    }
1295                    break;
1296                case kXMIT_ERROR_REQ:
1297                    if (fEthernetStatistics[0] & kXMIT_ERROR_REQ)
1298                    {
1299                        statOk = true;
1300                    }
1301                    break;
1302                case kRCV_ERROR_REQ:
1303                    if (fEthernetStatistics[0] & kRCV_ERROR_REQ)
1304                    {
1305                        statOk = true;
1306                    }
1307                    break;
1308                case kRCV_CRC_ERROR_REQ:
1309                    if (fEthernetStatistics[2] & kRCV_CRC_ERROR)
1310                    {
1311                        statOk = true;
1312                    }
1313                    break;
1314                case kRCV_ERROR_ALIGNMENT_REQ:
1315                    if (fEthernetStatistics[2] & kRCV_ERROR_ALIGNMENT)
1316                    {
1317                        statOk = true;
1318                    }
1319                    break;
1320                case kXMIT_ONE_COLLISION_REQ:
1321                    if (fEthernetStatistics[2] & kXMIT_ONE_COLLISION)
1322                    {
1323                        statOk = true;
1324                    }
1325                    break;
1326                case kXMIT_MORE_COLLISIONS_REQ:
1327                    if (fEthernetStatistics[2] & kXMIT_MORE_COLLISIONS)
1328                    {
1329                        statOk = true;
1330                    }
1331                    break;
1332                case kXMIT_DEFERRED_REQ:
1333                    if (fEthernetStatistics[2] & kXMIT_DEFERRED)
1334                    {
1335                        statOk = true;
1336                    }
1337                    break;
1338                case kXMIT_MAX_COLLISION_REQ:
1339                    if (fEthernetStatistics[2] & kXMIT_MAX_COLLISION)
1340                    {
1341                        statOk = true;
1342                    }
1343                    break;
1344                case kRCV_OVERRUN_REQ:
1345                    if (fEthernetStatistics[3] & kRCV_OVERRUN)
1346                    {
1347                        statOk = true;
1348                    }
1349                    break;
1350                case kXMIT_TIMES_CARRIER_LOST_REQ:
1351                    if (fEthernetStatistics[3] & kXMIT_TIMES_CARRIER_LOST)
1352                    {
1353                        statOk = true;
1354                    }
1355                    break;
1356                case kXMIT_LATE_COLLISIONS_REQ:
1357                    if (fEthernetStatistics[3] & kXMIT_LATE_COLLISIONS)
1358                    {
1359                        statOk = true;
1360                    }
1361                    break;
1362                default:
1363                    break;
1364            }
1365        }
1366
1367        if (statOk)
1368        {
1369            STREQ = (IOUSBDevRequest*)IOMalloc(sizeof(IOUSBDevRequest));
1370            if (!STREQ)
1371            {
1372                XTRACE(this, 0, 0, "statsProcessing - allocate STREQ failed");
1373            } else {
1374                bzero(STREQ, sizeof(IOUSBDevRequest));
1375
1376                    // Now build the Statistics Request
1377
1378                STREQ->bmRequestType = USBmakebmRequestType(kUSBOut, kUSBClass, kUSBInterface);
1379                STREQ->bRequest = kGet_Ethernet_Statistics;
1380                STREQ->wValue = currStat;
1381                STREQ->wIndex = fCommInterfaceNumber;
1382                STREQ->wLength = 4;
1383                STREQ->pData = &fStatValue;
1384
1385                fStatsCompletionInfo.parameter = STREQ;
1386
1387                rc = fControlInterface->GetDevice()->DeviceRequest(STREQ, &fStatsCompletionInfo);
1388                if (rc != kIOReturnSuccess)
1389                {
1390                    XTRACE(this, STREQ->bRequest, rc, "statsProcessing - Error issueing DeviceRequest");
1391                    IOFree(STREQ, sizeof(IOUSBDevRequest));
1392                } else {
1393                    fStatInProgress = true;
1394                }
1395            }
1396        }
1397    }
1398
1399    return true;
1400
1401}/* end statsProcessing */
1402
1403/****************************************************************************************************/
1404//
1405//		Method:		AppleUSBCDCECMControl::message
1406//
1407//		Inputs:		type - message type
1408//				provider - my provider
1409//				argument - additional parameters
1410//
1411//		Outputs:	return Code - kIOReturnSuccess
1412//
1413//		Desc:		Handles IOKit messages.
1414//
1415/****************************************************************************************************/
1416
1417IOReturn AppleUSBCDCECMControl::message(UInt32 type, IOService *provider, void *argument)
1418{
1419    IOReturn	ior;
1420
1421    XTRACE(this, 0, type, "message");
1422
1423    switch (type)
1424    {
1425        case kIOMessageServiceIsTerminated:
1426            XTRACE(this, 0, type, "message - kIOMessageServiceIsTerminated");
1427			if (fDataDriver)
1428			{
1429				fDataDriver->message(kIOMessageServiceIsTerminated, fControlInterface, NULL);
1430			}
1431            fTerminate = true;		// we're being terminated (unplugged)
1432            releaseResources();
1433            return kIOReturnSuccess;
1434        case kIOMessageServiceIsSuspended:
1435            XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended");
1436            break;
1437        case kIOMessageServiceIsResumed:
1438            XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed");
1439            break;
1440        case kIOMessageServiceIsRequestingClose:
1441            XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose");
1442            break;
1443        case kIOMessageServiceWasClosed:
1444            XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed");
1445            break;
1446        case kIOMessageServiceBusyStateChange:
1447            XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange");
1448            break;
1449        case kIOUSBMessagePortHasBeenResumed:
1450            XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed");
1451            if (fCommDead)					// If it's dead try and resurrect it
1452            {
1453                ior = fCommPipe->Read(fCommPipeMDP, &fCommCompletionInfo, NULL);
1454                if (ior != kIOReturnSuccess)
1455                {
1456                    XTRACE(this, 0, ior, "message - Read io error");
1457                } else {
1458                    fCommDead = false;
1459                }
1460            }
1461            return kIOReturnSuccess;
1462        case kIOUSBMessageHubResumePort:
1463            XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort");
1464            break;
1465        default:
1466            XTRACE(this, 0, type, "message - unknown message");
1467            break;
1468    }
1469
1470    return super::message(type, provider, argument);
1471
1472}/* end message */
1473
1474#if 0
1475/****************************************************************************************************/
1476//
1477//		Method:		AppleUSBCDCECMControl::initForPM
1478//
1479//		Inputs:		provider - my provider
1480//
1481//		Outputs:	return code - true(initialized), false(failed)
1482//
1483//		Desc:		Add ourselves to the power management tree so we can do
1484//				the right thing on sleep/wakeup.
1485//
1486/****************************************************************************************************/
1487
1488bool AppleUSBCDCECMControl::initForPM(IOService *provider)
1489{
1490    XTRACE(this, 0, 0, "initForPM");
1491
1492    fPowerState = kCDCPowerOnState;				// init our power state to be 'on'
1493    PMinit();							// init power manager instance variables
1494    provider->joinPMtree(this);					// add us to the power management tree
1495    if (pm_vars != NULL)
1496    {
1497
1498            // register ourselves with ourself as policy-maker
1499
1500        registerPowerDriver(this, gOurPowerStates, kNumCDCStates);
1501        return true;
1502    } else {
1503        ALERT(0, 0, "initForPM - Initializing power manager failed");
1504    }
1505
1506    return false;
1507
1508}/* end initForPM */
1509
1510/****************************************************************************************************/
1511//
1512//		Method:		AppleUSBCDCECMControl::initialPowerStateForDomainState
1513//
1514//		Inputs:		flags -
1515//
1516//		Outputs:	return code - Current power state
1517//
1518//		Desc:		Request for our initial power state.
1519//
1520/****************************************************************************************************/
1521
1522unsigned long AppleUSBCDCECMControl::initialPowerStateForDomainState(IOPMPowerFlags flags)
1523{
1524
1525    XTRACE(this, 0, flags, "initialPowerStateForDomainState");
1526
1527    return fPowerState;
1528
1529}/* end initialPowerStateForDomainState */
1530
1531/****************************************************************************************************/
1532//
1533//		Method:		AppleUSBCDCECMControl::setPowerState
1534//
1535//		Inputs:		powerStateOrdinal - on/off
1536//
1537//		Outputs:	return code - IOPMNoErr, IOPMAckImplied or IOPMNoSuchState
1538//
1539//		Desc:		Request to turn device on or off.
1540//
1541/****************************************************************************************************/
1542
1543IOReturn AppleUSBCDCECMControl::setPowerState(unsigned long powerStateOrdinal, IOService *whatDevice)
1544{
1545
1546    XTRACE(this, 0, powerStateOrdinal, "setPowerState");
1547
1548    if (powerStateOrdinal == kCDCPowerOffState || powerStateOrdinal == kCDCPowerOnState)
1549    {
1550        if (powerStateOrdinal == fPowerState)
1551            return IOPMAckImplied;
1552
1553        fPowerState = powerStateOrdinal;
1554        if (fPowerState == kCDCPowerOnState)
1555        {
1556			if (fDataDriver)
1557			{
1558				fDataDriver->fResetState = kResetNeeded;
1559				fDataDriver->fReady = FALSE;
1560			}
1561        }
1562
1563        return IOPMAckImplied;
1564    }
1565
1566    return IOPMAckImplied;
1567
1568}/* end setPowerState */
1569#endif