//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//******************************************************************************
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//******************************************************************************

/*++

Module Name:  
    usbclass.h

Abstract:  
    USB driver access class.
    
Notes: 

--*/
#ifndef __USBCLASS_H_
#define __USBCLASS_H_

#include <usbdi.h>
#include "syncobj.h"

#define DEFAULT_USB_DRIVER TEXT("USBD.DLL")

class UsbClientDrv;
#define MAX_SERVICE_ENTRY 5
#define MAX_USB_CLIENT_DRIVER 128
class UsbDriverArray : public CCriticalSection {
public:
	UsbDriverArray(BOOL bAutoDelete,DWORD arraySize=MAX_USB_CLIENT_DRIVER);
	~UsbDriverArray();
	UsbClientDrv * operator[](int nIndex) const;
	UsbDriverArray& operator=(UsbClientDrv * oneDriver);
	BOOL AddClientDrv(UsbClientDrv * );
	BOOL RemoveClientDrv(UsbClientDrv *,BOOL bDelete );
	UsbClientDrv * GetAt(int nIndex) const;
	DWORD GetArraySize() { return dwArraySize; };
       DWORD GetCurAvailDevs() {return dwCurDevs; };
	BOOL IsEmpty();
	BOOL IsContainClientDrv(UsbClientDrv * pClientDriver);
private:
	UsbClientDrv ** arrayUsbClientDrv;
	const BOOL autoDelete;
	DWORD dwArraySize;
       DWORD dwCurDevs;

};

class USBDriverClass : public UsbDriverArray{
public:
	USBDriverClass(BOOL bAutoDelete=TRUE) ;
	USBDriverClass(LPCTSTR lpDrvName,BOOL bAutoDelete=TRUE);
	~USBDriverClass() { FreeLibrary(hInst);};
 
//access function
	VOID GetUSBDVersion(LPDWORD lpdwMajorVersion, LPDWORD lpdwMinorVersion);
	BOOL RegisterClientDriverID(LPCWSTR szUniqueDriverId);
	BOOL UnRegisterClientDriverID(LPCWSTR szUniqueDriverId);
	BOOL RegisterClientSettings(LPCWSTR lpszDriverLibFile,
                            LPCWSTR lpszUniqueDriverId, LPCWSTR szReserved,
                            LPCUSB_DRIVER_SETTINGS lpDriverSettings);
	BOOL UnRegisterClientSettings(LPCWSTR lpszUniqueDriverId, LPCWSTR szReserved,
                              LPCUSB_DRIVER_SETTINGS lpDriverSettings);
	HKEY OpenClientRegistryKey(LPCWSTR szUniqueDriverId);

	BOOL IsOk() { return(!UsbDriverClassError);};
private:
	BOOL CreateUsbAccessHandle(HINSTANCE hInst);
    LPOPEN_CLIENT_REGISTRY_KEY          lpOpenClientRegistyKey;
    LPREGISTER_CLIENT_DRIVER_ID         lpRegisterClientDriverID;
    LPUN_REGISTER_CLIENT_DRIVER_ID      lpUnRegisterClientDriverID;
    LPREGISTER_CLIENT_SETTINGS          lpRegisterClientSettings;
    LPUN_REGISTER_CLIENT_SETTINGS       lpUnRegisterClientSettings;
    LPGET_USBD_VERSION                  lpGetUSBDVersion;
	BOOL UsbDriverClassError;
	HINSTANCE hInst;
};

extern USBDriverClass *pUsbDriver;
extern const   TCHAR   gcszTestDriverId[];

extern "C" void TRACE(LPCTSTR szFormat, ...);

class UsbBasic {
public:
	UsbBasic(LPCUSB_FUNCS UsbFuncsPtr,LPCUSB_INTERFACE lpInterface, LPCWSTR szUniqueDriverId,
                     LPCUSB_DRIVER_SETTINGS lpDriverSettings);
	~UsbBasic();
	VOID GetUSBDVersion(LPDWORD lpdwMajorVersion, LPDWORD lpdwMinorVersion);
//Helper commands
    BOOL TranslateStringDesc(LPCUSB_STRING_DESCRIPTOR, LPWSTR,DWORD);
    LPCUSB_INTERFACE FindInterface(LPCUSB_DEVICE, UCHAR, UCHAR);
// attribute
	const LPCUSB_FUNCS lpUsbFuncs;
	HKEY OpenClientRegistryKey();
	LPCUSB_INTERFACE GetInterCurface() { return lpInterface; };
	LPCWSTR GetUniqueDriverId() { return szUniqueDriverId; };

	void debug(LPCTSTR szFormat, ...);

private:
	LPUSB_INTERFACE lpInterface;
	LPWSTR szUniqueDriverId;

};

#define MAX_ISOCH_FRAME_LENGTH (0x400*3)
#define LIMITED_UHCI_BLOCK 0x400//64


class UsbClass : public UsbBasic {
public:
	UsbClass(USB_HANDLE usbHandle,LPCUSB_FUNCS UsbFuncsPtr,
			LPCUSB_INTERFACE lpInterface, LPCWSTR szUniqueDriverId,
            LPCUSB_DRIVER_SETTINGS lpDriverSettings);
	~UsbClass();


//??    BOOL RegisterNotificationRoutine(USB_HANDLE,LPDEVICE_NOTIFY_ROUTINE,LPVOID);
//??	BOOL UnRegisterNotificationRoutine(USB_HANDLE,LPDEVICE_NOTIFY_ROUTINE,LPVOID);
	// function to load drivers for separate interfaces
//?    BOOL LoadGenericInterfaceDriver(LPCUSB_INTERFACE);

//USB Subsystem Commands
    BOOL GetFrameNumber(LPDWORD);
    BOOL GetFrameLength(LPUSHORT);

//Enables Device to Adjust the USB SOF period on OHCI or UHCI cards
    BOOL TakeFrameLengthControl();
    BOOL SetFrameLength(HANDLE, USHORT);
    BOOL ReleaseFrameLengthControl();


// Gets info on a device
    LPCUSB_DEVICE GetDeviceInfo();


//Device commands
	USB_TRANSFER IssueVendorTransfer(LPTRANSFER_NOTIFY_ROUTINE,LPVOID,DWORD dwFlags,
		LPCUSB_DEVICE_REQUEST lpControlHeader, LPVOID lpvBuffer,ULONG uBufferPhusicalAddress);
	USB_TRANSFER GetInterface(LPTRANSFER_NOTIFY_ROUTINE,LPVOID, DWORD, UCHAR, PUCHAR);
	USB_TRANSFER SetInterface(LPTRANSFER_NOTIFY_ROUTINE,LPVOID,DWORD, UCHAR, UCHAR);
	USB_TRANSFER GetDescriptor(LPTRANSFER_NOTIFY_ROUTINE,LPVOID, DWORD, UCHAR, UCHAR, WORD,
                                          WORD, LPVOID);
	USB_TRANSFER SetDescriptor(LPTRANSFER_NOTIFY_ROUTINE,LPVOID, DWORD, UCHAR, UCHAR, WORD,
                                          WORD, PVOID);
	USB_TRANSFER SetFeature(LPTRANSFER_NOTIFY_ROUTINE,LPVOID,DWORD, WORD, UCHAR);
	USB_TRANSFER ClearFeature(LPTRANSFER_NOTIFY_ROUTINE,LPVOID, DWORD, WORD, UCHAR);
	USB_TRANSFER GetStatus(LPTRANSFER_NOTIFY_ROUTINE,LPVOID, DWORD, UCHAR, LPWORD);
	USB_TRANSFER SyncFrame(LPTRANSFER_NOTIFY_ROUTINE,LPVOID, DWORD, UCHAR, LPWORD);

	// attribute of default pipe.
	USHORT GetMaxPacketSize( ) { return DefaultDeviceDesc.wMaxPacketSize; };
	UCHAR GetEndPointAttribute () { return (DefaultDeviceDesc.bmAttributes & USB_ENDPOINT_TYPE_MASK);};
	USB_HANDLE GetUsbHandle() const { return hUsb; };
// default pipe function
	BOOL ResetDefaultPipe();
	BOOL IsDefaultPipeHalted(LPBOOL lpHalted) ;
//??typedef BOOL (* LPRESET_DEFAULT_PIPE)(USB_HANDLE);
//??typedef BOOL (* LPIS_DEFAULT_PIPE_HALTED)(USB_HANDLE, LPBOOL);
	BOOL SetSyncFramNumber() { return GetFrameNumber(&m_dwSyncFrameNumber); };
	DWORD GetSyncFramNumber() { return m_dwSyncFrameNumber; };

private:
	const USB_HANDLE hUsb;
	USB_ENDPOINT_DESCRIPTOR DefaultDeviceDesc;
	DWORD m_dwSyncFrameNumber;
	
	
};


#define MAX_PIPE 0x10
class UsbClientDrv : public UsbClass, public CMutex {
public:
	UsbClientDrv(USB_HANDLE usbHandle,LPCUSB_FUNCS UsbFuncsPtr,
			LPCUSB_INTERFACE lpInterface, LPCWSTR szUniqueDriverId,
            LPCUSB_DRIVER_SETTINGS lpDriverSettings);
	virtual ~UsbClientDrv();
	virtual BOOL Initialization() { return TRUE; };
	LPCUSB_ENDPOINT GetDescriptorPoint(DWORD dwIndex);
	DWORD GetNumOfEndPoints() { return dwNumEndPoints; };
/*
	static CreateUsbClientDrv(USB_HANDLE usbHandle,LPCUSB_FUNCS UsbFuncsPtr,
			LPCUSB_INTERFACE lpInterface, LPCWSTR szUniqueDriverId,
            LPCUSB_DRIVER_SETTINGS lpDriverSettings);
*/
	//Class Service
private:
	DWORD dwNumEndPoints;
	LPUSB_ENDPOINT lpEndPoints;
	HANDLE hDevice;
};


#endif
