📄 smscir.h
字号:
//
// See pnp.c or READ/WRITE_HARDWARE_UCHAR
//
BOOLEAN PortIsMapped;
//
// Resource information for TRANSMIT
//
PUCHAR TransmitBaseAddress;
BOOLEAN TransmitPortIsMapped;
//
// Has the class driver sent us the handshake IOCTL
// yet? Informational use only.
//
BOOLEAN HandshakeAccepted;
//
// When the device is in priority mode (due to the
// receiving of an ENTER_PRIORITY_MODE IOCTL)
// normal receives are starved while priority receives
// are processed. Once we exit priority mode (because
// of an EXIT_PRIORITY_MODE IOCTL) we cancel any
// outstanding priority receivers and switch back
// to normal receive mode.
//
BOOLEAN InPriorityMode;
//
// The individual receiver containers
//
SMSCIR_RLC_RECEIVER Receiver;
SMSCIR_RLC_RECEIVER PriorityReceiver;
//
// The number of consecutive FFs (i.e. silence) we have seen
// from the device after a receive has started. We use this
// to determine when a data end event occurs
//
ULONG ConsecutiveFFs;
//
// The number of FFs we need to see before we
// consider the sample to be over. Defaults to
// SMSCIR_NUM_FFS_FOR_DATA_END
//
ULONG NumFFsForDataEnd;
//
// There are several IOCTLs that we wish to process serially.
// Instead of taking out a lock to protect them against
// either the same IOCTL or other IOCTLs we wish to serialize
// against, we take request from our default parallel queue
// and forward them into our serial queue.
//
WDFQUEUE SerialQueue;
//
// We need to loop in our ISR pulling data bytes out of
// our FIFO. Once we take a byte from the FIFO, we'll
// enqueue it onto a circular buffer one byte at a time
// The DPC will then run, take the raw FIFO data, RLC
// it, then enqueue it onto the currently active receiver.
//
// Note that we need to carry about the "BytesToDataEnd"
// field with us everywhere, the watermark is queued in
// the FIFO buffer, then queued into the receiver buffer
// (see isr_dpc.c).
//
UCHAR FifoBuffer[SMSCIR_FIFO_BUFFER_SIZE];
ULONG CurrentFifoBufferSize;
ULONG NextFifoIndex;
ULONG CurrentFifoIndex;
ULONG BytesToDataEnd;
//
// When we pull data from the CIRCC2 FIFO, we copy it
// into a SMSCIR_MAX_LOCAL_BUFFER_SIZE sized UCHAR array.
// When we RLC this data, we use this storage as the
// worker buffer. The reason for the size is that in the
// worst case every byte will represent 8 on/off samples
// PLUS one more space for the previous sample (see isr_dpc.c)
//
LONG RLCResultBuffer[SMSCIR_MAX_LOCAL_BUFFER_SIZE * 9];
//
// If we're doing a learning operation (a.k.a. if we're in priority
// mode) then we'll need to return the carrier of the sampled
// IR to the reader. We'll get this info from the carrier measure
// register on the device, which we'll store here
//
UCHAR CarrierMeasure;
//
// When it comes time to blast, we're going to pre-convert the user
// data into something applicable for our device. We'll build
// the converted data into SMSCIR_TX_FIFO_DATA structures linked
// together via the TxFifoDataList field and protected by the
// TxFifoDataLock. The structure currently being blasted is
// both pointed to by CurrentTxFifoData and at the head
// of the TxFifoDataList
//
PSMSCIR_TX_FIFO_DATA CurrentTxFifoData;
LIST_ENTRY TxFifoDataList;
KSPIN_LOCK TxFifoDataLock;
//
// We pend the user's blasting request so that we can do it
// asynchronously. The pended reques tis here
//
WDFREQUEST CurrentTxRequest;
ULONG BytesTransmitted;
//
// Shadow copy of the last interrupt ID we received from the
// transmitter
//
BIRCC2_INTERRUPT_ID_OR_ENABLE TxIntId;
//
// Blasting can have a tendency to underrun on a heavily loaded
// system. If an underrun occurs we can't necessarily detect
// it, so we must keep some sort of deadman in order to reset
// the device should something go wrong. When we first
// start blasting we start the deadman and when the blasting
// is completed we end it. For every piece that we blast we
// update LastBlastSentTime in the DPC. If the device doesn't
// interrupt within X amount of time after that the deadman
// timer will notice and reset the transmitter (and potentially
// reset the receiver)
//
WDFTIMER DeadManTimer;
LARGE_INTEGER LastBlastSentTime;
//
// The key used to wake the sytem via the CIR block is configurable.
// ArmForWakeData contains the information about which key will
// be used to wake the sytem
//
SMSCIR_ARM_FOR_WAKE_DATA ArmForWakeData;
}SMSCIR_DATA, *PSMSCIR_DATA;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SMSCIR_DATA, GetIrData)
//
// Here we define the functions that we use to write to the device
// in a non-processor architecture specific way. We call the correct
// function based on whether the port is in memory or port space. This is
// determined when we claim our resources.
//
// You might be concerned about the overhead incurred by using these functions.
// Note that we've declared them as "forceinline" which should result in code
// generation that's equivalent to a macro. While this function adds a test
// for every read/write operation, that's the price we pay for not knowing
// until run-time whether our registers are in port or memory space. Note that
// you can't directly call the appropriate function via a pointer, because
// you don't know if WRITE_REGISTER_UCHAR (for example) is implemented as a
// function or a macro on any given processor architecture (it's a macro on
// IA64, by the way).
//
__forceinline
VOID
WRITE_HARDWARE_UCHAR(PSMSCIR_DATA DevData, UCHAR Register, UCHAR Value) {
if(DevData->PortIsMapped) {
WRITE_REGISTER_UCHAR(DevData->BaseAddress+Register, Value);
} else {
WRITE_PORT_UCHAR(DevData->BaseAddress+Register, Value);
}
}
__forceinline
UCHAR
READ_HARDWARE_UCHAR(PSMSCIR_DATA DevData, UCHAR Register) {
if(DevData->PortIsMapped) {
return (READ_REGISTER_UCHAR(DevData->BaseAddress+Register));
} else {
return (READ_PORT_UCHAR(DevData->BaseAddress+Register));
}
}
__forceinline
VOID
WRITE_TRANSMIT_UCHAR(PSMSCIR_DATA DevData, UCHAR Register, UCHAR Value) {
if(DevData->TransmitPortIsMapped) {
WRITE_REGISTER_UCHAR(DevData->TransmitBaseAddress+Register, Value);
} else {
WRITE_PORT_UCHAR(DevData->TransmitBaseAddress+Register, Value);
}
}
__forceinline
UCHAR
READ_TRANSMIT_UCHAR(PSMSCIR_DATA DevData, UCHAR Register) {
if(DevData->TransmitPortIsMapped) {
return (READ_REGISTER_UCHAR(DevData->TransmitBaseAddress+Register));
} else {
return (READ_PORT_UCHAR(DevData->TransmitBaseAddress+Register));
}
}
__forceinline
VOID
WRITE_TRANSMIT_BUFFER_UCHAR(PSMSCIR_DATA DevData,
UCHAR Register,
PUCHAR Buffer,
ULONG Count){
if(DevData->TransmitPortIsMapped) {
ULONG i;
//
// Memory mapped I/O...Need to fake it.
//
for (i = 0; i < Count; i++) {
WRITE_REGISTER_UCHAR(DevData->TransmitBaseAddress+Register,
Buffer[i]);
}
} else {
WRITE_PORT_BUFFER_UCHAR(DevData->TransmitBaseAddress+Register,
Buffer,
Count);
}
}
//
// Handy Dandy Time Macros
//
#define ABSOLUTE(wait) (wait)
#define RELATIVE(wait) (-(wait))
#define NANOSECONDS(nanos) \
(((signed __int64)(nanos)) / 100L)
#define MICROSECONDS(micros) \
(((signed __int64)(micros)) * NANOSECONDS(1000L))
#define MILLISECONDS(milli) \
(((signed __int64)(milli)) * MICROSECONDS(1000L))
#define SECONDS(seconds) \
(((signed __int64)(seconds)) * MILLISECONDS(1000L))
//
// Shared globals
//
extern UNICODE_STRING SmscIrRegistryPath;
extern SAMPLE_RUN SmscIrSampleTable[256][8];
//
// Prototypes
//
//
// usbir.c
//
NTSTATUS
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
);
VOID
SmscIrEvtDriverUnload(
WDFDRIVER Driver
);
//
// io.c
//
VOID
SmscIrEvtIoDeviceControl(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
);
VOID
SmscIrEvtDeviceFileCreate(
IN WDFDEVICE Device,
IN WDFREQUEST Request,
IN WDFFILEOBJECT FileObject
);
VOID
SmscIrEvtFileClose(
IN WDFFILEOBJECT FileObject
);
VOID
SmscIrEvtIoDeviceControlSerial(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
);
VOID
IrHandshake(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request
);
VOID
IrReceive(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T OutputBufferLength
);
VOID
IrPriorityReceive(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T OutputBufferLength
);
VOID
IrTransmit(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T OutputBufferLength,
SIZE_T InputBufferLength
);
VOID
IrReceiveInProgressCancel(
IN WDFREQUEST Request
);
VOID
IrPriorityReceiveInProgressCancel(
IN WDFREQUEST Request
);
VOID
IrUserOpen(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request
);
VOID
IrUserClose(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request
);
VOID
IrEnterPriorityMode(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T InputBufferLength
);
VOID
IrExitPriorityMode(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request
);
VOID
IrGetDevCaps(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T OutputBufferLength
);
VOID
IrGetEmitters(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T OutputBufferLength
);
VOID
IrFlashReceiver(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request,
SIZE_T InputBufferLength
);
VOID
IrResetDevice(
PSMSCIR_DATA DeviceData,
WDFREQUEST Request
);
//
// pnp.c
//
NTSTATUS
SmscIrEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
);
NTSTATUS
SmscIrEvtDevicePrepareHardware(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourceList,
IN WDFCMRESLIST ResourceListTranslated
);
NTSTATUS
SmscIrEvtDeviceReleaseHardware(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourceListTranslated
);
NTSTATUS
SmscIrEvtDeviceD0Entry(
IN WDFDEVICE Device,
IN WDF_POWER_DEVICE_STATE PreviousState
);
NTSTATUS
SmscIrEvtDeviceD0Exit(
IN WDFDEVICE Device,
IN WDF_POWER_DEVICE_STATE TargetState
);
//
// isr.c
//
NTSTATUS
SmscIrEvtInterruptEnable(
IN WDFINTERRUPT Interrupt,
IN WDFDEVICE Device
);
BOOLEAN
SmscIrEvtInterruptIsr(
IN WDFINTERRUPT Interrupt,
IN ULONG MessageID
);
ULONG
SmscIrFifoBytesRemaining(
IN PSMSCIR_DATA DeviceData
);
ULONG
SmscIrDequeueFifoData(
IN PSMSCIR_DATA DeviceData,
__out_bcount(MaxLen) PUCHAR Buffer,
ULONG MaxLen,
__out PBOOLEAN DataEnd
);
NTSTATUS
SmscIrEvtInterruptDisable(
IN WDFINTERRUPT Interrupt,
IN WDFDEVICE Device
);
//
// Dpc.c
//
VOID
SmscIrEvtInterruptDpc(
IN WDFINTERRUPT Interrupt,
IN WDFOBJECT Object
);
VOID
SmscIrEnqueueRLCData(
PSMSCIR_RLC_RECEIVER RLCReceiver,
__in_bcount(Length) PUCHAR RLCData,
ULONG Length,
IN BOOLEAN DataEnd
);
ULONG
SmscIrDequeueRLCData(
PSMSCIR_RLC_RECEIVER RLCReceiver,
__out_bcount(MaxLen) PUCHAR Buffer,
ULONG MaxLen,
__out PBOOLEAN DataEnd
);
VOID
SmscIrProcessPendingReceives(
IN PSMSCIR_RLC_RECEIVER RLCReceiver,
__out WDFREQUEST *CompleteWithSuccess,
__out WDFREQUEST *CompleteWithFailure,
__out PNTSTATUS FailureStatus
);
NTSTATUS
IrSetupNextRequest(
IN PSMSCIR_RLC_RECEIVER RLCReceiver,
OUT WDFREQUEST *CompleteWithFailure,
OUT PNTSTATUS FailureStatus
);
VOID
SmscIrContinueBlasting(
IN PSMSCIR_DATA DeviceData,
OUT WDFREQUEST *TxRequestToComplete,
OUT PNTSTATUS CompletionStatus
);
VOID
SmscIrEvtDeadManTimerForTransmit(
IN WDFTIMER Timer
);
//
// Wake.c
//
VOID
SmscIrSetWakeKeyInfo(
IN PSMSCIR_DATA DeviceData
);
NTSTATUS
SmscIrEvtDeviceWakeArm(
IN WDFDEVICE Device
);
BOOLEAN
SmscIrDeviceWokeSystem(
IN PSMSCIR_DATA DeviceData
);
#endif // ndef SmscIrH
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -