//--------------------------------------------------------------------------------
//
//	File:		AppleUSBAudioDevice.h
//
//	Contains:	Support for the USB Audio Class Control Interface.
//
//	Technology:	OS X
//
//--------------------------------------------------------------------------------

#ifndef _APPLEUSBAUDIODEVICE_H
#define _APPLEUSBAUDIODEVICE_H

#include <libkern/c++/OSCollectionIterator.h>

#include <IOKit/IOLocks.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOKitKeys.h>
#include <IOKit/IORegistryEntry.h>
#include <IOKit/IOMessage.h>

#include <IOKit/audio/IOAudioDevice.h>
#include <IOKit/audio/IOAudioEngine.h>
#include <IOKit/audio/IOAudioPort.h>
#include <IOKit/audio/IOAudioControl.h>
#include <IOKit/audio/IOAudioStream.h>
#include <IOKit/audio/IOAudioDefines.h>
#include <IOKit/audio/IOAudioSelectorControl.h>

#include <IOKit/usb/USB.h>
#include <IOKit/usb/IOUSBInterface.h>
#include <IOKit/usb/IOUSBRootHubDevice.h>

//#include "AppleUSBAudioMuteControl.h"
//#include "AppleUSBAudioLevelControl.h"
#include "AppleUSBAudioEngine.h"
#include "AppleUSBAudioCommon.h"
#include "USBAudioObject.h"

#define kStringBufferSize				255

enum {
	kIOUSBVendorIDHaronKardon			= 0x074D,
	kIOUSBVendorMicronas				= 0x05FC
};

enum {
	kVolumeControl						= 1,
	kMuteControl						= 2
};

enum {
	kStudioDisplay15CRT					= 0x9115,
	kStudioDisplay17CRT					= 0x9113,
	kCinemaDisplay						= 0x9116,
	kStudioDisplay17FP					= 0x9117
};

class IOUSBInterface;
class AppleUSBAudioEngine;

/*
 * @class AppleUSBAudioDevice
 * @abstract : universal Apple USB driver
 * @discussion : Current version of the driver deals with outputing stereo 16 bits data at 44100kHz
 * It's gonna create an AppleUSBAudioEngine, and a serie
 */

#define kEngine							"engine"
#define kInterface						"interface"
#define kAltSetting						"altsetting"
#define kInputGainControls				"inputgaincontrols"
#define kInputMuteControls				"inputmutecontrols"
#define kPassThruVolControls			"passthrucontrols"
#define kOutputVolControls				"outputvolcontrols"
#define kPassThruPathsArray				"passthrupathsarray"

class AppleUSBAudioDevice : public IOAudioDevice {
    OSDeclareDefaultStructors (AppleUSBAudioDevice);

public:
    IOUSBInterface *					mControlInterface;

protected:
    USBAudioConfigObject *				mUSBAudioConfig;
	OSArray *							mControlGraph;
    IORecursiveLock *					mInterfaceLock;
	Boolean								mTerminatingDriver;
	thread_call_t						mInitHardwareThread;

	OSArray *							mRegisteredEngines;

public:
	virtual	bool			start (IOService * provider);
    virtual	void			free ();
    virtual	void			stop (IOService *provider);
	virtual	bool			initHardware (IOService * provider);
	static	void			initHardwareThread (AppleUSBAudioDevice * aua, void * provider);
	static	IOReturn		initHardwareThreadAction (OSObject * owner, void * provider, void * arg2, void * arg3, void * arg4);
	virtual	IOReturn		protectedInitHardware (IOService * provider);
	virtual	Boolean			ShouldUpdatePRAM (void);
			Boolean			FindSoundNode (void);
    virtual	IOReturn		message (UInt32 type, IOService * provider, void * arg);
	virtual	bool			ControlsStreamNumber (UInt8 streamNumber);
	virtual	IOReturn		createControlsForInterface (IOAudioEngine *audioEngine, UInt8 interfaceNum, UInt8 altSettingNum);
	virtual void			setConfigurationApp (const char *bundleID);
	virtual	IOReturn		performPowerStateChange (IOAudioDevicePowerState oldPowerState, IOAudioDevicePowerState newPowerState, UInt32 *microSecsUntilComplete);
    virtual	USBAudioConfigObject * GetUSBAudioConfigObject (void) {return mUSBAudioConfig;}
	virtual	bool			willTerminate (IOService * provider, IOOptionBits options);
//	virtual	OSArray * 		FindSelectorUnitsInPath (UInt8 controlInterfaceNum, UInt8 startingUnitID);
//	virtual	OSArray * 		FindAllInputSources (OSArray * completeGraph, UInt8 outputTerminalID, Boolean forOutput);
	virtual	OSArray * 		BuildConnectionGraph (UInt8 controlInterfaceNum);
	virtual	OSArray * 		BuildPath (UInt8 controlInterfaceNum, UInt8 startingUnitID, OSArray *allPaths, OSArray * thisPath);
	virtual	char * 			TerminalTypeString (UInt16 terminalType);

	virtual	SInt32			getEngineInfoIndex (AppleUSBAudioEngine * inAudioEngine);
	virtual	IOReturn		doControlStuff (IOAudioEngine *audioEngine, UInt8 interfaceNum, UInt8 altSettingNum);
	virtual	IOReturn		doPlaythroughSetup (AppleUSBAudioEngine * usbAudioEngine, OSArray * playThroughPaths, UInt8 interfaceNum, UInt8 altSettingNum);
	virtual	IOReturn		addSelectorSourcesToSelectorControl (IOAudioSelectorControl * theSelectorControl, OSArray * arrayOfPathsFromOutputTerminal, UInt32 pathsToOutputTerminalN, UInt8 selectorIndex);
	virtual	OSString *		getNameForPath (OSArray * arrayOfPathsFromOutputTerminal, UInt32 * pathIndex, UInt8 startingPoint);
	virtual	OSString *		getNameForMixerPath (OSArray * arrayOfPathsFromOutputTerminal, UInt32 * pathIndex, UInt8 startingPoint);

	static	IOReturn		controlChangedHandler (OSObject *target, IOAudioControl *audioControl, SInt32 oldValue, SInt32 newValue);
	virtual	IOReturn		protectedControlChangedHandler (IOAudioControl *audioControl, SInt32 oldValue, SInt32 newValue);
	virtual	IOReturn		doSelectorControlChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue);
	virtual	UInt8			getSelectorSetting (UInt8 selectorID);
	virtual	IOReturn		setSelectorSetting (UInt8 selectorID, UInt8 setting);
	virtual	SInt16			getFeatureUnitSetting (UInt8 controlSelector, UInt8 unitID, UInt8 channelNumber, UInt8 requestType);
	virtual	IOReturn		setFeatureUnitSetting (UInt8 controlSelector, UInt8 unitID, UInt8 channelNumber, UInt8 requestType, UInt16 newValue, UInt16 newValueLen);
	virtual	OSArray *		getPlaythroughPaths ();
	virtual	UInt8			getBestFeatureUnitInPath (OSArray * thePath, UInt32 direction, UInt8 interfaceNum, UInt8 altSettingNum, UInt32 controlTypeWanted);
	virtual	void			addVolumeControls (AppleUSBAudioEngine * usbAudioEngine, UInt8 featureUnitID, UInt8 interfaceNum, UInt8 altSettingNum, UInt32 usage);
	virtual	void			addMuteControl (AppleUSBAudioEngine * usbAudioEngine, UInt8 featureUnitID, UInt8 interfaceNum, UInt8 altSettingNum, UInt32 usage);
	virtual	SInt16			getCurMute (UInt8 unitID, UInt8 channelNumber);
	virtual	SInt16			getCurVolume (UInt8 unitID, UInt8 channelNumber);
	virtual	SInt16			getMaxVolume (UInt8 unitID, UInt8 channelNumber);
	virtual	SInt16			getMinVolume (UInt8 unitID, UInt8 channelNumber);
	virtual	UInt16			getVolumeResolution (UInt8 unitID, UInt8 channelNumber);
	virtual	IOReturn		setCurVolume (UInt8 unitID, UInt8 channelNumber, SInt16 volume);
	virtual	IOReturn		setCurMute (UInt8 unitID, UInt8 channelNumber, SInt16 mute);
	virtual	IOReturn		doInputSelectorChange (IOAudioControl *audioControl, SInt32 oldValue, SInt32 newValue);
	virtual	IOReturn		doVolumeControlChange (IOAudioControl *audioControl, SInt32 oldValue, SInt32 newValue);
	virtual	IOReturn		doToggleControlChange (IOAudioControl *audioControl, SInt32 oldValue, SInt32 newValue);
	virtual IOReturn		doPassThruSelectorChange (IOAudioControl * audioControl, SInt32 oldValue, SInt32 newValue);
	virtual	IOFixed			ConvertUSBVolumeTodB (SInt16 volume);

	virtual	IOReturn		deviceRequest (IOUSBDevRequest * request, IOUSBCompletion * completion = NULL);			// Depricated, don't use
	virtual	IOReturn		deviceRequest (IOUSBDevRequestDesc * request, IOUSBCompletion * completion = NULL);
	static	IOReturn		deviceRequest (IOUSBDevRequest * request, AppleUSBAudioDevice * self, IOUSBCompletion * completion = 0);

#ifdef DEBUG
    virtual void			retain() const;
    virtual void			release() const;
#endif
};

#endif /* _APPLEUSBAUDIODEVICE_H */

