⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nscdevice.cpp

📁 美国国家半导体公司的扫描仪芯片LM9833的驱动程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*******************************************************************************
 *	@doc
 *
 *  @module NSCDevice.cpp | 
 *
 *	This module contains <o UsdNSCDevice> object methods and helpers that 
 *	implement the IStiUSDDevice interface which is one of the standard 
 *	STI interfaces
 *
 *  Copyright (c) National Semiconductor Corporation 1999-2000
 *  All rights reserved
 *
 ******************************************************************************/

#include "NSCStiU.h"
#include "NscDevice.h"
#include "NSCUtils.h"
#include "NSCUsbIO.h"

// Uncomment this if the device has to be polled for events otherwise it will
// be assumed that the device will generate events
#define NS_POLL_FOR_EVENTS   

const DWORD NS_READ_DATA_TIMEOUT	= 	20000; // in milliseconds
const DWORD NS_WRITE_DATA_TIMEOUT	=	20000; // in milliseconds
const DWORD NS_READ_CMD_TIMEOUT		=	20000; // in milliseconds
const DWORD NS_WRITE_CMD_TIMEOUT	=	20000; // in milliseconds
const DWORD NS_THREADWAIT_TIMEOUT	=	5000;  // in milliseconds
const DWORD NS_MAX_ERRORSTRING		=	254;   // characters
const UCHAR NS_MAX_INTERRUPT_PACKET	=	1;	   // bytes	
const DWORD NS_MAX_LOCKTIMEOUT		=	1000;  // in milliseconds
const DWORD NS_POLLING_INTERVAL     =   500;   // in milliseconds
const DWORD NS_DEFAULT_KICKSTART	=	250;   // in milliseconds

const DWORD NS_DEFAULT_DEBOUNCE     = 5000;     // in milliseconds
const DWORD NS_MIN_DEBOUNCE         = 500;      // in milliseconds
const DWORD NS_MAX_DEBOUNCE         = 10000;    // in milliseconds

// The "Significant Events" recognized by the interrupt thread
const DWORD NS_DEVICE_INTERRUPT    = 0x0001; // Process a device event
const DWORD NS_SHUTDOWN_REQUEST    = 0x0002; // Shutdown the interrupt thread
const DWORD NS_WAIT_ERROR          = 0x0003; // Error while polling/waiting 
                                            // for events
const DWORD NS_IOCONTROL_ERROR     = 0x004;  // Error while using the IOcontrol
                                            // call to talk to the device

// Temporary define for the device descriptor the next version 
// of the DDK should have this value defined
const UCHAR NS_USB_DEVICE	= 1;

// Constants for reading and writing registers from the 
// LM9831 using the bulk endpoints
const UCHAR COMMAND_BYTE_COUNT	= 4;
const BYTE	LM_COMMAND_REGISTER	= 7;
const BYTE	LM_IOSTATUS_REGISTER = 2;

const BYTE	NS_MISC_IO_BIT[]	= { 0x04, 0x08, 0x10};
const BYTE	NS_EVENT_BIT[]		= { 0x01, 0x02, 0x04};
const BYTE	NS_RESET_BIT		=  0x20 ;

// The first byte for the bulk register reads is the mode 
// byte and this is bit mapped 
// Bit 0 , 1 - Read, 0 - Write
// Bit 1 , 1 - Inc, 0 - No Inc
const BYTE MODE_INC_READ	= 0x03;
const BYTE MODE_NOINC_READ	= 0x01;
const BYTE MODE_INC_WRITE	= 0x02;
const BYTE MODE_NOINC_WRITE = 0x00;

const TCHAR	NSCUSD_MUTEX[] = TEXT("NSCSTIU_MUTEX_");
const TCHAR	NSCUSD_POLLING_MUTEX[] = TEXT("NSCSTIU_POLLING_MUTEX_"); 
const TCHAR NSCUSD_KICKSTART_MUTEX[] = TEXT("NSCSTIU_KICKSTART_MUTEX_");

const BYTE NS_ENABLE_REMOTEWAKEUP   = 3;
const BYTE NS_DISABLE_REMOTEWAKEUP  = 1;

// The prototype for the interrupt thread fucntion
VOID	InterruptThreadFunc(LPVOID  lpParameter);

/*******************************************************************************
DESCRIPTION:

UsdNSCDevice::UsdNSCDevice is the constructor for this class 

PARAMETERS: 

LPUNKNOWN punkOuter - This is the pointer to the controlling unknown, if we are
being aggregated otherwise this will be NULL - For more info on COM 
aggregation, see Inside COM by Dale Rogerson of other articles on the MSDN

RETURN VALUE:
none

NOTES:
    This constructor handles COM delegation using the non delgating unknonw 
    base class. The only other thing that is done here is the creation of the
    event objects that we will need to use later on to signal the event thread 
    to shutdown
*******************************************************************************/
UsdNSCDevice::UsdNSCDevice( LPUNKNOWN punkOuter ):
    m_cRef(1),
    m_punkOuter(NULL),
    m_fValid(FALSE),
    m_pDcb(NULL),
    m_DeviceDataHandle(INVALID_HANDLE_VALUE),
	m_pszDeviceNameA(NULL),
    m_hSignalEvent(INVALID_HANDLE_VALUE),
    m_hThread(NULL),
    m_guidLastEvent(GUID_NULL),
	m_bEventMask(0),
	m_bEventsInitialized(false),
	m_hMutex(NULL),
    m_dwDebounceTime(NS_DEFAULT_DEBOUNCE),
	m_bPolling(false),
	m_bRemoteWakeup(false),
	m_bWHQLTest(false),
	m_dwKickStartTime(NS_DEFAULT_KICKSTART),
	m_hKickStartMutex(NULL)
{
	NSC_TRACE("In UsdNSCDevice::UsdNSCDevice");

	for (int index = 0; index < NS_MAX_OPEN_APPS ; index++)
		m_hPollingMutex[index] = NULL;
    //
    // See if we are aggregated. If we are ( which will be almost always the case )
    // save pointer to controlling Unknown , so subsequent calls will be delegated
    // If not, set the same pointer to "this" .
    // N.b. cast below is important in order to point to right virtual table
    //
    if (punkOuter) 
	{
        m_punkOuter = punkOuter;
    }
    else 
	{
        m_punkOuter = reinterpret_cast<IUnknown*>
                      (static_cast<INonDelegatingUnknown*>
                      (this));
    }

	m_hShutdownEvent =  CreateEvent( NULL,   // Attributes
                                   TRUE,     // Manual reset
                                   FALSE,    // Initial state - not set
                                   NULL );   // Anonymous

    if (m_hShutdownEvent && (INVALID_HANDLE_VALUE !=m_hShutdownEvent)) 
	{
		// We are now properly initialized and ready for action
        m_fValid = TRUE;
    }
}


/*******************************************************************************
DESCRIPTION:

UsdNSCDevice::~UsdNSCDevice is the destructor for this object class

PARAMETERS: 

VOID

RETURN VALUE:
none

NOTES:

This method cleans up after this object. The main actions performed here are 
1) shutting down the event thread in case it is active 
2) Closing the handle to the actual device 
3) Destroying the mutex used for synchronization

*******************************************************************************/
UsdNSCDevice::~UsdNSCDevice( VOID )
{
	NSC_TRACE("In UsdNSCDevice::~UsdNSCDevice");

    // Kill the notification thread if it exists by 
	// making sure that any notification handles are 
	// NULLed out.
    if (m_hSignalEvent && (m_hSignalEvent != INVALID_HANDLE_VALUE))
	{
		SetNotificationHandle(NULL);
	}

    if (m_hShutdownEvent && (m_hShutdownEvent!=INVALID_HANDLE_VALUE)) 
	{
        CloseHandle(m_hShutdownEvent);
    }

	CloseDevice();

    if (m_pszDeviceNameA) 
	{
        delete [] m_pszDeviceNameA;
        m_pszDeviceNameA = NULL;
    }

	// Close the mutex object 
	if (m_hMutex != NULL)
	{
		ReleaseMutex(m_hMutex);
	    CloseHandle(m_hMutex);
	}

	for (int index = 0; index < NS_MAX_OPEN_APPS; index++)
	{
		if (m_hPollingMutex[index] != NULL)
		{
			ReleaseMutex(m_hPollingMutex[index]);
			CloseHandle(m_hPollingMutex[index]);
		}
	}
}


/*******************************************************************************
DESCRIPTION:

UsdNSCDevice::GetCapabilities is called by STI to determine the capabilities
supported by this device 

PARAMETERS: 

PSTI_USD_CAPS pUsdCaps - This structure has to be filled in with data 
indicting the capabilitoes of the device

RETURN VALUE:
STDMETHODIMP  - This is a macro that indicates that we return HRESULT 

NOTES:
    The only capability which we want the STI to know about at this 
    point is the fact that we don't need polling and can generate our 
    own events

*******************************************************************************/
STDMETHODIMP UsdNSCDevice::GetCapabilities( PSTI_USD_CAPS pUsdCaps )
{
	NSC_TRACE("In UsdNSCDevice::GetCapabilities");

	HRESULT hres = STI_OK;

    ZeroMemory(pUsdCaps,sizeof(*pUsdCaps));

    pUsdCaps->dwVersion = STI_VERSION;

    // We support device notifications without polling
    pUsdCaps->dwGenericCaps = STI_USD_GENCAP_NATIVE_PUSHSUPPORT;

    return hres;
}


/*******************************************************************************
DESCRIPTION:

UsdNSCDevice::GetStatus is called by the STI to determine if the device that we 
    represent is still online

PARAMETERS: 

PSTI_DEVICE_STATUS pDevStatus

RETURN VALUE:
STDMETHODIMP - This is a macro that indicates that we return HRESULT 

NOTES:

*******************************************************************************/
STDMETHODIMP UsdNSCDevice::GetStatus( PSTI_DEVICE_STATUS pDevStatus )
{
	WriteToLog(	STI_TRACE_INFORMATION,
				L"In UsdNSCDevice::GetStatus - Online Status : %d, Event Status : %d", 
				pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE,
				pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE);

	HRESULT hres = STI_OK;

    //
    // If we are asked, verify whether device is online
    //
    pDevStatus->dwOnlineState = 0L;
    if( pDevStatus->StatusMask & STI_DEVSTATUS_ONLINE_STATE )  
	{
		hres = GetDeviceStatus(pDevStatus);
	}

    //
    // If we are asked, verify state of event
    //
    pDevStatus->dwEventHandlingState = 0L;
    if( pDevStatus->StatusMask & STI_DEVSTATUS_EVENTS_STATE ) 
	{
		if(m_guidLastEvent != GUID_NULL)
		{
			pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_PENDING;
		}
		
		if (m_hSignalEvent && (m_hSignalEvent!= INVALID_HANDLE_VALUE))
		{
			pDevStatus->dwEventHandlingState |= STI_EVENTHANDLING_ENABLED;
		}

    }

    return hres;
}


/*******************************************************************************
DESCRIPTION:

UsdNSCDevice::DeviceReset

PARAMETERS: 

VOID

RETURN VALUE:
STDMETHODIMP  - This is a macro that indicates that we return HRESULT 

NOTES:

*******************************************************************************/
STDMETHODIMP UsdNSCDevice::DeviceReset( VOID )
{
	NSC_TRACE("In UsdNSCDevice::DeviceReset");

	HRESULT hres = STIERR_NOT_INITIALIZED;

    // Reset the current active device - this can be 
	// accomplished by a DeviceIOControl call with an 
	// IOCTL of RESET_PIPE and a value of all pipes
	// Use the escape command to handle all the niceties
	// of the overlapped IO on this call
    if (INVALID_HANDLE_VALUE != m_DeviceDataHandle) 
	{
		
		DWORD		cbBytesWritten;
		PIPE_TYPE	ePipes = ALL_PIPE;
		hres = Escape(	IOCTL_RESET_PIPE,
						&ePipes,
						sizeof(ePipes),
						NULL,
						0,
						&cbBytesWritten);
    }

    return hres;
}

/*******************************************************************************
DESCRIPTION:

UsdNSCDevice::Diagnostic

PARAMETERS: 

LPDIAG pBuffer

RETURN VALUE:
STDMETHODIMP  - This is a macro that indicates that we return HRESULT 

NOTES:

*******************************************************************************/
STDMETHODIMP UsdNSCDevice::Diagnostic( LPDIAG pBuffer )
{
	NSC_TRACE("In UsdNSCDevice::Diagnostic");

    WriteToLog(	STI_TRACE_INFORMATION,
						L"%s : %s : 0x%X", // Message, Error, Code
						L"UsdNSCDevice::Diagnostic",
						L"testing",
						0) ;

	HRESULT hres = STI_OK;

    // We will try to get the maximum packet size for the 
	// USB pipes. This must obviously be greater than zero
	// If there is an error during this operation or the 
	// size is not greater than zero then the device is offline
    if (INVALID_HANDLE_VALUE != m_DeviceDataHandle) 
	{
		// Get the maximum packet size - this has to be 
		// greater than zero for all the pipes 
		CHANNEL_INFO	channelInfo = {0,0,0};
		DWORD			cbBytesWritten(0);

		hres = Escape(	IOCTL_GET_CHANNEL_ALIGN_RQST,
						NULL,
						0,
						&channelInfo,
						sizeof(channelInfo),
						&cbBytesWritten);

		if (FAILED(hres) ||  !channelInfo.EventChannelSize)
		{
			hres = STIERR_GENERIC;
		    m_dwLastOperationError = ::GetLastError();
			// Fill in the error info using the GetLastErrorInfo call
			GetLastErrorInfo(&pBuffer->sErrorInfo);
		}
		else
		{
		    m_dwLastOperationError = 0;
			GetLastErrorInfo(&pBuffer->sErrorInfo);
		}
    }
	else
	{
		hres = STIERR_NOT_INITIALIZED;		
	}

    return hres;
}


/*******************************************************************************
DESCRIPTION:

SetNotificationHandle

PARAMETERS: 

HANDLE hEvent

RETURN VALUE:
STDMETHODIMP  - This is a macro that indicates that we return HRESULT 

NOTES:
// SYNCHRONIZED

*******************************************************************************/
STDMETHODIMP UsdNSCDevice::SetNotificationHandle( HANDLE hEvent )
{
	WriteToLog(	STI_TRACE_INFORMATION,
				L"In UsdNSCDevice::SetNotificationHandle with handle Ox%X", 
				hEvent);

	HRESULT hres = STI_OK;

    TAKE_CRIT_SECT t(m_cs);

    if (hEvent && (hEvent !=INVALID_HANDLE_VALUE)) 
	{
        m_hSignalEvent = hEvent;

        if (m_DeviceDataHandle != INVALID_HANDLE_VALUE) 
		{
            m_guidLastEvent = GUID_NULL;

            if (!m_hThread) 
			{
			    DWORD   dwThread;
				m_hThread = ::CreateThread(NULL,
                                       2*1024,
                                       (LPTHREAD_START_ROUTINE)InterruptThreadFunc,
                                       (LPVOID)this,
                                       0,
                                       &dwThread);

				WriteToLog(	STI_TRACE_INFORMATION,
							L"%s : %s : 0x%X", // Message, Error, Code
							L"UsdNSCDevice::Enabling notification monitoring",
							L"Created Thread (handle) ",
							m_hThread) ;
            }
        }
        else 
		{
            // If we have not been initialized (like when we are 
			// opened in status mode) we will start listening
			// when we are actually opened in data mode so there is
			// no need to return an error code at this point
			WriteToLog(	STI_TRACE_INFORMATION,
						L"%s : %s : 0x%X", // Message, Error, Code
						L"UsdNSCDevice::Device not initialized",
						L"Deferring notification monitoring",
						0) ;
        }
    }
    else
	{
	    //
        // Disable hardware notifications
        //
        m_hSignalEvent = INVALID_HANDLE_VALUE;

		WriteToLog(	STI_TRACE_INFORMATION,
					L"%s : %s : 0x%X", // Message, Error, Code
					L"UsdNSCDevice::Disabling notification monitoring",
					L"Closing Thread (handle)",
					m_hThread) ;

        if ( m_hThread ) 
		{
			::SetEvent(m_hShutdownEvent);
            WaitForSingleObject(m_hThread, NS_THREADWAIT_TIMEOUT);
            CloseHandle(m_hThread);
            m_hThread = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -