/*
 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
 
#ifndef _APPLEUSBAUDIOLEVELCONTROL_H
#define _APPLEUSBAUDIOLEVELCONTROL_H

#include <sys/cdefs.h>

__BEGIN_DECLS
#include <kern/thread_call.h>
__END_DECLS

#include <libkern/OSByteOrder.h>

#include <IOKit/IOLib.h>
#include <IOKit/IOPlatformExpert.h>

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

#include <IOKit/audio/IOAudioLevelControl.h>
#include <IOKit/audio/IOAudioTypes.h>
#include <IOKit/audio/IOAudioDefines.h>

#include "AppleUSBAudioCommon.h"
#include "USBAudioObject.h"

class AppleUSBAudioDevice;
typedef struct call_entry *thread_call_t;

typedef IOReturn (*USBDeviceRequest)(IOUSBDevRequest * request, void * refCon, IOUSBCompletion * completion);

// PRAM read write values
enum{
	kMaximumPRAMVolume 	= 	7,
	kMinimumPRAMVolume	= 	0,
	KNumPramVolumeSteps	= 	(kMaximumPRAMVolume - kMinimumPRAMVolume + 1),
	kPRamVolumeAddr	= 		8,

	kDefaultVolume	= 0x006E006E,
	kInvalidVolumeMask	= 0xFE00FE00
};

#define kiSubMaxVolume		60
#define kiSubVolumePercent	92

class AppleUSBAudioLevelControl : public IOAudioLevelControl
{
    OSDeclareDefaultStructors(AppleUSBAudioLevelControl);

    UInt8					mUnitID;
    UInt8					mInterfaceNumber;
    UInt8					mControlSelector;
    UInt8					mChannelNumber;
    SInt16					mOffset;
	UInt16					mVolRes;
    thread_call_t			mSetValueThreadCall;
    USBDeviceRequest		mUSBDeviceRequest;
	void *					mCallerRefCon;
	Boolean					gExpertMode;
    UInt32					fMaxVolume;
    UInt32					fMinVolume;
	Boolean					fShouldUpdatePRAM;

public:
	static AppleUSBAudioLevelControl *create(UInt8 theUnitID, UInt8 theInterfaceNumber, UInt8 theControlSelector, UInt8 theChannelNumber, Boolean shouldUpdatePRAM, USBDeviceRequest theUSBDeviceRequest, void *theCallerRefCon, UInt32 subType, UInt32 usage);

	virtual bool init(UInt8 theUnitID, UInt8 theInterfaceNumber, UInt8 theControlSelector, UInt8 theChannelNumber, Boolean shouldUpdatePRAM, USBDeviceRequest theUSBDeviceRequest, void *theCallerRefCon, UInt32 subType, UInt32 usage, OSDictionary *properties = NULL);
	virtual void free();

	virtual IOReturn performValueChange(OSObject * newValue);
	virtual void updateUSBValue();
	virtual void updateUSBValue(SInt32 newValue);

	static void updateValueCallback(void *arg1, void *arg2);

private:
	IOReturn	GetCurVolume (UInt8 interfaceNumber, UInt8 channelNumber, SInt16 * target);
	IOReturn	GetMaxVolume (UInt8 interfaceNumber, UInt8 channelNumber, SInt16 * target);
	IOReturn	GetMinVolume (UInt8 interfaceNumber, UInt8 channelNumber, SInt16 * target);
	IOReturn	GetVolumeResolution (UInt8 interfaceNumber, UInt8 channelNumber, UInt16 * target);
	IOReturn	SetCurVolume (UInt8 interfaceNumber, UInt8 channelNumber, SInt16 volume);
	IOFixed		ConvertUSBVolumeTodB (SInt16 volume);
//	IORegistryEntry * FindEntryByNameAndProperty (const IORegistryEntry * start, const char * name, const char * key, UInt32 value);
	UInt8 VolumeToPRAMValue (SInt32 leftVol, SInt32 rightVol);
	void WritePRAMVol (SInt32 leftVol, SInt32 rightVol);
};

#endif
