|
|
/**************************************************************************************************************************
* HWIO.C SigmaTel STIR4200 hardware specific module (to access the registers) ************************************************************************************************************************** * (C) Unpublished Copyright of Sigmatel, Inc. All Rights Reserved. * * * Created: 04/06/2000 * Version 0.9 * Edited: 04/27/2000 * Version 0.92 * Edited: 05/12/2000 * Version 0.94 * Edited: 07/27/2000 * Version 1.01 * Edited: 08/22/2000 * Version 1.02 * Edited: 09/16/2000 * Version 1.03 * Edited: 09/25/2000 * Version 1.10 * Edited: 11/10/2000 * Version 1.12 * Edited: 01/16/2001 * Version 1.14 * Edited: 02/20/2001 * Version 1.15 * **************************************************************************************************************************/
#define DOBREAKS // enable debug breaks
#include <ndis.h>
#include <ntdef.h>
#include <windef.h>
#include "stdarg.h"
#include "stdio.h"
#include "debug.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "ircommon.h"
#include "irusb.h"
#include "irndis.h"
#include "stir4200.h"
/*****************************************************************************
* * Function: St4200ResetFifo * * Synopsis: Reset the STIr4200 FIFO to clear several hangs * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200ResetFifo( IN PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; DEBUGMSG(DBG_INT_ERR, (" St4200ResetFifo: Issuing a FIFO reset()\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_MODE_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n")); goto done; } #endif
//
// Force a FIFO reset by clearing and setting again the RESET_OFF bit
//
pThisDev->StIrTranceiver.ModeReg &= (~STIR4200_MODE_RESET_OFF); if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n")); goto done; }
pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_RESET_OFF; if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200DoubleResetFifo * * Synopsis: Reset the STIr4200 FIFO to clear several 4012 related hangs * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200DoubleResetFifo( IN PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; DEBUGMSG(DBG_INT_ERR, (" St4200DoubleResetFifo: Issuing a FIFO reset()\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); //
// Turn off the receiver to clear the pointers
//
if( (Status = St4200TurnOffReceiver( pThisDev ) ) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n")); goto done; }
//
// Now clear the fifo logic
//
#if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_STATUS_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n")); goto done; }
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_STATUS_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n")); goto done; } #endif
pThisDev->StIrTranceiver.StatusReg |= STIR4200_STAT_FFCLR; if( (Status = St4200WriteRegister(pThisDev, STIR4200_STATUS_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n")); goto done; }
//
// All back on
//
pThisDev->StIrTranceiver.StatusReg &= (~STIR4200_STAT_FFCLR); if( (Status = St4200WriteRegister(pThisDev, STIR4200_STATUS_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n")); goto done; }
if( (Status = St4200TurnOnReceiver( pThisDev ) ) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200SoftReset * * Synopsis: Soft reset of the STIr4200 modulator * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200SoftReset( IN PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; DEBUGMSG(DBG_INT_ERR, (" St4200SoftReset: Issuing a soft reset()\n")); // MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n")); goto done; } #endif
//
// Force a FIFO reset by clearing and setting again the RESET_OFF bit
//
pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SRESET; if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n")); goto done; }
pThisDev->StIrTranceiver.ControlReg &= (~STIR4200_CTRL_SRESET); if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200SetIrMode * * Synopsis: Sets the STIr4200 to the proper operational mode * * Arguments: pDevice - pointer to current ir device object * mode - mode to set the tranceiver to * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200SetIrMode( IN OUT PVOID pDevice, ULONG mode ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_MODE_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n")); goto done; } #endif
//
// Remove all mode bits and set the proper mode
//
pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_MASK; pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_RESET_OFF;
//
// Enable the bug fixing feature for LA8
//
#if defined(SUPPORT_LA8)
if( pThisDev->ChipRevision >= CHIP_REVISION_8 ) { pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_AUTO_RESET; pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_BULKIN_FIX; } #endif
switch( (IR_MODE)mode ) { case IR_MODE_SIR: #if defined(WORKAROUND_CASIO)
if( pThisDev->linkSpeedInfo->BitsPerSec != SPEED_9600 ) #endif
pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_BULKIN_FIX;
pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_SIR; //pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_ASK;
break; #if !defined(WORKAROUND_BROKEN_MIR)
case IR_MODE_MIR: pThisDev->MirIncompleteBitCount = 0; pThisDev->MirOneBitCount = 0; pThisDev->MirIncompleteByte = 0; pThisDev->MirFlagCount = 0; pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_MIR; break; #endif
case IR_MODE_FIR: pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_FIR; #if defined(SUPPORT_LA8)
if( pThisDev->ChipRevision >= CHIP_REVISION_8 ) { pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_BULKIN_FIX; pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_AUTO_RESET; } #endif
break; default: IRUSB_ASSERT( 0 ); }
#ifdef NO_BULKIN_FIX
// force clear of mode reg bit 3
pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_BULKIN_FIX; #endif
if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG) ) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n")); goto done; }
/***********************************************/ /* Set TEMIC transceiver... */ /***********************************************/ #if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n")); goto done; } #endif
pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SDMODE; if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n")); goto done; } #if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n")); goto done; } #endif
pThisDev->StIrTranceiver.ControlReg &= (~STIR4200_CTRL_SDMODE);
if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200SetSpeed * * Synopsis: Sets the STIr4200 speed * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200SetSpeed( IN OUT PVOID pDevice ) { NTSTATUS Status = STATUS_SUCCESS; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); //
// MS Security bug #539173
// These log files need either ACLs restricted to Admin, or need
// to be put in a admin directory. For now we are punting on this because
// logging is NEVER turned on in a driver that is released to customers.
//
#define RECEIVE_LOG_FILE_NAME L"\\DosDevices\\c:\\receive.log"
#define RECEIVE_ERR_LOG_FILE_NAME L"\\DosDevices\\c:\\receive_error.log"
#define SEND_LOG_FILE_NAME L"\\DosDevices\\c:\\send.log"
#if defined(RECEIVE_LOGGING)
if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 ) { IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING FileName; NTSTATUS Status;
RtlInitUnicodeString(&FileName, RECEIVE_LOG_FILE_NAME); InitializeObjectAttributes( &ObjectAttributes, &FileName, // MS Security bug #539151
OBJ_CASE_INSENSITIVE || OBJ_KERNEL_HANDLE, NULL, NULL );
// MS Security bug #539093
if( pThisDev->ReceiveFileHandle ) { ZwClose( pThisDev->ReceiveFileHandle ); }
Status=ZwCreateFile( &pThisDev->ReceiveFileHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); pThisDev->ReceiveFilePosition = 0; } else { if( pThisDev->ReceiveFileHandle ) { ZwClose( pThisDev->ReceiveFileHandle ); pThisDev->ReceiveFileHandle = 0; pThisDev->ReceiveFilePosition = 0; } } #endif
#if defined(RECEIVE_ERROR_LOGGING)
if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 ) { IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING FileName; NTSTATUS Status;
RtlInitUnicodeString(&FileName, RECEIVE_ERR_LOG_FILE_NAME); InitializeObjectAttributes( &ObjectAttributes, &FileName, // MS Security bug #539151
OBJ_CASE_INSENSITIVE || OBJ_KERNEL_HANDLE, NULL, NULL );
// MS Security bug #539093
if( pThisDev->ReceiveErrorFileHandle ) { ZwClose( pThisDev->ReceiveErrorFileHandle ); }
Status=ZwCreateFile( &pThisDev->ReceiveErrorFileHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); pThisDev->ReceiveErrorFilePosition = 0; } else { if( pThisDev->ReceiveErrorFileHandle ) { ZwClose( pThisDev->ReceiveErrorFileHandle ); pThisDev->ReceiveErrorFileHandle = 0; pThisDev->ReceiveErrorFilePosition = 0; } } #endif
#if defined(SEND_LOGGING)
if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 ) { IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING FileName; NTSTATUS Status;
RtlInitUnicodeString(&FileName, SEND_LOG_FILE_NAME); InitializeObjectAttributes( &ObjectAttributes, &FileName, // MS Security bug #539151
OBJ_CASE_INSENSITIVE || OBJ_KERNEL_HANDLE, NULL, NULL );
// MS Security bug #539093
if( pThisDev->SendFileHandle ) { ZwClose( pThisDev->SendFileHandle ); }
Status=ZwCreateFile( &pThisDev->SendFileHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); pThisDev->SendFilePosition = 0; } else { if( pThisDev->SendFileHandle ) { ZwClose( pThisDev->SendFileHandle ); pThisDev->SendFileHandle = 0; pThisDev->SendFilePosition = 0; } } #endif
//
// Always force a new tuning
//
if( (Status = St4200TuneDpllAndSensitivity(pThisDev, pThisDev->linkSpeedInfo->BitsPerSec)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n")); goto done; }
//
// First power down the modulator
//
/*
#if !defined(FAST_WRITE_REGISTERS)
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; } #endif
pThisDev->StIrTranceiver.ControlReg |= (STIR4200_CTRL_TXPWD | STIR4200_CTRL_RXPWD); if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; }*/
//
// Then set baudrate
//
pThisDev->StIrTranceiver.BaudrateReg = pThisDev->linkSpeedInfo->Stir4200Divisor;
if( (Status = St4200WriteRegister(pThisDev, STIR4200_BAUDRATE_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; }
//
// We'll have to write the MSB of baud-rate too (only for 2400)
//
if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_2400 ) { pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_PDLCK8; if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; } } else { if( pThisDev->StIrTranceiver.ModeReg & STIR4200_MODE_PDLCK8 ) { pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_PDLCK8; if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; } } }
//
// Modulator back up
//
/*pThisDev->StIrTranceiver.ControlReg &= (~(STIR4200_CTRL_TXPWD | STIR4200_CTRL_RXPWD));
if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; }*/
//
// then IR mode
//
Status = St4200SetIrMode( pThisDev, pThisDev->linkSpeedInfo->IrMode );
if( Status != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; }
//
// optionally set the rx line
//
if( pThisDev->ReceiveMode == RXMODE_SLOWFAST ) { if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_4000000 ) { pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_RXSLOW; } else { pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXSLOW; }
if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; } } else if (pThisDev->ReceiveMode == RXMODE_SLOW ) { pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXSLOW;
if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n")); goto done; } }
//
// Program the receive delay for FIR
//
if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_4000000 ) { if( pThisDev->dongleCaps.windowSize == 2 ) pThisDev->ReceiveAdaptiveDelay = STIR4200_MULTIPLE_READ_DELAY; else pThisDev->ReceiveAdaptiveDelay = 0; pThisDev->ReceiveAdaptiveDelayBoost = 0; }
#if defined(WORKAROUND_GEAR_DOWN)
//
// Force a reset if going to 9600 from 4M
//
pThisDev->GearedDown = FALSE; if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_9600 && pThisDev->currentSpeed==SPEED_4000000 ) { St4200ResetFifo( pThisDev ); pThisDev->GearedDown = TRUE; } #endif
done: return Status; }
/*****************************************************************************
* * Function: St4200GetFifoCount * * Synopsis: Verifies if there is data to be received * * Arguments: pDevice - pointer to current ir device object * pCountFifo - pointer to variable to return FIFO count * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200GetFifoCount( IN PVOID pDevice, OUT PULONG pCountFifo ) { NTSTATUS Status = STATUS_SUCCESS; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); IRUSB_ASSERT(pCountFifo != NULL); *pCountFifo = 0; if( pThisDev->PreFifoCount ) { *pCountFifo = pThisDev->PreFifoCount; } else { Status = St4200ReadRegisters( pThisDev, STIR4200_FIFOCNT_LSB_REG, 2 );
if( Status == STATUS_SUCCESS ) { *pCountFifo = ((ULONG)MAKEUSHORT(pThisDev->StIrTranceiver.FifoCntLsbReg, pThisDev->StIrTranceiver.FifoCntMsbReg)); } }
pThisDev->PreFifoCount = 0; return Status; }
/*****************************************************************************
* * Function: St4200TuneDpllAndSensitivity * * Synopsis: tunes the DPLL and sensitivity registers * * Arguments: pDevice - pointer to current ir device object * Speed - speed to tune for * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200TuneDpllAndSensitivity( IN OUT PVOID pDevice, ULONG Speed ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value of the DPLL
//
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_DPLLTUNE_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n")); goto done; } #endif
//
// Tune the DPLL according to the installed transceiver
//
switch( pThisDev->TransceiverType ) { case TRANSCEIVER_HP: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_HP; break; case TRANSCEIVER_INFINEON: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_INFI; break; case TRANSCEIVER_VISHAY: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_VISHAY; break; case TRANSCEIVER_VISHAY_6102F: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_VISHAY_6102F; break; case TRANSCEIVER_4000: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4000; break; case TRANSCEIVER_4012: switch( Speed ) { case SPEED_9600: case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012_SIR; break; case SPEED_4000000: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012_FIR; break; default: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012; break; } break; case TRANSCEIVER_CUSTOM: default: switch( Speed ) { case SPEED_9600: case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: #if defined(VARIABLE_SETTINGS)
pThisDev->StIrTranceiver.DpllTuneReg = (UCHAR)pThisDev->SirDpll; #else
pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_CUSTOM_SIR; #endif
break; case SPEED_4000000: #if defined(VARIABLE_SETTINGS)
pThisDev->StIrTranceiver.DpllTuneReg = (UCHAR)pThisDev->FirDpll; #else
pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_CUSTOM_FIR; #endif
break; default: pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_CUSTOM; break; } break; }
if( (Status = St4200WriteRegister(pThisDev, STIR4200_DPLLTUNE_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n")); goto done; }
#if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value of the sensitivity
//
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_SENSITIVITY_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n")); goto done; } #endif
//
// Tune the sensitivity
//
switch( pThisDev->TransceiverType ) { case TRANSCEIVER_HP: switch( Speed ) { default: case SPEED_9600: case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_HP_SIR; break; case SPEED_4000000: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_HP_FIR; break; } break; case TRANSCEIVER_INFINEON: switch( Speed ) { default: case SPEED_9600: case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_INFI_SIR; break; case SPEED_4000000: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_INFI_FIR; break; } break; case TRANSCEIVER_VISHAY_6102F: switch( Speed ) { default: case SPEED_9600: case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_VISHAY_6102F_SIR; break; case SPEED_4000000: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_VISHAY_6102F_FIR; break; } break; case TRANSCEIVER_VISHAY: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_DEFAULT; break; case TRANSCEIVER_4000: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_DEFAULT; break; case TRANSCEIVER_4012: switch( Speed ) { default: case SPEED_9600: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_SIR_9600; break; case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_SIR; break; case SPEED_4000000: pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_FIR; break; } break; case TRANSCEIVER_CUSTOM: default: switch( Speed ) { default: case SPEED_9600: #if defined(VARIABLE_SETTINGS)
pThisDev->StIrTranceiver.SensitivityReg = (UCHAR)pThisDev->SirSensitivity; #else
pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_CUSTOM_SIR_9600; #endif
break; case SPEED_19200: case SPEED_38400: case SPEED_57600: case SPEED_115200: #if defined(VARIABLE_SETTINGS)
pThisDev->StIrTranceiver.SensitivityReg = (UCHAR)pThisDev->SirSensitivity; #else
pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_CUSTOM_SIR; #endif
break; case SPEED_4000000: #if defined(VARIABLE_SETTINGS)
pThisDev->StIrTranceiver.SensitivityReg = (UCHAR)pThisDev->FirSensitivity; #else
pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_CUSTOM_FIR; #endif
break; } break; } if( (Status = St4200WriteRegister(pThisDev, STIR4200_SENSITIVITY_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200EnableOscillatorPowerDown * * Synopsis: enable the oscillator to power down when we go into suspend mode * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200EnableOscillatorPowerDown( IN OUT PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value
//
if( (Status = St4200ReadRegisters(pThisDev, pThisDev, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200EnableOscillatorPowerDown(): USB failure\n")); goto done; } #endif
//
// Enable
//
pThisDev->StIrTranceiver.TestReg |= STIR4200_TEST_EN_OSC_SUSPEND; if( (Status = St4200WriteRegister(pThisDev, STIR4200_TEST_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200EnableOscillatorPowerDown(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200TurnOnSuspend * * Synopsis: prepares the part to go into suspend mode * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200TurnOnSuspend( IN OUT PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value
//
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOnSuspend(): USB failure\n")); goto done; } #endif
//
// Control UOUT
//
pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SDMODE; if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOnSuspend(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200TurnOffSuspend * * Synopsis: prepares the part to go back into operational mode * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200TurnOffSuspend( IN OUT PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value
//
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOffSuspend(): USB failure\n")); goto done; } #endif
//
// Control UOUT
//
pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_SDMODE; if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOffSuspend(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200TurnOffReceiver * * Synopsis: turns of the STIr4200 receiver * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200TurnOffReceiver( IN OUT PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value
//
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOffReceiver(): USB failure\n")); goto done; } #endif
//
// Turn off receiver
//
pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXPWD; if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOffReceiver(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200TurnOnReceiver * * Synopsis: turns on the STIr4200 receiver * * Arguments: pDevice - pointer to current ir device object * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200TurnOnReceiver( IN OUT PVOID pDevice ) { NTSTATUS Status; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); #if !defined(FAST_WRITE_REGISTERS)
//
// Read the current value
//
if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOnReceiver(): USB failure\n")); goto done; } #endif
//
// Turn on receiver
//
pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_RXPWD; if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS ) { DEBUGMSG(DBG_ERR, (" St4200TurnOnReceiver(): USB failure\n")); goto done; }
done: return Status; }
/*****************************************************************************
* * Function: St4200WriteMultipleRegisters * * Synopsis: reads multiple registers from the tranceiver * * Arguments: pDevice - pointer to current ir device object * FirstRegister - first register to write * RegistersToWrite - number of registers * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200WriteMultipleRegisters( IN PVOID pDevice, UCHAR FirstRegister, UCHAR RegistersToWrite ) { NTSTATUS status = STATUS_SUCCESS; PIRUSB_CONTEXT pThisContext; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; PIRP pIrp; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; PLIST_ENTRY pListEntry;
DEBUGMSG(DBG_FUNC, ("+St4200WriteMultipleRegisters\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//
// Make sure there isn't a halt/reset going on
//
if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall ) { DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to pending reset\n"));
status = STATUS_UNSUCCESSFUL; goto done; } //
// Validate the parameters
//
if( (FirstRegister+RegistersToWrite)>(STIR4200_MAX_REG+1) ) { DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters invalid input parameters\n"));
status = STATUS_UNSUCCESSFUL; goto done; }
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters failed to find a free context struct\n")); IRUSB_ASSERT( 0 );
status = STATUS_UNSUCCESSFUL; goto done; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
//
// MS Security recommendation - allocate a new urb.
//
pThisContext->UrbLen = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen); if (pThisContext->pUrb == NULL) { DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to urb alloc failure\n")); goto done; } pUrb = pThisContext->pUrb;
//
// Now that we have created the urb, we will send a
// request to the USB device object.
//
pUrbTargetDev = pThisDev->pUsbDevObj;
//
// make an irp sending to usbhub
//
pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
if( NULL == pIrp ) { DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters failed to alloc IRP\n"));
ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount ); MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL; status = STATUS_UNSUCCESSFUL; goto done; }
pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0;
pThisContext->pIrp = pIrp;
//
// Build our URB for USBD
//
pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT)sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE; pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT; // short packet is not treated as an error.
pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK; pUrb->UrbControlVendorClassRequest.UrbLink = NULL; pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL; pUrb->UrbControlVendorClassRequest.TransferBuffer = &(pThisDev->StIrTranceiver.FifoDataReg)+FirstRegister; pUrb->UrbControlVendorClassRequest.TransferBufferLength = RegistersToWrite; pUrb->UrbControlVendorClassRequest.Request = STIR4200_WRITE_REGS_REQ; pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0; pUrb->UrbControlVendorClassRequest.Index = FirstRegister;
//
// Call the class driver to perform the operation.
//
pNextStack = IoGetNextIrpStackLocation( pIrp );
IRUSB_ASSERT( pNextStack != NULL );
//
// pass the URB to the USB driver stack
//
pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; pNextStack->Parameters.Others.Argument1 = pUrb; pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine( pIrp, // irp to use
St4200CompleteReadWriteRequest, // routine to call when irp is done
DEV_TO_CONTEXT(pThisContext), // context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE // call on cancel
);
KeClearEvent( &pThisDev->EventSyncUrb );
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->ReadWritePendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->ReadWritePendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) ) { // wait, but dump out on timeout
if( status == STATUS_PENDING ) { status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { KIRQL OldIrql;
DEBUGMSG( DBG_ERR,(" St4200WriteMultipleRegisters() TIMED OUT! return from IoCallDriver USBD %x\n", status)); KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->ReadWritePendingCount ); // MS Security recommendation - cannot cancel IRP.
} } } else { DEBUGMSG( DBG_ERR, (" St4200WriteMultipleRegisters IoCallDriver FAILED(%x)\n",status)); IRUSB_ASSERT( status == STATUS_PENDING ); }
done: DEBUGMSG(DBG_FUNC, ("-St4200WriteMultipleRegisters\n")); return status; }
/*****************************************************************************
* * Function: St4200WriteRegister * * Synopsis: writes a STIr4200 register * * Arguments: pDevice - pointer to current ir device object * FirstRegister - first register to write * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200WriteRegister( IN PVOID pDevice, UCHAR RegisterToWrite ) { NTSTATUS status = STATUS_SUCCESS; PIRUSB_CONTEXT pThisContext; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; PIRP pIrp; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; PLIST_ENTRY pListEntry;
DEBUGMSG(DBG_FUNC, ("+St4200WriteRegister\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//
// Make sure there isn't a halt/reset going on
//
if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall ) { DEBUGMSG(DBG_ERR, (" St4200WriteRegister abort due to pending reset\n"));
status = STATUS_UNSUCCESSFUL; goto done; } //
// Validate the parameters
//
if( RegisterToWrite>STIR4200_MAX_REG ) { DEBUGMSG(DBG_ERR, (" St4200WriteRegister invalid input parameters\n"));
status = STATUS_UNSUCCESSFUL; goto done; }
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" St4200WriteRegister failed to find a free context struct\n")); IRUSB_ASSERT( 0 );
status = STATUS_UNSUCCESSFUL; goto done; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
//
// MS Security recommendation - allocate a new urb.
//
pThisContext->UrbLen = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen); if (pThisContext->pUrb == NULL) { DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to urb alloc failure\n")); goto done; } pUrb = pThisContext->pUrb;
//
// Now that we have created the urb, we will send a
// request to the USB device object.
//
pUrbTargetDev = pThisDev->pUsbDevObj;
//
// make an irp sending to usbhub
//
pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
if( NULL == pIrp ) { DEBUGMSG(DBG_ERR, (" St4200WriteRegister failed to alloc IRP\n"));
MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL; ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount ); status = STATUS_UNSUCCESSFUL; goto done; }
pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0;
pThisContext->pIrp = pIrp;
//
// Build our URB for USBD
//
pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE; pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT; // short packet is not treated as an error.
pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK; pUrb->UrbControlVendorClassRequest.UrbLink = NULL; pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL; pUrb->UrbControlVendorClassRequest.Value = *(&pThisDev->StIrTranceiver.FifoDataReg+RegisterToWrite); pUrb->UrbControlVendorClassRequest.Request = STIR4200_WRITE_REG_REQ; pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0; pUrb->UrbControlVendorClassRequest.Index = RegisterToWrite;
//
// Call the class driver to perform the operation.
//
pNextStack = IoGetNextIrpStackLocation( pIrp );
IRUSB_ASSERT( pNextStack != NULL );
//
// pass the URB to the USB driver stack
//
pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; pNextStack->Parameters.Others.Argument1 = pUrb; pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine( pIrp, // irp to use
St4200CompleteReadWriteRequest, // routine to call when irp is done
DEV_TO_CONTEXT(pThisContext), // context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE // call on cancel
);
KeClearEvent( &pThisDev->EventSyncUrb );
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->ReadWritePendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->ReadWritePendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) ) { // wait, but dump out on timeout
if( status == STATUS_PENDING ) { status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { KIRQL OldIrql;
DEBUGMSG( DBG_ERR,(" St4200WriteRegister() TIMED OUT! return from IoCallDriver USBD %x\n", status)); KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->ReadWritePendingCount ); // MS Security recommendation - cannot cancel IRP.
} } } else { DEBUGMSG( DBG_ERR, (" St4200WriteRegister IoCallDriver FAILED(%x)\n",status)); IRUSB_ASSERT( status == STATUS_PENDING ); }
done: DEBUGMSG(DBG_FUNC, ("-St4200WriteRegister\n")); return status; }
/*****************************************************************************
* * Function: St4200ReadRegisters * * Synopsis: reads multiple STIr4200 register * * Arguments: pDevice - pointer to current ir device object * FirstRegister - first register to read * RegistersToWrite - number of registers to read * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200ReadRegisters( IN OUT PVOID pDevice, UCHAR FirstRegister, UCHAR RegistersToRead ) { NTSTATUS status = STATUS_SUCCESS; PIRUSB_CONTEXT pThisContext; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; PIRP pIrp; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; PLIST_ENTRY pListEntry;
DEBUGMSG(DBG_FUNC, ("+St4200ReadRegisters\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//
// Make sure there isn't a halt/reset going on
//
if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall ) { DEBUGMSG(DBG_ERR, (" St4200ReadRegisters abort due to pending reset\n"));
status = STATUS_UNSUCCESSFUL; goto done; }
//
// Validate the parameters
//
if( (FirstRegister+RegistersToRead)>(STIR4200_MAX_REG+1) ) { DEBUGMSG(DBG_ERR, (" St4200ReadRegisters invalid input parameters\n"));
status = STATUS_UNSUCCESSFUL; goto done; }
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" St4200ReadRegisters failed to find a free context struct\n")); IRUSB_ASSERT( 0 );
status = STATUS_UNSUCCESSFUL; goto done; }
InterlockedDecrement( &pThisDev->SendAvailableCount ); pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
//
// MS Security recommendation - allocate a new urb.
//
pThisContext->UrbLen = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen); if (pThisContext->pUrb == NULL) { DEBUGMSG(DBG_ERR, (" St4200ReadRegisters abort due to urb alloc failure\n")); goto done; } pUrb = pThisContext->pUrb;
//
// Now that we have created the urb, we will send a
// request to the USB device object.
//
pUrbTargetDev = pThisDev->pUsbDevObj;
//
// make an irp sending to usbhub
//
pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
if( NULL == pIrp ) { DEBUGMSG(DBG_ERR, (" St4200ReadRegisters failed to alloc IRP\n"));
MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL; ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount ); status = STATUS_UNSUCCESSFUL; goto done; }
pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0;
pThisContext->pIrp = pIrp;
//
// Build our URB for USBD
//
pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST ); pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE ; pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN ; // short packet is not treated as an error.
pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK; pUrb->UrbControlVendorClassRequest.UrbLink = NULL; pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL; pUrb->UrbControlVendorClassRequest.TransferBuffer = &(pThisDev->StIrTranceiver.FifoDataReg)+FirstRegister; pUrb->UrbControlVendorClassRequest.TransferBufferLength = RegistersToRead; pUrb->UrbControlVendorClassRequest.Request = STIR4200_READ_REGS_REQ; pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0; pUrb->UrbControlVendorClassRequest.Index = FirstRegister; //
// Call the class driver to perform the operation.
//
pNextStack = IoGetNextIrpStackLocation( pIrp );
IRUSB_ASSERT( pNextStack != NULL );
//
// pass the URB to the USB driver stack
//
pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; pNextStack->Parameters.Others.Argument1 = pUrb; pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine( pIrp, // irp to use
St4200CompleteReadWriteRequest, // routine to call when irp is done
DEV_TO_CONTEXT(pThisContext), // context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE // call on cancel
);
KeClearEvent( &pThisDev->EventSyncUrb );
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->ReadWritePendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->ReadWritePendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) ) { // wait, but dump out on timeout
if( status == STATUS_PENDING ) { status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { KIRQL OldIrql;
DEBUGMSG( DBG_ERR,(" St4200ReadRegisters() TIMED OUT! return from IoCallDriver USBD %x\n", status)); KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->ReadWritePendingCount ); // MS Security recommendation - cannot cancel IRP.
} else { //
// Update the status to reflect the real return code
//
status = pThisDev->StatusReadWrite; } } } else { DEBUGMSG( DBG_ERR, (" St4200ReadRegisters IoCallDriver FAILED(%x)\n",status)); //
// Don't assert, as such a failure can happen at shutdown
//
//IRUSB_ASSERT( status == STATUS_PENDING );
}
done: DEBUGMSG(DBG_FUNC, ("-St4200ReadRegisters\n")); return status; }
/*****************************************************************************
* * Function: St4200CompleteReadWriteRequest * * Synopsis: completes a read/write ST4200 register request * * Arguments: pUsbDevObj - pointer to the device object which * completed the irp * pIrp - the irp which was completed by the device * object * Context - send context * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200CompleteReadWriteRequest( IN PDEVICE_OBJECT pUsbDevObj, IN PIRP pIrp, IN PVOID Context ) { PIR_DEVICE pThisDev; NTSTATUS status; PIRUSB_CONTEXT pThisContext = (PIRUSB_CONTEXT)Context; PIRP pContextIrp; PURB pContextUrb; PLIST_ENTRY pListEntry;
DEBUGMSG(DBG_FUNC, ("+St4200CompleteReadWriteRequest\n")); //
// The context given to IoSetCompletionRoutine is an IRUSB_CONTEXT struct
//
IRUSB_ASSERT( NULL != pThisContext ); // we better have a non NULL buffer
pThisDev = pThisContext->pThisDev;
IRUSB_ASSERT( NULL != pThisDev );
pContextIrp = pThisContext->pIrp; pContextUrb = pThisContext->pUrb; //
// Perform various IRP, URB, and buffer 'sanity checks'
//
IRUSB_ASSERT( pContextIrp == pIrp ); // check we're not a bogus IRP
IRUSB_ASSERT( pContextUrb != NULL );
status = pIrp->IoStatus.Status;
//
// we should have failed, succeeded, or cancelled, but NOT be pending
//
IRUSB_ASSERT( STATUS_PENDING != status );
//
// Remove from the pending queue (only if NOT cancelled)
//
if( status != STATUS_CANCELLED ) { KIRQL OldIrql; KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->ReadWritePendingCount ); }
//pIrp->IoStatus.Information = pContextUrb->UrbControlVendorClassRequest.TransferBufferLength;
DEBUGMSG(DBG_OUT, (" St4200CompleteReadWriteRequest pIrp->IoStatus.Status = 0x%x\n", status)); //DEBUGMSG(DBG_OUT,
// (" St4200CompleteReadWriteRequest pIrp->IoStatus.Information = 0x%x, dec %d\n", pIrp->IoStatus.Information,pIrp->IoStatus.Information));
//
// Free the IRP.
//
IoFreeIrp( pIrp ); InterlockedIncrement( &pThisDev->NumReadWrites );
IrUsb_DecIoCount( pThisDev ); // we will track count of pending irps
// Free the URB.
MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL;
//
// Put back on the available queue
//
ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount );
if( ( STATUS_SUCCESS != status ) && ( STATUS_CANCELLED != status ) ) { InterlockedIncrement( (PLONG)&pThisDev->NumReadWriteErrors ); //
// We have a serious USB failure, we'll have to issue a total reset
//
if( !pThisDev->fPendingClearTotalStall && !pThisDev->fPendingHalt && !pThisDev->fPendingReset && pThisDev->fProcessing ) { DEBUGMSG(DBG_ERR, (" St4200CompleteReadWriteRequest error, will schedule an entire reset\n")); InterlockedExchange( (PLONG)&pThisDev->fPendingClearTotalStall, TRUE ); ScheduleWorkItem( pThisDev, RestoreIrDevice, NULL, 0 ); } }
//
// This will only work as long as we serialize the access to the hardware
//
pThisDev->StatusReadWrite = status; //
// Signal we're done
//
KeSetEvent( &pThisDev->EventSyncUrb, 0, FALSE ); DEBUGMSG(DBG_FUNC, ("-St4200CompleteReadWriteRequest\n")); return STATUS_MORE_PROCESSING_REQUIRED; }
#if defined( WORKAROUND_STUCK_AFTER_GEAR_DOWN )
/*****************************************************************************
* * Function: St4200FakeSend * * Synopsis: forces a bulk out transfer * * Arguments: pDevice - pointer to current ir device object * pData - pointer to bulk data * DataSize - size of bulk data * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200FakeSend( IN PVOID pDevice, PUCHAR pData, ULONG DataSize ) { NTSTATUS status = STATUS_SUCCESS; PIRUSB_CONTEXT pThisContext; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; PIRP pIrp; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; PLIST_ENTRY pListEntry;
DEBUGMSG(DBG_FUNC, ("+St4200FakeSend\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" St4200FakeSend failed to find a free context struct\n")); IRUSB_ASSERT( 0 );
status = STATUS_UNSUCCESSFUL; goto done; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
//
// MS Security recommendation - allocate a new urb.
//
pThisContext->UrbLen = sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER ); pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen); if (pThisContext->pUrb == NULL) { DEBUGMSG(DBG_ERR, (" St4200FakeSend abort due to urb alloc failure\n")); goto done; } pUrb = pThisContext->pUrb;
//
// Now that we have created the urb, we will send a
// request to the USB device object.
//
pUrbTargetDev = pThisDev->pUsbDevObj;
//
// make an irp sending to usbhub
//
pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
if( NULL == pIrp ) { DEBUGMSG(DBG_ERR, (" St4200FakeSend failed to alloc IRP\n"));
MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL; ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount ); status = STATUS_UNSUCCESSFUL; goto done; }
pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0;
pThisContext->pIrp = pIrp;
//
// Build our URB for USBD
//
pUrb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT)sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER ); pUrb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkOutPipeHandle; pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT ; // short packet is not treated as an error.
pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; pUrb->UrbBulkOrInterruptTransfer.UrbLink = NULL; pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL; pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pData; pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)DataSize;
//
// Call the class driver to perform the operation.
//
pNextStack = IoGetNextIrpStackLocation( pIrp );
IRUSB_ASSERT( pNextStack != NULL );
//
// pass the URB to the USB driver stack
//
pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; pNextStack->Parameters.Others.Argument1 = pUrb; pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine( pIrp, // irp to use
St4200CompleteReadWriteRequest, // routine to call when irp is done
DEV_TO_CONTEXT(pThisContext), // context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE // call on cancel
);
KeClearEvent( &pThisDev->EventSyncUrb );
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->ReadWritePendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->ReadWritePendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp ); DEBUGMSG( DBG_ERR,(" St4200FakeSend() Did it\n"));
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) ) { // wait, but dump out on timeout
if( status == STATUS_PENDING ) { status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { KIRQL OldIrql;
DEBUGMSG( DBG_ERR,(" St4200FakeSend() TIMED OUT! return from IoCallDriver USBD %x\n", status)); KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->ReadWritePendingCount ); // MS Security recommendation - cannot cancel IRP.
} } } else { DEBUGMSG( DBG_ERR, (" St4200FakeSend IoCallDriver FAILED(%x)\n",status)); IRUSB_ASSERT( status == STATUS_PENDING ); }
done: DEBUGMSG(DBG_FUNC, ("-St4200FakeSend\n")); return status; }
/*****************************************************************************
* * Function: St4200FakeReceive * * Synopsis: forces a bulk in transfer * * Arguments: pDevice - pointer to current ir device object * pData - pointer to bulk data * DataSize - size of bulk data * * Returns: NT_STATUS * * *****************************************************************************/ NTSTATUS St4200FakeReceive( IN PVOID pDevice, PUCHAR pData, ULONG DataSize ) { NTSTATUS status = STATUS_SUCCESS; PIRUSB_CONTEXT pThisContext; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; PIRP pIrp; PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice; PLIST_ENTRY pListEntry;
DEBUGMSG(DBG_FUNC, ("+St4200FakeReceive\n"));
// MS Security bug #538703
IRUSB_ASSERT(pDevice != NULL); IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" St4200FakeReceive failed to find a free context struct\n")); IRUSB_ASSERT( 0 );
status = STATUS_UNSUCCESSFUL; goto done; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
//
// MS Security recommendation - allocate a new urb.
//
pThisContext->UrbLen = sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER ); pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen); if (pThisContext->pUrb == NULL) { DEBUGMSG(DBG_ERR, (" St4200FakeReceive abort due to urb alloc failure\n")); goto done; } pUrb = pThisContext->pUrb;
//
// Now that we have created the urb, we will send a
// request to the USB device object.
//
pUrbTargetDev = pThisDev->pUsbDevObj;
//
// make an irp sending to usbhub
//
pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
if( NULL == pIrp ) { DEBUGMSG(DBG_ERR, (" St4200FakeReceive failed to alloc IRP\n"));
MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL; ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount ); status = STATUS_UNSUCCESSFUL; goto done; }
pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0;
pThisContext->pIrp = pIrp;
//
// Build our URB for USBD
//
pUrb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT)sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER ); pUrb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkInPipeHandle; pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN ; // short packet is not treated as an error.
pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; pUrb->UrbBulkOrInterruptTransfer.UrbLink = NULL; pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL; pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pData; pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)DataSize;
//
// Call the class driver to perform the operation.
//
pNextStack = IoGetNextIrpStackLocation( pIrp );
IRUSB_ASSERT( pNextStack != NULL );
//
// pass the URB to the USB driver stack
//
pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; pNextStack->Parameters.Others.Argument1 = pUrb; pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine( pIrp, // irp to use
St4200CompleteReadWriteRequest, // routine to call when irp is done
DEV_TO_CONTEXT(pThisContext), // context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE // call on cancel
);
KeClearEvent( &pThisDev->EventSyncUrb );
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->ReadWritePendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->ReadWritePendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp ); DEBUGMSG( DBG_ERR,(" St4200FakeReceive() Did it\n"));
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) ) { // wait, but dump out on timeout
if( status == STATUS_PENDING ) { status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { KIRQL OldIrql;
DEBUGMSG( DBG_ERR,(" St4200FakeReceive() TIMED OUT! return from IoCallDriver USBD %x\n", status)); KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->ReadWritePendingCount ); // MS Security recommendation - cannot cancel IRP.
} } } else { DEBUGMSG( DBG_ERR, (" St4200FakeReceive IoCallDriver FAILED(%x)\n",status)); IRUSB_ASSERT( status == STATUS_PENDING ); }
done: DEBUGMSG(DBG_FUNC, ("-St4200FakeReceive\n")); return status; } #endif
|