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

📄 nscdevice.cpp

📁 美国国家半导体公司的扫描仪芯片LM9833的驱动程序。
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	::CoUninitialize();
}


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

UsdNSCDevice::ListenForInterrupts

PARAMETERS: 


RETURN VALUE:
void 

NOTES:

*******************************************************************************/
void UsdNSCDevice::ListenForInterrupts()
{
	NSC_TRACE("In UsdNSCDevice::ListenForInterrupts");

	WriteToLog(	STI_TRACE_INFORMATION,
				L"%s : %s : 0x%X", // Message, Error, Code
				L"UsdNSCDevice::Listening for Interrupts Started",
				L"In Thread (id)",
                ::GetCurrentThreadId()) ;

	if (!m_DeviceDataHandle || (m_DeviceDataHandle == INVALID_HANDLE_VALUE))
	{
		WriteToLog(	STI_TRACE_ERROR,
					L"%s : %s : 0x%X", // Message, Error, Code
					L"UsdNSCDevice::Listening for Interrupts Aborted",
					L"Device not Initialized in Thread (id)",
                    ::GetCurrentThreadId()) ;
		return;
	}

    // We dont have to create a overlapped event if we are only polling
    // the device but we do it anyway just to make the code simpler to read
    // and modify . The alternatice would be to bracket all this code and
    // the code that closes the overlapped handle with #ifdef commands
    // and that makes the code really messy
    OVERLAPPED	 stOverlapped;
	LPOVERLAPPED lpOverlapped = &stOverlapped;
	ZeroMemory(lpOverlapped, sizeof(OVERLAPPED));
	lpOverlapped->hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

	BOOL	fLooping = TRUE;
    DWORD   dwEventCode;

	while(fLooping)
	{

#ifdef NS_POLL_FOR_EVENTS
        dwEventCode = PollForDriverEvent();
#else
        dwEventCode = WaitForDriverEvent(lpOverlapped);
#endif
		switch(dwEventCode) 
		{
			case NS_DEVICE_INTERRUPT: 

				// Find out what kind of event has occured and then 
                // generate a event for the STI if necessary
				// an event has occured 
				GenerateScannerEvent();

				// We will be back through this loop to wait on device
				// events so it is critical that we reset the event object
				// as this is a manual reset event
				::ResetEvent(lpOverlapped->hEvent);
				break;
			
			case NS_SHUTDOWN_REQUEST:
				// We have to shutdown the interrupt thread
				WriteToLog(	STI_TRACE_INFORMATION,
							L"%s : %s : 0x%X", // Message, Error, Code
							L"UsdNSCDevice::Listening for Interrupts Aborted",
							L"Shutdown Request",
							0) ;

				::ResetEvent(m_hShutdownEvent);
				fLooping  = false;
				break;

			case NS_WAIT_ERROR:
				WriteToLog(	STI_TRACE_ERROR,
							L"%s : %s : 0x%X", // Message, Error, Code
							L"UsdNSCDevice::Listening for Interrupts Aborted",
							L"Wait Error ",
							::GetLastError()) ;

                fLooping  = false;
                break;
            case NS_IOCONTROL_ERROR:
                WriteToLog(	STI_TRACE_ERROR, 
						    L"%s : %s : 0x%X", // Message, Error, Code
						    L"UsdNSCDevice::Listening for Interrupts Aborted",
						    L"DeviceIoControl() Error",
						    ::GetLastError()) ;

			    fLooping = FALSE;
                break;
		}
	}

	::CloseHandle(lpOverlapped->hEvent);
}


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

 UsdNSCDevice::WaitForDriverEvent

PARAMETERS: 

LPOVERLAPPED lpOverlapped

RETURN VALUE:
DWORD  

NOTES:

*******************************************************************************/
DWORD   UsdNSCDevice::WaitForDriverEvent(LPOVERLAPPED lpOverlapped)
{
	DWORD   dwBytesReturned;
	BYTE	pStatus[NS_MAX_INTERRUPT_PACKET];
    DWORD   dwReturnCode;
	BOOL    fRet = TRUE;

    fRet = ::DeviceIoControl(m_DeviceDataHandle,
							(DWORD) IOCTL_WAIT_ON_DEVICE_EVENT,
							NULL, 
							0, 
							pStatus,
							NS_MAX_INTERRUPT_PACKET, 
							&dwBytesReturned,
							lpOverlapped);

    // If the deviceIOControl call returned false and it was not
    // because of a pending IO then we have a real error. In this case 
    // the wait will be aborted with an error return otherwise we 
    // can process the results of the call
    if ( fRet || (::GetLastError() == ERROR_IO_PENDING))
    {
	    HANDLE	EventHandleArray[2] = {m_hShutdownEvent, lpOverlapped->hEvent};
	    int numEvents = sizeof(EventHandleArray) / sizeof(EventHandleArray[0]);

	    // Wait for an event to occur - one of the events could be a 
	    // request for this thread to shutdown because our minidriver
	    // is being unloaded - this is not exactly a device event but it 
	    // is handled here anyway as it is easy to do so
	    DWORD dwIndex = WaitForMultipleObjects(	numEvents, 
											    EventHandleArray, 
											    FALSE, 
											    INFINITE);


        switch (dwIndex)
        {
            case WAIT_OBJECT_0 + 1:
                // We have an interrupt, Trace the event 
				WriteToLog(	STI_TRACE_INFORMATION,
							L"%s : %s : 0x%X", // Message, Error, Code
							L"UsdNSCDevice::Status Register Changed Event",
							L"In Thread (id)",
							::GetCurrentThreadId()) ;

                dwReturnCode = NS_DEVICE_INTERRUPT;
                break;
            case WAIT_OBJECT_0:
                dwReturnCode = NS_SHUTDOWN_REQUEST;
                break;
            default:
                dwReturnCode = NS_WAIT_ERROR;
        }
    }
    else // actual error in the device io control call
    {
        dwReturnCode = NS_IOCONTROL_ERROR;
    }

    return dwReturnCode;
}


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

UsdNSCDevice::PollForDriverEvent

PARAMETERS: 


RETURN VALUE:
DWORD 

NOTES:

*******************************************************************************/
DWORD UsdNSCDevice::PollForDriverEvent()
{
    // if some app has opened the driver then we will 
    // be stuck here till we either get a shutdown notice or
    // the app closes the driver
	bool mutex_wait = false;
	for (int index = 0; index < NS_MAX_OPEN_APPS; index++)
	{
		while (::WaitForSingleObject(m_hPollingMutex[index], 
				min(m_dwKickStartTime,NS_POLLING_INTERVAL))
					== WAIT_TIMEOUT)
		{
			// Check to make sure that we don't have a shutdown request
			if (WaitForSingleObject(m_hShutdownEvent, 0) == WAIT_OBJECT_0)
				return NS_SHUTDOWN_REQUEST;
			// Check command reg = reset
			mutex_wait = true;
			// If waiting on bulkin, do some command to kick start
			// any pause due to step counter termination
			if (::WaitForSingleObject(m_hKickStartMutex,m_dwKickStartTime) == WAIT_TIMEOUT)
			{
				DoKickStart(); 
			}
			else
			{
				ReleaseMutex(m_hKickStartMutex);
			}
		}
		ReleaseMutex(m_hPollingMutex[index]);
	}

	//flush status when exit mutex wait so don't get any events
	if (mutex_wait)
	{
		ResetModeCheckAndClear();
		BYTE bValue;
        ReadStatusRegister(bValue); //flush first after wait
	}

	Sleep (NS_POLLING_INTERVAL);
    
    // Check to make sure that we don't have a shutdown request
    if (WaitForSingleObject(m_hShutdownEvent, 0) == WAIT_OBJECT_0)
        return NS_SHUTDOWN_REQUEST;
    
    // Pretend we just had a device event
    return NS_DEVICE_INTERRUPT;

}


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

UsdNSCDevice::WriteToLog

PARAMETERS: 

DWORD dwType
LPWSTR  lpszFormat
...

RETURN VALUE:
void 

NOTES:

*******************************************************************************/
void UsdNSCDevice::WriteToLog(DWORD dwType, LPWSTR  lpszFormat, ...)
{
	va_list args;
	va_start(args, lpszFormat);

	int nBuf;
	WCHAR szBuffer[512];
	nBuf = _vsnwprintf(szBuffer, 511, lpszFormat, args);

	va_end(args);

	if (nBuf < 0) 
		return;
	
	if (m_pDcb)
	{
		m_pDcb->WriteToErrorLog(dwType, szBuffer, NOERROR) ;	
	}

#ifdef _DEBUG
	// Also trace the message to the debugger if in debug mode
	// Convert name to SBCS as using OutputDebugStringW does not seem
	// to work
    UINT uiNameLen = WideCharToMultiByte(CP_ACP, 0, szBuffer, -1, NULL, NULL, 0, 0);
    if (uiNameLen) 
	{
		LPSTR lpszBuffer = new CHAR[uiNameLen+1];
	    if (lpszBuffer)
		{
		    WideCharToMultiByte(CP_ACP, 0, szBuffer, -1, lpszBuffer, uiNameLen, 0, 0);
			::OutputDebugString(lpszBuffer);
			::OutputDebugString("\n");
			delete lpszBuffer;
		}
	}

#endif    

	return;
}


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

UsdNSCDevice::GetDeviceStatus

PARAMETERS: 

PSTI_DEVICE_STATUS pDevStatus

RETURN VALUE:
HRESULT 

NOTES:

*******************************************************************************/
HRESULT UsdNSCDevice::GetDeviceStatus(PSTI_DEVICE_STATUS pDevStatus)
{
	// The device status can be one of the following 
	// and these conditions are checked for in the 
	// given order 
	// STI_ONLINESTATE_POWER_SAVE (reg 7, bit 4)
	// STI_ONLINESTATE_BUSY (reg 7, bit 0-2 are NOT zero)
	// STI_ONLINESTATE_OPERATIONAL  (if none of the above)

	HRESULT hres = STI_OK;
	// Always lock the device before trying to access the scanner
	hres = LockDevice();

	// So the first order of business is to make sure that we 
	// can read register 7 and then based on the value we will
	// determine the actual status of the device
    if ( SUCCEEDED(hres) && (INVALID_HANDLE_VALUE != m_DeviceDataHandle)) 
	{

		BYTE pCommandBytes[COMMAND_BYTE_COUNT];
		BYTE bValue;

		// Write the command bytes for a register read 
		// without increment 
		pCommandBytes[0] = MODE_NOINC_READ;
		pCommandBytes[1] = LM_COMMAND_REGISTER;
		pCommandBytes[2] = 0; 
		pCommandBytes[3] = 1;

		hres = 	RawWriteData(&pCommandBytes, COMMAND_BYTE_COUNT, NULL);
		
		if (SUCCEEDED(hres))
		{
			// Then read the register in question
			DWORD cbBytes(1);
			hres = RawReadData(&bValue, &cbBytes, NULL);
		}

		if (SUCCEEDED(hres))
		{
			pDevStatus->dwOnlineState |= STI_ONLINESTATE_OPERATIONAL;
			if (bValue & 0x10)
				pDevStatus->dwOnlineState |= STI_ONLINESTATE_POWER_SAVE;
			else if (bValue & 0x07) 
				pDevStatus->dwOnlineState |= STI_ONLINESTATE_BUSY;
		}

		UnLockDevice();
    }

	return hres;
}



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

UsdNSCDevice::GenerateScannerEvent

PARAMETERS: 


RETURN VALUE:
void 

NOTES:

*******************************************************************************/
void UsdNSCDevice::GenerateScannerEvent()
{
	// Make sure that somebody is actually interested in hearing 
	// about this event
	if ((m_hSignalEvent == INVALID_HANDLE_VALUE) || (!m_bEventsInitialized))
		return;

	// Find out if the scanner is online and is the scanner is in 
	// reset mode - if the scanner is in reset mode we will simply
	// bring it out of this mode and ignore the event
	HRESULT hres = S_OK;

	//do every 20 times for safety
	static int ct = 0;
	if (!ct--) 
	{
		ct = 20;	
		hres = ResetModeCheckAndClear();
	}

	BYTE bStatusRegister;
	if SUCCEEDED(hres)
	{
		hres = ReadStatusRegister(bStatusRegister);
	}

	// If there was a scanner IO error then in all probability scanner
	// is offline and this event should be ignored
	if SUCCEEDED(hres)
	{
		// Get the event GUID corresponding to the current state
		// of the register
		m_guidLastEvent = GetEventGUID(bStatusRegister);
		if (!IsEqualGUID(m_guidLastEvent,GUID_NULL))
		{
			// The event is forwarded onto the STI only if the 
			// status register bit is set and the event mask for that 
			// IO pin is turned on
			::SetEvent(m_hSignalEvent);

            // Once we successfully activate an event, we want to make 
            // sure that we debounce the input that is we dont want
            // any more false positives till the debounce interval 
            // is finished so we just let this thread sleep for the
            // debounce interval and then read and clear the status 
            // register
            ::Sleep(m_dwDebounceTime);
            
            // Now clear any bits that were set when we were asleep
            ReadStatusRegister(bStatusRegister);

		}
	}

}



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

UsdNSCDevice::ReadStatusRegister

PARAMETERS: 

BYTE& bValue

RETURN VALUE:
HRESULT 

NOTES:

*******************************************************************************/
HRESULT UsdNSCDevice::ReadStatusRegister(BYTE& bValue)
{
	HRESULT hres = STI_OK;

	if (!m_bPolling)
	{
		bValue = 0;
		return hres;
	}

	hres = LockDevice();

	// Follow the standard procedure of writing command bytes
	// to the bulk out endpoint to read the io status register and then 
	// actually reading in the value from the bulk in endpoint
    if ( SUCCEEDED(hres) && (INVALID_HANDLE_VALUE != m_DeviceDataHandle)) 
	{
		BYTE	pCommandBytes[COMMAND_BYTE_COUNT];

		// Write the command bytes for a register read 
		// without increment 
		pCommandBytes[0] = MODE_NOINC_READ;
		pCommandBytes[1] = LM_IOSTATUS_REGISTER;
		pCommandBytes[2] = 0; 
		pCommandBytes[3] = 1;

		hres = 	RawWriteData(&pCommandBytes, COMMAND_BYTE_COUNT, NULL);
		
		if (SUCCEEDED(hres))
		{

⌨️ 快捷键说明

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