📄 dpc.c
字号:
if (lastSampleOn == curSample->On) {
//
// This is the previous on or off sample
// overflowing into the next byte.
//
// Add the current sample value into the
// previous result. Note that this will ONLY
// happen when bitsConsumed == 8. What it means
// is that we've overflown from the last bits
// of the previous byte into the first bits
// of this byte.
//
ASSERT(bitsConsumed == 8);
resultPtr[samples-1] += curSample->Result;
} else {
resultPtr[samples++] = curSample->Result;
}
//
// Subtract the number of bits that this run
// consumed from the sample...
//
bitsConsumed -= curSample->BitsConsumed;
lastSampleOn = curSample->On;
curSample++;
}
}
//
// Store away the last piece of this
// report...
//
lastRLCPiece = resultPtr[samples-1];
//
// We possibly won't be passing that to the class driver...
//
resultLen = ((samples-1) * sizeof(LONG));
//
// Was the last piece of the previous calculation
// the same sign as the first piece of this
// report?
//
if ((RLCReceiver->LastRLCPieceOfPreviousPacket < 0 && resultPtr[0] < 0) ||
(RLCReceiver->LastRLCPieceOfPreviousPacket > 0 && resultPtr[0] > 0)) {
//
// join pieces
//
resultPtr[0] += RLCReceiver->LastRLCPieceOfPreviousPacket;
//
// Watch out for the case where we only had one sample. If
// we did then the last RLC piece needs to be modified
//
if (samples == 1) {
lastRLCPiece = resultPtr[0];
}
} else if (RLCReceiver->LastRLCPieceOfPreviousPacket) {
//
// Nope, it was different. We need to
// adjust the result pointer to be the
// beginning of the buffer, give the last
// piece of the previous calculation to the user,
// and bump the amount of bytes we'll be sending...
//
// Note that this does not take into account the
// "lastRLCPiece" that we've saved off above, that's
// the last piece of THIS packet (which we may add
// back in if this is a data end)
//
resultPtr = &RLCReceiver->DeviceData->RLCResultBuffer[0];
resultPtr[0] = RLCReceiver->LastRLCPieceOfPreviousPacket;
resultLen += sizeof(LONG);
}
//
// For some unknown reason, we get a 50 uSec period of
// silence from the SIO1049 the first time we turn on the
// learning receiver. If we hit this, skip it.
//
if ( RLCReceiver->IgnoreFirstSilence &&
resultLen >= sizeof(LONG) ) {
if ( resultPtr[0] < 0 ) {
resultPtr++;
resultLen -= sizeof(LONG);
}
//
// Turn off this flag even if we don't get the silence.
// We're trying to skip the _first_ period of silence,
// not every period of silence.
//
RLCReceiver->IgnoreFirstSilence = FALSE;
}
if (!DataEnd) {
//
// Not done yet? Store away the last piece, we'll get to it in the
// next pass.
//
RLCReceiver->LastRLCPieceOfPreviousPacket = lastRLCPiece;
} else {
//
// DONE! Up the count of samples taken, this causes it to
// include the lastRLCPiece in our return...
//
resultLen += sizeof(LONG);
//
// Start over...
//
RLCReceiver->LastRLCPieceOfPreviousPacket = 0;
}
SmscIrEnqueueRLCData(RLCReceiver,
(PUCHAR)resultPtr,
resultLen,
DataEnd);
}
VOID
__forceinline
SmscIrEnqueueRLCData(
PSMSCIR_RLC_RECEIVER RLCReceiver,
__in_bcount(Length) PUCHAR RLCData,
ULONG Length,
IN BOOLEAN DataEnd
) {
/*++
Routine Description:
This routine puts the given RLC data into the
circular buffer that the class driver requests
are satisfied from
RLCReceiver is *LOCKED* by caller on entry
Arguments:
RLCReceiver - The holder for either regular IR
receivers or priority IR receivers
RLCData - The RLC data
ReportLength - Number of bytes to enqueue
DataEnd - Is this a data end?
--*/
ULONG amountToCopy;
ASSERT(Length < RLC_RECEIVER_BUFFER_LENGTH);
if (!RLCReceiver->OpenCount) {
return;
}
RLCReceiver->CurrentBufferSize += Length;
if (RLCReceiver->NextIndex+Length > RLC_RECEIVER_BUFFER_LENGTH) {
// Wrap past end of buffer
RtlCopyMemory(RLCReceiver->RLCBuffer + RLCReceiver->NextIndex,
RLCData,
RLC_RECEIVER_BUFFER_LENGTH - RLCReceiver->NextIndex);
//
// Prefast will complain about this calculation, but it is
// correct.
//
amountToCopy = (RLC_RECEIVER_BUFFER_LENGTH - RLCReceiver->NextIndex);
#pragma prefast (suppress:412, "Calculation is correct and as designed")
RtlCopyMemory(RLCReceiver->RLCBuffer,
RLCData+amountToCopy,
Length-amountToCopy);
RLCReceiver->NextIndex = (Length - amountToCopy);
} else {
RtlCopyMemory(RLCReceiver->RLCBuffer + RLCReceiver->NextIndex,
RLCData,
Length);
RLCReceiver->NextIndex =
(RLCReceiver->NextIndex + Length == RLC_RECEIVER_BUFFER_LENGTH) ?
0 : RLCReceiver->NextIndex+Length;
}
if (RLCReceiver->CurrentBufferSize > RLC_RECEIVER_BUFFER_LENGTH) {
RLCReceiver->CurrentBufferSize = RLC_RECEIVER_BUFFER_LENGTH;
RLCReceiver->CurrentIndex = (RLCReceiver->NextIndex != 0) ?
RLCReceiver->NextIndex-1 :
RLC_RECEIVER_BUFFER_LENGTH-1;
}
//
// If this is a data end, then we'll set the watermark
// for the data end event. When the dequeue code comes
// in it will use this to know how to mark the
// DataEnd member of the RECEIVE IOCTL.
//
if (DataEnd) {
if (RLCReceiver->BytesToDataEnd) {
SmscIrTracePrint(
TRACE_LEVEL_INFORMATION,
SMSCDBG_RECEIVE_INFO,
("SmscIrEnqueueRLCData: DataEnd was already present. "
"Previous KeyUp missed"));
}
RLCReceiver->BytesToDataEnd = RLCReceiver->CurrentBufferSize;
}
}
ULONG
SmscIrDequeueRLCData(
PSMSCIR_RLC_RECEIVER RLCReceiver,
__out_bcount(MaxLen) PUCHAR Buffer,
ULONG MaxLen,
__out PBOOLEAN DataEnd
) {
/*++
Routine Description:
This routine pulls RLC data out of the given receiver
and stores it in the given buffer
RLCReceiver is *LOCKED* by caller on entry
Arguments:
RLCReceiver - The holder for either regular IR
receivers or priority IR receivers
Buffer - Buffer to copy the data into
MaxLen - Size of the Buffer parameter, in bytes
DataEnd - Is this a data end?
Return Value:
Actual number of bytes copied
--*/
ULONG bufferSize;
ULONG amountToCopy;
#if DBG
ULONG prevValue;
#endif
*DataEnd = FALSE;
if (0 == RLCReceiver->CurrentBufferSize){
return 0;
} else {
if (RLCReceiver->BytesToDataEnd) {
bufferSize = RLCReceiver->BytesToDataEnd;
} else {
bufferSize = RLCReceiver->CurrentBufferSize;
}
amountToCopy = bufferSize < MaxLen ? bufferSize : MaxLen;
if ((RLCReceiver->CurrentIndex + amountToCopy)
> RLC_RECEIVER_BUFFER_LENGTH) {
ULONG amountToCopyFirst
= RLC_RECEIVER_BUFFER_LENGTH - RLCReceiver->CurrentIndex;
RtlCopyMemory(Buffer,
RLCReceiver->RLCBuffer + RLCReceiver->CurrentIndex,
amountToCopyFirst);
//
// Prefast will complain about this calculation, but it is
// correct.
//
#pragma prefast (suppress:411, "Calculation is correct and as designed")
RtlCopyMemory(Buffer + amountToCopyFirst,
RLCReceiver->RLCBuffer,
amountToCopy - amountToCopyFirst);
RLCReceiver->CurrentIndex = amountToCopy - amountToCopyFirst;
} else {
RtlCopyMemory(Buffer,
RLCReceiver->RLCBuffer + RLCReceiver->CurrentIndex,
amountToCopy);
RLCReceiver->CurrentIndex =
((RLCReceiver->CurrentIndex + amountToCopy)
== RLC_RECEIVER_BUFFER_LENGTH) ? 0 :
RLCReceiver->CurrentIndex + amountToCopy;
}
if (RLCReceiver->BytesToDataEnd) {
#if DBG
prevValue = RLCReceiver->BytesToDataEnd;
#endif
RLCReceiver->BytesToDataEnd -= amountToCopy;
#if DBG
//
// Make sure we didn't wrap under...
//
ASSERT(RLCReceiver->BytesToDataEnd < prevValue);
#endif
*DataEnd = (BOOLEAN)(RLCReceiver->BytesToDataEnd == 0);
}
#if DBG
prevValue = RLCReceiver->CurrentBufferSize;
#endif
RLCReceiver->CurrentBufferSize -= amountToCopy;
#if DBG
//
// Make sure we didn't wrap under...
//
ASSERT(RLCReceiver->CurrentBufferSize < prevValue);
#endif
return amountToCopy;
}
}
NTSTATUS
IrSetupNextRequest(
IN PSMSCIR_RLC_RECEIVER RLCReceiver,
OUT WDFREQUEST *CompleteWithFailure,
OUT PNTSTATUS FailureStatus
) {
/*++
Routine Description:
This routine dequeues the next pending request from the receiver
queue and makes it the active/current request
RLCReceiver is *LOCKED* by caller on entry
Arguments:
RLCReceiver - Circular buffer for this IR data
CompleteWithFailure - In case of error, the request to complete
with *FailureStatus by the caller once the
lock is dropped
FailureStatus - If *CompleteWithFailure != NULL, failure
status of request.
--*/
NTSTATUS status;
WDFREQUEST nextRequest;
status = WdfIoQueueRetrieveNextRequest(RLCReceiver->PendingReceiveQueue,
&nextRequest);
if (NT_SUCCESS(status)) {
//
// We have to get slightly different parameters
// based on this being a priority IR data buffer or not
//
if (!RLCReceiver->IsPriorityReceiver) {
status = IrSetupCurrentReceive(RLCReceiver,
nextRequest);
} else {
status = IrSetupCurrentPriorityReceive(RLCReceiver,
nextRequest);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -