|
|
/**************************************************************************************************************************
* DIAGS.C SigmaTel STIR4200 diagnostic module ************************************************************************************************************************** * (C) Unpublished Copyright of Sigmatel, Inc. All Rights Reserved. * * * Created: 04/27/2000 * Version 0.92 * Edited: 05/12/2000 * Version 0.94 * Edited: 05/19/2000 * Version 0.95 * Edited: 05/24/2000 * Version 0.96 * Edited: 10/09/2000 * Version 1.10 * * **************************************************************************************************************************/
#if defined(DIAGS)
#define DOBREAKS // enable debug breaks
#include <ndis.h>
#include <ntddndis.h> // defines OID's
#include <usbdi.h>
#include <usbdlib.h>
#include "debug.h"
#include "ircommon.h"
#include "irndis.h"
#include "irusb.h"
#include "stir4200.h"
#include "diags.h"
/*****************************************************************************
* * Function: Diags_BufferToFirPacket * * Synopsis: convert a buffer to a Fir IR packet * * Write the IR packet into the provided buffer and report * its actual size. * * Arguments: pIrDev - pointer to device instance * pIrPacketBuf - output buffer * IrPacketBufLen - output buffer size * pContigPacketBuf - temporary staging buffer (input buffer) * ContigPacketLen - input buffer size * pIrPacketLen - lenght of the converted data * * MS Security bug #533243 * Note: size of pContigPacketBuf staging buffer is: * MAX_TOTAL_SIZE_WITH_ALL_HEADERS + FAST_IR_FCS_SIZE * * Returns: TRUE - on success * FALSE - on failure * * *****************************************************************************/ BOOLEAN Diags_BufferToFirPacket( IN PIR_DEVICE pIrDev, OUT PUCHAR pIrPacketBuf, ULONG IrPacketBufLen, IN PUCHAR pContigPacketBuf, ULONG ContigPacketLen, OUT PULONG pIrPacketLen ) { ULONG I_fieldBytes; FAST_IR_FCS_TYPE fcs, *pfcs; ULONG i, TotalBytes, EscSize; PSTIR4200_FRAME_HEADER pFrameHeader = (PSTIR4200_FRAME_HEADER)pIrPacketBuf; PUCHAR pIrPacketBufFrame = pIrPacketBuf + sizeof(STIR4200_FRAME_HEADER);
/***********************************************/ /* Make sure that the packet is big enough */ /* to be legal. It consists of an A, C, and */ /* variable-length I field. */ /***********************************************/ if( ContigPacketLen < IRDA_A_C_TOTAL_SIZE ) { DEBUGMSG(DBG_ERR, (" Diags_BufferToFirPacket(): Packet is too small\n")); return FALSE; } else { I_fieldBytes = ContigPacketLen - IRDA_A_C_TOTAL_SIZE; }
/***********************************************/ /* Make sure that we won't overwrite our */ /* contiguous buffer */ /***********************************************/ if( (ContigPacketLen > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) || (MAX_POSSIBLE_IR_PACKET_SIZE_FOR_DATA(I_fieldBytes) > IrPacketBufLen) ) { /***********************************************/ /* The packet is too large. Tell the caller */ /* to retry with a packet size large enough */ /* to get past this stage next time. */ /***********************************************/ DEBUGMSG(DBG_ERR, (" Diags_BufferToFirPacket(): Packet is too big\n")); return FALSE; }
/***********************************************/ /* Compute the FCS on the packet BEFORE */ /* applying transparency fixups. The FCS */ /* also must be sent using ESC-char */ /* transparency. */ /***********************************************/ fcs = ComputeFCS32( pContigPacketBuf, ContigPacketLen );
/***********************************************/ /* Add FCS to packet... */ /***********************************************/ pfcs = (FAST_IR_FCS_TYPE *)&pContigPacketBuf[ContigPacketLen]; *pfcs = fcs;
/***********************************************/ /* Build the STIr4200 FIR frame. */ /***********************************************/
/***********************************************/ /* Add preamble... */ /***********************************************/ memset( pIrPacketBufFrame, STIR4200_FIR_PREAMBLE, STIR4200_FIR_PREAMBLE_SIZ );
/***********************************************/ /* Add BOF's... */ /***********************************************/ memset( &pIrPacketBufFrame[STIR4200_FIR_PREAMBLE_SIZ], STIR4200_FIR_BOF, STIR4200_FIR_BOF_SIZ ); /***********************************************/ /* Escape A, C, I & CRC fields of packet... */ /***********************************************/ EscSize = ContigPacketLen + FAST_IR_FCS_SIZE; for( i = 0, TotalBytes = STIR4200_FIR_PREAMBLE_SIZ + STIR4200_FIR_BOF_SIZ; i < EscSize; i++ ) { UCHAR c;
switch( c = pContigPacketBuf[i] ) { case STIR4200_FIR_ESC_CHAR: pIrPacketBufFrame[TotalBytes++] = STIR4200_FIR_ESC_CHAR; pIrPacketBufFrame[TotalBytes++] = STIR4200_FIR_ESC_DATA_7D; break; case STIR4200_FIR_BOF: // BOF = EOF too
pIrPacketBufFrame[TotalBytes++] = STIR4200_FIR_ESC_CHAR; pIrPacketBufFrame[TotalBytes++] = STIR4200_FIR_ESC_DATA_7E; break; case STIR4200_FIR_PREAMBLE: pIrPacketBufFrame[TotalBytes++] = STIR4200_FIR_ESC_CHAR; pIrPacketBufFrame[TotalBytes++] = STIR4200_FIR_ESC_DATA_7F; break; default: pIrPacketBufFrame[TotalBytes++] = c; } }
/***********************************************/ /* Add EOF's... */ /***********************************************/ memset( &pIrPacketBufFrame[TotalBytes], STIR4200_FIR_EOF, STIR4200_FIR_EOF_SIZ );
/***********************************************/ /* Add in STIr4200 header... */ /***********************************************/ TotalBytes += STIR4200_FIR_EOF_SIZ; pFrameHeader->id1 = STIR4200_HEADERID_BYTE1; pFrameHeader->id2 = STIR4200_HEADERID_BYTE2; pFrameHeader->sizlsb = LOBYTE(TotalBytes); pFrameHeader->sizmsb = HIBYTE(TotalBytes);
/***********************************************/ /* Calc size packet w/escaped data... */ /***********************************************/ *pIrPacketLen = TotalBytes + sizeof(STIR4200_FRAME_HEADER);
return TRUE; }
/*****************************************************************************
* * Function: Diags_BufferToSirPacket * * Synopsis: convert a buffer to a Sir IR packet * * Write the IR packet into the provided buffer and report * its actual size. * * Arguments: pIrDev - pointer to device instance * pPacket - NDIS packet to convert * pIrPacketBuf - output buffer * IrPacketBufLen - output buffer size * pContigPacketBuf - temporary staging buffer (input buffer) * ContigPacketLen - input buffer size * pIrPacketLen - lenght of the converted data * * MS Security bug #533243 * Note: size of pContigPacketBuf staging buffer is: * MAX_TOTAL_SIZE_WITH_ALL_HEADERS + FAST_IR_FCS_SIZE * * Returns: TRUE - on success * FALSE - on failure * * *****************************************************************************/ BOOLEAN Diags_BufferToSirPacket( IN PIR_DEVICE pIrDev, OUT PUCHAR pIrPacketBuf, ULONG IrPacketBufLen, IN PUCHAR pContigPacketBuf, ULONG ContigPacketLen, USHORT ExtraBOFs, OUT PULONG pIrPacketLen ) { ULONG i; ULONG I_fieldBytes, totalBytes = 0; ULONG numExtraBOFs; SLOW_IR_FCS_TYPE fcs, tmpfcs; UCHAR fcsBuf[SLOW_IR_FCS_SIZE * 2]; ULONG fcsLen = 0; UCHAR nextChar; PSTIR4200_FRAME_HEADER pFrameHeader = (PSTIR4200_FRAME_HEADER)pIrPacketBuf; PUCHAR pIrPacketBufFrame = pIrPacketBuf + sizeof(STIR4200_FRAME_HEADER);
/***********************************************/ /* Make sure that the packet is big enough */ /* to be legal. It consists of an A, C, and */ /* variable-length I field. */ /***********************************************/ if( ContigPacketLen < IRDA_A_C_TOTAL_SIZE ) { DEBUGMSG(DBG_ERR, (" NdisToSirPacket(): Packet is too small\n")); return FALSE; } else { I_fieldBytes = ContigPacketLen - IRDA_A_C_TOTAL_SIZE; }
/***********************************************/ /* Make sure that we won't overwrite our */ /* contiguous buffer. Make sure that the */ /* passed-in buffer can accomodate this */ /* packet's data no matter how much it */ /* grows through adding ESC-sequences, etc. */ /***********************************************/ if( (ContigPacketLen > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) || (MAX_POSSIBLE_IR_PACKET_SIZE_FOR_DATA(I_fieldBytes) > IrPacketBufLen) ) { //
// Packet is too big
//
DEBUGMSG(DBG_ERR, (" NdisToSirPacket(): Packet is too big\n")); return FALSE; }
/***********************************************/ /* Compute the FCS on the packet BEFORE */ /* applying transparency fixups. The FCS */ /* also must be sent using ESC-char */ /* transparency, so figure out how large */ /* the fcs will really be. */ /***********************************************/ fcs = ComputeFCS16( pContigPacketBuf, ContigPacketLen );
for( i = 0, tmpfcs = fcs, fcsLen = 0; i < SLOW_IR_FCS_SIZE; tmpfcs >>= 8, i++ ) { UCHAR fcsbyte = tmpfcs & 0x00ff;
switch( fcsbyte ) { case SLOW_IR_BOF: case SLOW_IR_EOF: case SLOW_IR_ESC: fcsBuf[fcsLen++] = SLOW_IR_ESC; fcsBuf[fcsLen++] = fcsbyte ^ SLOW_IR_ESC_COMP; break; default: fcsBuf[fcsLen++] = fcsbyte; break; } }
/***********************************************/ /* Now begin building the IR frame. */ /* */ /* This is the final format: */ /* */ /* BOF (1) */ /* extra BOFs ... */ /* NdisMediumIrda packet (from NDIS): */ /* Address (1) */ /* Control (1) */ /* FCS (2) */ /* EOF (1) */ /* */ /* Prepend BOFs (extra BOFs + 1 actual BOF) */ /***********************************************/ numExtraBOFs = ExtraBOFs; if( numExtraBOFs > MAX_NUM_EXTRA_BOFS ) { numExtraBOFs = MAX_NUM_EXTRA_BOFS; }
for( i = totalBytes = 0; i < numExtraBOFs; i++ ) { *(SLOW_IR_BOF_TYPE*)(pIrPacketBufFrame + totalBytes) = SLOW_IR_EXTRA_BOF; totalBytes += SLOW_IR_EXTRA_BOF_SIZE; }
*(SLOW_IR_BOF_TYPE*)(pIrPacketBufFrame + totalBytes) = SLOW_IR_BOF; totalBytes += SLOW_IR_BOF_SIZE;
/***********************************************/ /* Copy the NDIS packet from our contiguous */ /* buffer, applying escape-char */ /* transparency. */ /***********************************************/ for( i = 0; i < ContigPacketLen; i++ ) { nextChar = pContigPacketBuf[i]; switch( nextChar ) { case SLOW_IR_BOF: case SLOW_IR_EOF: case SLOW_IR_ESC: pIrPacketBufFrame[totalBytes++] = SLOW_IR_ESC; pIrPacketBufFrame[totalBytes++] = nextChar ^ SLOW_IR_ESC_COMP; break; default: pIrPacketBufFrame[totalBytes++] = nextChar; break; } }
/***********************************************/ /* Add FCS, EOF. */ /***********************************************/ NdisMoveMemory( (PVOID)(pIrPacketBufFrame + totalBytes), (PVOID)fcsBuf, fcsLen ); totalBytes += fcsLen; *(SLOW_IR_EOF_TYPE*)(pIrPacketBufFrame + totalBytes) = (UCHAR)SLOW_IR_EOF; totalBytes += SLOW_IR_EOF_SIZE;
/***********************************************/ /* Add in STIr4200 header... */ /***********************************************/ pFrameHeader->id1 = STIR4200_HEADERID_BYTE1; pFrameHeader->id2 = STIR4200_HEADERID_BYTE2; pFrameHeader->sizlsb = LOBYTE(totalBytes); pFrameHeader->sizmsb = HIBYTE(totalBytes);
*pIrPacketLen = totalBytes + sizeof(STIR4200_FRAME_HEADER); return TRUE; }
/*****************************************************************************
* * Function: Diags_Enable * * Synopsis: Switches the STIr4200 to diagnostic mode * * Arguments: pThisDev - pointer to IR device * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS Diags_Enable( IN OUT PIR_DEVICE pThisDev ) { PIRUSB_CONTEXT pThisContext; PLIST_ENTRY pListEntry;
//
// Make sure diags aren't already active
//
if( pThisDev->DiagsActive ) { DEBUGMSG(DBG_ERR, (" Diags_Enable diags already active\n")); return STATUS_UNSUCCESSFUL; }
//
// Get a context to switch to the new mode
//
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" Diags_Enable failed to find a free context struct\n")); IRUSB_ASSERT( 0 ); return STATUS_UNSUCCESSFUL; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_DIAGS_ENABLE; //
// Disable further interaction with the stack
//
InterlockedExchange( &pThisDev->DiagsPendingActivation, TRUE );
//
// Queue the context and then wait
//
KeClearEvent( &pThisDev->EventDiags ); ExInterlockedInsertTailList( &pThisDev->SendBuiltQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendBuiltCount );
MyKeWaitForSingleObject( pThisDev, &pThisDev->EventDiags, 0 );
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_Disable * * Synopsis: Switches the STIr4200 back to normal mode * * Arguments: pThisDev - pointer to IR device * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS Diags_Disable( IN OUT PIR_DEVICE pThisDev ) { PRCV_BUFFER pRecBuf; PLIST_ENTRY pEntry; //
// Make sure diags are active
//
if( !pThisDev->DiagsActive ) { DEBUGMSG(DBG_ERR, (" Diags_Disable diags not active\n")); return STATUS_UNSUCCESSFUL; }
//
// Enable interaction with the stack and no queuing of contexts is required
//
InterlockedExchange( &pThisDev->DiagsActive, FALSE ); InterlockedExchange( &pThisDev->DiagsPendingActivation, FALSE );
//
// Get rid of all the diagnostic buffers
//
while( pEntry=ExInterlockedRemoveHeadList( &pThisDev->DiagsReceiveQueue, &pThisDev->DiagsReceiveLock ) ) { pRecBuf = CONTAINING_RECORD( pEntry, RCV_BUFFER, ListEntry );
InterlockedExchange( &pRecBuf->DataLen, 0 ); InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE ); }
return STATUS_SUCCESS; }
/*****************************************************************************
* * Function: Diags_ReadRegisters * * Synopsis: Prepares a context to read the registers * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS Diags_ReadRegisters( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_READ_REGISTERS_IOCTL pIOCTL, ULONG IOCTLSize ) { PIRUSB_CONTEXT pThisContext; PLIST_ENTRY pListEntry;
//
// First basic validation
//
if( IOCTLSize < sizeof(DIAGS_READ_REGISTERS_IOCTL) ) { DEBUGMSG(DBG_ERR, (" Diags_ReadRegisters invalid output buffer\n")); return STATUS_UNSUCCESSFUL; } //
// Now we get a little more sofisticated
//
if( ((pIOCTL->FirstRegister+pIOCTL->NumberRegisters)>(STIR4200_MAX_REG+1)) || ((IOCTLSize+1)<(sizeof(DIAGS_READ_REGISTERS_IOCTL)+pIOCTL->NumberRegisters)) ) { DEBUGMSG(DBG_ERR, (" Diags_ReadRegisters invalid output buffer\n")); return STATUS_UNSUCCESSFUL; }
pThisDev->pIOCTL = pIOCTL; pThisDev->IOCTLStatus = STATUS_UNSUCCESSFUL; //
// Get a context to queue
//
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" Diags_ReadRegisters failed to find a free context struct\n")); IRUSB_ASSERT( 0 ); return STATUS_UNSUCCESSFUL; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_DIAGS_READ_REGISTERS; //
// Queue the context and then wait
//
KeClearEvent( &pThisDev->EventDiags ); ExInterlockedInsertTailList( &pThisDev->SendBuiltQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendBuiltCount );
MyKeWaitForSingleObject( pThisDev, &pThisDev->EventDiags, 0 );
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_WriteRegister * * Synopsis: Prepares a context to write the registers * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS Diags_WriteRegister( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_READ_REGISTERS_IOCTL pIOCTL, ULONG IOCTLSize ) { PIRUSB_CONTEXT pThisContext; PLIST_ENTRY pListEntry;
//
// Validation
//
if( (IOCTLSize < sizeof(DIAGS_READ_REGISTERS_IOCTL)) || (pIOCTL->FirstRegister>STIR4200_MAX_REG) ) { DEBUGMSG(DBG_ERR, (" Diags_WriteRegister invalid output buffer\n")); return STATUS_UNSUCCESSFUL; } pThisDev->pIOCTL = pIOCTL; pThisDev->IOCTLStatus = STATUS_UNSUCCESSFUL; //
// Get a context to queue
//
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" Diags_ReadRegisters failed to find a free context struct\n")); IRUSB_ASSERT( 0 ); return STATUS_UNSUCCESSFUL; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_DIAGS_WRITE_REGISTER; //
// Queue the context and the wait
//
KeClearEvent( &pThisDev->EventDiags ); ExInterlockedInsertTailList( &pThisDev->SendBuiltQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendBuiltCount );
MyKeWaitForSingleObject( pThisDev, &pThisDev->EventDiags, 0 );
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_PrepareBulk * * Synopsis: Prepares a context to do a bulk transfer * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * DirectionOut - TRUE if bulk-out, FALSE if bulk-in * * Returns: NT status code * * Notes: * *****************************************************************************/ NTSTATUS Diags_PrepareBulk( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_BULK_IOCTL pIOCTL, ULONG IOCTLSize, BOOLEAN DirectionOut ) { PIRUSB_CONTEXT pThisContext; PLIST_ENTRY pListEntry;
//
// First basic validation
//
if( IOCTLSize < sizeof(DIAGS_BULK_IOCTL) ) { DEBUGMSG(DBG_ERR, (" Diags_PrepareBulk invalid input buffer\n")); return STATUS_UNSUCCESSFUL; } //
// Now we get a little more sofisticated
//
if( IOCTLSize < (sizeof(DIAGS_BULK_IOCTL)+pIOCTL->DataSize-1) ) { DEBUGMSG(DBG_ERR, (" Diags_PrepareBulk invalid output buffer\n")); return STATUS_UNSUCCESSFUL; }
pThisDev->pIOCTL = pIOCTL; pThisDev->IOCTLStatus = STATUS_UNSUCCESSFUL; //
// Get a context to queue
//
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" Diags_PrepareBulk failed to find a free context struct\n")); IRUSB_ASSERT( 0 ); return STATUS_UNSUCCESSFUL; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); if( DirectionOut ) pThisContext->ContextType = CONTEXT_DIAGS_BULK_OUT; else pThisContext->ContextType = CONTEXT_DIAGS_BULK_IN;
//
// Queue the context and then wait
//
KeClearEvent( &pThisDev->EventDiags ); ExInterlockedInsertTailList( &pThisDev->SendBuiltQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendBuiltCount );
MyKeWaitForSingleObject( pThisDev, &pThisDev->EventDiags, 0 );
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_PrepareSend * * Synopsis: Prepares a diagnostic send * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * * Returns: None * * Notes: * *****************************************************************************/ NTSTATUS Diags_PrepareSend( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_SEND_IOCTL pIOCTL, ULONG IOCTLSize ) { PIRUSB_CONTEXT pThisContext; PLIST_ENTRY pListEntry; ULONG Size = sizeof(DIAGS_SEND_IOCTL)+pIOCTL->DataSize-1;
//
// First basic validation
//
if( IOCTLSize < sizeof(DIAGS_SEND_IOCTL) ) { DEBUGMSG(DBG_ERR, (" Diags_PrepareBulk invalid input buffer\n")); return STATUS_UNSUCCESSFUL; } //
// Now we get a little more sofisticated
//
if( IOCTLSize < (sizeof(DIAGS_SEND_IOCTL)+pIOCTL->DataSize-1) ) { DEBUGMSG(DBG_ERR, (" Diags_PrepareSend invalid output buffer\n")); return STATUS_UNSUCCESSFUL; }
pThisDev->pIOCTL = pIOCTL; pThisDev->IOCTLStatus = STATUS_UNSUCCESSFUL; //
// Get a context to queue
//
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
if( NULL == pListEntry ) { //
// This must not happen
//
DEBUGMSG(DBG_ERR, (" Diags_PrepareSend failed to find a free context struct\n")); IRUSB_ASSERT( 0 ); return STATUS_UNSUCCESSFUL; } InterlockedDecrement( &pThisDev->SendAvailableCount );
pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry ); pThisContext->ContextType = CONTEXT_DIAGS_SEND;
//
// Queue the context and then wait
//
KeClearEvent( &pThisDev->EventDiags ); ExInterlockedInsertTailList( &pThisDev->SendBuiltQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendBuiltCount );
MyKeWaitForSingleObject( pThisDev, &pThisDev->EventDiags, 0 );
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_Receive * * Synopsis: Diagnostic receive * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * * Returns: None * * Notes: * *****************************************************************************/ NTSTATUS Diags_Receive( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_RECEIVE_IOCTL pIOCTL, ULONG IOCTLSize ) { PLIST_ENTRY pListEntry; PRCV_BUFFER pRecBuf;
//
// First basic validation
//
if( IOCTLSize < sizeof(DIAGS_RECEIVE_IOCTL) ) { DEBUGMSG(DBG_ERR, (" Diags_Receive invalid input buffer\n")); return STATUS_UNSUCCESSFUL; } //
// Get a received packet
//
pListEntry = ExInterlockedRemoveHeadList( &pThisDev->DiagsReceiveQueue, &pThisDev->DiagsReceiveLock );
if( NULL == pListEntry ) { //
// No packet available
//
return STATUS_UNSUCCESSFUL; } pRecBuf = CONTAINING_RECORD( pListEntry, RCV_BUFFER, ListEntry );
//
// Now we get a little more sofisticated
//
if( IOCTLSize < (sizeof(DIAGS_RECEIVE_IOCTL)+pIOCTL->DataSize-1) ) { DEBUGMSG(DBG_ERR, (" Diags_Receive invalid output buffer\n")); return STATUS_UNSUCCESSFUL; }
//
// Fix MS Security bug #534771
//
if (pIOCTL->DataSize < pRecBuf->DataLen) { DEBUGMSG(DBG_ERR, (" Diags_Receive output buffer too small\n")); return STATUS_UNSUCCESSFUL; }
//
// Copy the data
//
NdisMoveMemory( pIOCTL->pData, pRecBuf->pDataBuf, pRecBuf->DataLen ); pIOCTL->DataSize = (USHORT)pRecBuf->DataLen; pThisDev->pIOCTL = pIOCTL; InterlockedExchange( &pRecBuf->DataLen, 0 ); InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
return STATUS_SUCCESS; }
/*****************************************************************************
* * Function: Diags_GetSpeed * * Synopsis: Retrieves the current speed * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * * Returns: None * * Notes: * *****************************************************************************/ NTSTATUS Diags_GetSpeed( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_SPEED_IOCTL pIOCTL, ULONG IOCTLSize ) { //
// First basic validation
//
if( IOCTLSize < sizeof(DIAGS_SPEED_IOCTL) ) { DEBUGMSG(DBG_ERR, (" Diags_GetSpeed invalid input buffer\n")); return STATUS_UNSUCCESSFUL; }
pIOCTL->Speed = pThisDev->currentSpeed;
return STATUS_SUCCESS; }
/*****************************************************************************
* * Function: Diags_SetSpeed * * Synopsis: Sets a new speed in diagnostic mode * * Arguments: pThisDev - pointer to IR device * pIOCTL - pointer to IOCTL descriptor * IOCTLSize - size of the IOCTL buffer * * Returns: None * * Notes: * *****************************************************************************/ NTSTATUS Diags_SetSpeed( IN OUT PIR_DEVICE pThisDev, OUT PDIAGS_SPEED_IOCTL pIOCTL, ULONG IOCTLSize ) { // MS Security fix bug #535716
NDIS_STATUS status = STATUS_UNSUCCESSFUL; USHORT i; //
// First basic validation
//
if( IOCTLSize < sizeof(DIAGS_SPEED_IOCTL) ) { DEBUGMSG(DBG_ERR, (" Diags_SetSpeed invalid input buffer\n")); return STATUS_UNSUCCESSFUL; }
if( pThisDev->currentSpeed == pIOCTL->Speed ) { //
// We are already set to the requested speed.
//
return STATUS_SUCCESS; }
DEBUGMSG(DBG_ERR, (" Diags_SetSpeed(OID_IRDA_LINK_SPEED, 0x%x, decimal %d)\n",pIOCTL->Speed, pIOCTL->Speed));
for( i = 0; i < NUM_BAUDRATES; i++ ) { if( supportedBaudRateTable[i].BitsPerSec == pIOCTL->Speed ) { //
// Keep a pointer to the link speed which has
// been requested.
//
pThisDev->linkSpeedInfo = &supportedBaudRateTable[i];
status = NDIS_STATUS_PENDING; break; //for
} }
//
// Don't set if there is an error
//
if( NDIS_STATUS_PENDING != status ) { DEBUGMSG(DBG_ERR, (" Invalid link speed\n")); return STATUS_UNSUCCESSFUL; }
//
// Set the new speed
//
IrUsb_PrepareSetSpeed( pThisDev ); while( pThisDev->linkSpeedInfo->BitsPerSec != pThisDev->currentSpeed ) { NdisMSleep( 50000 ); }
return STATUS_SUCCESS; }
/*****************************************************************************
* * Function: Diags_CompleteEnable * * Synopsis: Completes the enabling of the diagnostic state * * Arguments: pThisDev - pointer to IR device * pContext - pinter to the operation context * * Returns: None * * Notes: * *****************************************************************************/ VOID Diags_CompleteEnable( IN OUT PIR_DEVICE pThisDev, IN PVOID pContext ) { PIRUSB_CONTEXT pThisContext = pContext;
//
// Really enable diags
//
InterlockedExchange( &pThisDev->DiagsActive, TRUE );
//
// Return the context
//
ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount );
//
// Signal
//
KeSetEvent( &pThisDev->EventDiags, 0, FALSE ); //signal we're done
}
/*****************************************************************************
* * Function: Diags_CompleteReadRegisters * * Synopsis: Reads the registers and returns the value * * Arguments: pThisDev - pointer to IR device * pContext - pinter to the operation context * * Returns: NTSTATUS * * Notes: * *****************************************************************************/ NTSTATUS Diags_CompleteReadRegisters( IN OUT PIR_DEVICE pThisDev, IN PVOID pContext ) { PDIAGS_READ_REGISTERS_IOCTL pIOCTL = pThisDev->pIOCTL; PIRUSB_CONTEXT pThisContext = pContext;
//
// Read the data
//
pThisDev->IOCTLStatus = St4200ReadRegisters( pThisDev, pIOCTL->FirstRegister, pIOCTL->NumberRegisters ); if( pThisDev->IOCTLStatus == STATUS_SUCCESS ) { NdisMoveMemory( &pIOCTL->pRegisterBuffer, &pThisDev->StIrTranceiver.FifoDataReg+pIOCTL->FirstRegister, pIOCTL->NumberRegisters ); }
//
// Return the context
//
ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount );
//
// Signal
//
KeSetEvent( &pThisDev->EventDiags, 0, FALSE ); //signal we're done
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_CompleteWriteRegister * * Synopsis: Reads the registers and returns the value * * Arguments: pThisDev - pointer to IR device * pContext - pinter to the operation context * * Returns: NTSTATUS * * Notes: * *****************************************************************************/ NTSTATUS Diags_CompleteWriteRegister( IN OUT PIR_DEVICE pThisDev, IN PVOID pContext ) { PDIAGS_READ_REGISTERS_IOCTL pIOCTL = pThisDev->pIOCTL; PIRUSB_CONTEXT pThisContext = pContext;
//
// Copy the new register value
//
NdisMoveMemory( &pThisDev->StIrTranceiver.FifoDataReg+pIOCTL->FirstRegister, &pIOCTL->pRegisterBuffer, 1 );
//
// Write to the device
//
pThisDev->IOCTLStatus = St4200WriteRegister( pThisDev, pIOCTL->FirstRegister );
//
// Return the context
//
ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount );
//
// Signal
//
KeSetEvent( &pThisDev->EventDiags, 0, FALSE ); //signal we're done
return pThisDev->IOCTLStatus; }
/*****************************************************************************
* * Function: Diags_Bulk * * Synopsis: Executes a diagnostic bulk transfer * * Arguments: pThisDev - pointer to IR device * pContext - pinter to the operation context * DirectionOut - TRUE if bulk-out, FALSE if bulk-in * * Returns: NTSTATUS * * Notes: * *****************************************************************************/ NTSTATUS Diags_Bulk( IN OUT PIR_DEVICE pThisDev, IN PVOID pContext, BOOLEAN DirectionOut ) { PDIAGS_BULK_IOCTL pIOCTL = pThisDev->pIOCTL; PIRUSB_CONTEXT pThisContext = pContext; NTSTATUS status = STATUS_SUCCESS; PIRP pIrp; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; KIRQL OldIrql;
IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
IRUSB_ASSERT( NULL != pThisContext );
//
// Stop if a halt/reset is going on
//
if( pThisDev->fPendingWriteClearStall || pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall ) { DEBUGMSG(DBG_ERR, (" Diags_Bulk abort due to pending reset or halt\n")); goto done; } //
// 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, (" Diags_Bulk abort due to urb alloc failure\n")); goto done; } pUrb = pThisContext->pUrb;
//
// Save the effective length
//
pThisDev->BufLen = pIOCTL->DataSize;
//
// 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, (" Diags_Bulk failed to alloc IRP\n")); MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); 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; if( DirectionOut ) { pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT ; pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkOutPipeHandle; } else { pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN ; pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkInPipeHandle; } // 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 = pIOCTL->pData; pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)pIOCTL->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
Diags_CompleteIrp, // 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
);
#ifdef SERIALIZE
KeClearEvent( &pThisDev->EventSyncUrb ); #endif
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->SendPendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendPendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
IRUSB_ASSERT( status == STATUS_PENDING );
status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { DEBUGMSG( DBG_ERR,(" Diags_Bulk() TIMED OUT! return from IoCallDriver USBD %x\n", status)); // MS Security recommendation - cannot cancel IRP.
IRUSB_ASSERT(0); }
done:
//
// Return the context
//
KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->SendPendingCount ); ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount );
//
// Signal
//
KeSetEvent( &pThisDev->EventDiags, 0, FALSE ); //signal we're done
return status; }
/*****************************************************************************
* * Function: Diags_Send * * Synopsis: Sends a packet through the diagnostic path * * Arguments: pThisDev - pointer to IR device * pContext - pinter to the operation context * * Returns: NTSTATUS * * Notes: * *****************************************************************************/ NTSTATUS Diags_Send( IN OUT PIR_DEVICE pThisDev, IN PVOID pContext ) { PDIAGS_SEND_IOCTL pIOCTL = pThisDev->pIOCTL; PIRUSB_CONTEXT pThisContext = pContext; NTSTATUS status = STATUS_SUCCESS; PIRP pIrp; PURB pUrb = NULL; PDEVICE_OBJECT pUrbTargetDev; PIO_STACK_LOCATION pNextStack; BOOLEAN fConvertedPacket; KIRQL OldIrql; ULONG BytesToWrite;
IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
IRUSB_ASSERT( NULL != pThisContext );
//
// Stop if a halt/reset is going on
//
if( pThisDev->fPendingWriteClearStall || pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall ) { DEBUGMSG(DBG_ERR, (" Diags_Send abort due to pending reset or halt\n")); goto done; } DEBUGMSG(DBG_ERR, (" Diags_Send() packet size: %d\n", pIOCTL->DataSize));
//
// Convert the packet to an ir frame and copy into our buffer
// and send the irp.
//
if( pThisDev->currentSpeed<=MAX_SIR_SPEED ) { fConvertedPacket = Diags_BufferToSirPacket( pThisDev, (PUCHAR)pThisDev->pBuffer, MAX_IRDA_DATA_SIZE, pIOCTL->pData, pIOCTL->DataSize, pIOCTL->ExtraBOFs, &BytesToWrite ); } else if( pThisDev->currentSpeed<=MAX_MIR_SPEED ) { fConvertedPacket = Diags_BufferToFirPacket( pThisDev, (PUCHAR)pThisDev->pBuffer, MAX_IRDA_DATA_SIZE, pIOCTL->pData, pIOCTL->DataSize, &BytesToWrite ); } else { fConvertedPacket = Diags_BufferToFirPacket( pThisDev, (PUCHAR)pThisDev->pBuffer, MAX_IRDA_DATA_SIZE, pIOCTL->pData, pIOCTL->DataSize, &BytesToWrite ); } if( fConvertedPacket == FALSE ) { DEBUGMSG(DBG_ERR, (" Diags_Send() NdisToIrPacket failed. Couldn't convert packet!\n")); goto done; }
//
// Always force turnaround
//
NdisMSleep( pThisDev->dongleCaps.turnAroundTime_usec ); //
// 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, (" Diags_Send 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, (" Diags_Send failed to alloc IRP\n")); MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); 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 = pThisDev->pBuffer; pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)BytesToWrite;
//
// 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
Diags_CompleteIrp, // 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
);
#ifdef SERIALIZE
KeClearEvent( &pThisDev->EventSyncUrb ); #endif
//
// Call IoCallDriver to send the irp to the usb port.
//
ExInterlockedInsertTailList( &pThisDev->SendPendingQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendPendingCount ); status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
//
// The USB driver should always return STATUS_PENDING when
// it receives a write irp
//
IRUSB_ASSERT( status == STATUS_PENDING );
status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
if( status == STATUS_TIMEOUT ) { DEBUGMSG( DBG_ERR,(" Diags_Send() TIMED OUT! return from IoCallDriver USBD %x\n", status)); // MS Security recommendation - cannot cancel IRP.
IRUSB_ASSERT(0); }
done: //
// Return the context
//
KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql ); RemoveEntryList( &pThisContext->ListEntry ); KeReleaseSpinLock( &pThisDev->SendLock, OldIrql ); InterlockedDecrement( &pThisDev->SendPendingCount ); ExInterlockedInsertTailList( &pThisDev->SendAvailableQueue, &pThisContext->ListEntry, &pThisDev->SendLock ); InterlockedIncrement( &pThisDev->SendAvailableCount );
//
// Signal
//
KeSetEvent( &pThisDev->EventDiags, 0, FALSE ); //signal we're done
return status; }
/*****************************************************************************
* * Function: Diags_CompleteIrp * * Synopsis: Completes a USB operation * * Arguments: pUsbDevObj - pointer to the USB device object which * completed the irp * pIrp - the irp which was completed by the * device object * Context - the context given to IoSetCompletionRoutine * before calling IoCallDriver on the irp * The Context is a pointer to the ir device object. * * Returns: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine * (IofCompleteRequest) to stop working on the irp. * *****************************************************************************/ NTSTATUS Diags_CompleteIrp( 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; PDIAGS_BULK_IOCTL pIOCTL;
//
// 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; pIOCTL = pThisDev->pIOCTL;
//
// 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; pThisDev->IOCTLStatus = status;
//
// we should have failed, succeeded, or cancelled, but NOT be pending
//
IRUSB_ASSERT( STATUS_PENDING != status );
//
// IoCallDriver has been called on this Irp;
// Set the length based on the TransferBufferLength
// value in the URB
//
pIrp->IoStatus.Information = pContextUrb->UrbBulkOrInterruptTransfer.TransferBufferLength; pIOCTL->DataSize = (USHORT)pIrp->IoStatus.Information;
//
// Free the IRP.
//
IoFreeIrp( pIrp ); InterlockedIncrement( (PLONG)&pThisDev->NumWrites );
IrUsb_DecIoCount( pThisDev ); // we will track count of pending irps
// Free the URB.
MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen); pThisContext->pUrb = NULL;
#ifdef SERIALIZE
KeSetEvent( &pThisDev->EventSyncUrb, 0, FALSE ); //signal we're done
#endif
return STATUS_MORE_PROCESSING_REQUIRED; }
#endif
|