/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: HidSpiCx.h Abstract: Main header file for clients of the HidSpiCx class extension. Environment: Kernel-mode. --*/ // // NOTE: This header is generated by stubwork. Please make any // modifications to the corresponding template files // (.x or .y) and use stubwork to regenerate the header // #ifndef _HIDSPICX_H_ #define _HIDSPICX_H_ #ifndef WDF_EXTERN_C #ifdef __cplusplus #define WDF_EXTERN_C extern "C" #define WDF_EXTERN_C_START extern "C" { #define WDF_EXTERN_C_END } #else #define WDF_EXTERN_C #define WDF_EXTERN_C_START #define WDF_EXTERN_C_END #endif #endif WDF_EXTERN_C_START #pragma warning(push) #pragma warning(disable:4200) // zero-sized array in struct/union typedef struct _HIDSPICX_DRIVER_GLOBALS { ULONG Reserved; } HIDSPICX_DRIVER_GLOBALS, *PHIDSPICX_DRIVER_GLOBALS; typedef VOID (*HIDSPICXFUNC) (VOID); extern HIDSPICXFUNC HidspicxFunctions[]; /*++ EVT_HIDSPICX_RESETDEVICE Arguments: WDFDEVICE Device WDF handle to the device object this method is being called for. Return Value: NTSTATUS indicating whether the reset was successful or not. This method is not expected to fail at runtime, and may result in a failure of the device by HidSpiCx. Routine Description: The client driver is expected to implement and provide a reset callback. The class extension will call this function only while the hardware is in a working state (post-D0Entry after Interrupts / DMA enabled, and pre-D0Exit before Interrupts / DMA disbaled), at passive IRQL. The client driver shall synchronously reset the device, and return a status code indicating whether the physical reset was successful (*not* upon receipt of the reset response ??? which will be later provided to the class extension as an input report). --*/ typedef _Function_class_(EVT_HIDSPICX_RESETDEVICE) _IRQL_requires_same_ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS NTAPI EVT_HIDSPICX_RESETDEVICE( _In_ WDFDEVICE Device ); typedef EVT_HIDSPICX_RESETDEVICE *PFN_HIDSPICX_RESETDEVICE; /*++ EVT_HIDSPICX_NOTIFY_POWERDOWN Arguments: WDFDEVICE Device WDF handle to the device object this method is being called for. BOOLEAN ArmForWake Value indicating whether the device will be armed for wake (representing whether HidSpiCx has seen a WAIT_WAKE IRP for the device) in the target state for the impending Dx transition. Return Value: NTSTATUS indicating whether preparation for the power transition was successful or not. This method is not expected to fail at runtime, and may result in a failure of the device by HidSpiCx. Routine Description: The client driver is expected to implement and provide a callback which HidSpiCx will use to notify the client of an impending power down. The purpose of this callback is to allow the Cx to instruct the client to stop processing interrupts from the device, as the device is about to enter a low power state. The client should not resume processing interrupts until a callback to the client???s D0Entry WDF callback has occurred. The purpose of this function is to avoid the case when entering a sleep state where the Cx sends a SET_POWER SLEEP command to the device, and the device asserts interrupt to wake before the Dx IRP is completed by both the Cx and client driver. Without an additional callback instructing the client to stop hardware processing of interrupts, the hardware would issue a SPI read in response to a wake interrupt, which would violate the protocol requiring the host to first send a SET_POWER ON command before processing interrupts from the device. This function will be called by the Cx at passive IRQL, and the client should not return until interrupt processing has ceased. Whether or not the device will be armed for wake at the bus level (whether a WAIT_WAKE IRP has been sent) is provided to the client as a convenience, to avoid the client driver having to monitor for WAIT_WAKE itself if it is not a bus driver. --*/ typedef _Function_class_(EVT_HIDSPICX_NOTIFY_POWERDOWN) _IRQL_requires_same_ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS NTAPI EVT_HIDSPICX_NOTIFY_POWERDOWN( _In_ WDFDEVICE Device, _In_ BOOLEAN ArmForWake ); typedef EVT_HIDSPICX_NOTIFY_POWERDOWN *PFN_HIDSPICX_NOTIFY_POWERDOWN; #include "pshpack1.h" /*++ HIDSPICX_REPORT Description: Input and Output reports are represented using this structure. The fields correspond to their meanings as defined in the HIDSPI protocol specification, and the structure above is identical to the body part of a HIDSPI report. This is used rather than the full HIDSPI report structure including header, as the client is expected to marshall the data structures to be sent on the wire. --*/ typedef struct _HIDSPICX_REPORT { UCHAR ReportType; USHORT ReportContentLength; UCHAR ReportId; UCHAR ReportContent[0]; } HIDSPICX_REPORT; #include "poppack.h" /*++ HIDSPICX_DEVICE_CONFIG Description: Structure used to provide configuration information to HidSpiCx. Instances of this structure must be initialized using the HIDSPICX_DEVICE_CONFIG_INIT function. Members: ULONG Size This should not be explicitly set by the client driver, and will be set by HIDSPICX_DEVICE_CONFIG_INIT. PFN_HIDSPICX_RESETDEVICE EvtResetDevice Function pointer to a client-implemented device reset callback. PFN_HIDSPICX_NOTIFY_POWERDOWN EvtNotifyPowerDown Function pointer to a client-implemented power-down notification callback. WDFQUEUE InputReportQueue WDF handle to a client-created non-power-managed queue for receipt of input report WDFREQUESTS from HidSpiCx. The client may choose how reports are dispatched from this queue (manual, sequential, parallel etc). The class extension will forward a number of ???ping-pong??? read (IRP_MJ_READ) requests (as specified by the client in its configuration structure) to the provided input report queue, at IRQL <= DISPATCH_LEVEL. These requests may be programmed directly into hardware (through DMA etc) by the client driver, or selectively dequeued upon input from the peripheral device, and buffer copied into. When the peripheral device interrupts to provide a report, the client driver reads the report data, and a ping-pong is completed by the client driver to the class extension with the report body from the peripheral device. The size of the report buffers is automatically calculated by the class extension, on the basis of the peripheral device descriptor (or a default size before device descriptor retrieval). Requests may be completed by the client driver at IRQL <= DISPATCH_LEVEL. When a request is completed by the client driver, the class extension will send another request to the queue (or re-send) synchronously in the context of the request completion. The information of the requests should be set to the total bytes read from the device into the buffer (sizeof(HIDSPICX_REPORT) + ReportContentLength). In the event of a read error from the peripheral device (e.g. invalid or malformed data), the client driver may complete one of these ping pong requests with an error code and no data, or use the provided HidSpiCxNotifyDeviceReset DDI to inform the class extension of the need for a host initiated reset to occur. The class extension will cancel and re-send these requests at runtime when the buffer size changes (as part of startup / reset device descriptor retrieval flows). It is possible in certain cases (for devices not fully conforming to the protocol) for a report to be received from the device when there are no reads pending in the queue. If this is the case, the client shall notify the Cx that the device needs a reset using the HidSpiCxNotifyDeviceReset DDI, and either discard or not read the report from the device. WDFQUEUE OutputReportQueue WDF handle to a client-created non-power-managed queue for receipt of output report WDFREQUESTS from HidSpiCx. The client may choose how reports are dispatched from this queue (manual, sequential, parallel etc). The class extension will forward output (IRP_MJ_WRITE) requests to the output report queue to instruct the client driver to write a HIDSPI output report to the device. These requests may be forwarded at IRQL <= DISPATCH_LEVEL. The client driver should write the report to the bus, and complete the request with an appropriate status to indicate success or failure. On success, the request information should be set to the size of the output buffer. ULONG NumberOfInputReportRequestsToPend Optional parameter, specifying how many requests are to be pended in the Input Report Queue at a given time. If this is zero, the class extension will choose a default. ULONG Reserved Must be zero, and should not be explicitly set by client drivers. --*/ typedef struct _HIDSPICX_DEVICE_CONFIG { ULONG Size; PFN_HIDSPICX_RESETDEVICE EvtResetDevice; PFN_HIDSPICX_NOTIFY_POWERDOWN EvtNotifyPowerDown; WDFQUEUE InputReportQueue; WDFQUEUE OutputReportQueue; ULONG NumberOfInputReportRequestsToPend; ULONG Reserved; } HIDSPICX_DEVICE_CONFIG, *PHIDSPICX_DEVICE_CONFIG; /*++ HIDSPICX_DEVICE_CONFIG_INIT Arguments: PHIDSPICX_DEVICE_CONFIG DeviceConfig Output parameter, pointing to a caller-provided HIDSPICX_DEVICE_CONFIG structure. This may be a stack allocated structure. Macro Description: Before passing a PHIDSPICX_DEVICE_CONFIG structure pointer to the HidSpiCxDeviceConfigure function, it must first be initialized by a call to this macro. --*/ VOID FORCEINLINE HIDSPICX_DEVICE_CONFIG_INIT ( _Out_ PHIDSPICX_DEVICE_CONFIG DeviceConfig, _In_ PFN_HIDSPICX_RESETDEVICE EvtResetDevice, _In_ PFN_HIDSPICX_NOTIFY_POWERDOWN EvtNotifyPowerDown, _In_ WDFQUEUE InputReportQueue, _In_ WDFQUEUE OutputReportQueue ) { RtlZeroMemory(DeviceConfig, sizeof(HIDSPICX_DEVICE_CONFIG)); DeviceConfig->Size = sizeof(HIDSPICX_DEVICE_CONFIG); DeviceConfig->EvtResetDevice = EvtResetDevice; DeviceConfig->EvtNotifyPowerDown = EvtNotifyPowerDown; DeviceConfig->InputReportQueue = InputReportQueue; DeviceConfig->OutputReportQueue = OutputReportQueue; } #include "HidSpiCxFuncEnum.h" // // HIDSPICX Function: HidSpiCxDeviceInitConfig // typedef _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) WDFAPI NTSTATUS (NTAPI *PFN_HIDSPICXDEVICEINITCONFIG)( _In_ PHIDSPICX_DRIVER_GLOBALS DriverGlobals, _In_ PWDFDEVICE_INIT DeviceInit ); //! //! HidSpiCxDeviceInitConfig //! //! Arguments: //! //! PWDFDEVICE_INIT DeviceInit //! WDF handle to the device init object this method is being called for. //! //! Return Value: //! //! NTSTATUS indicating whether HidSpiCx was able to successfully initialize //! the device init. //! //! Routine Description: //! //! The client driver must call this function in its EVT_WDF_DRIVER_DEVICE_ADD WDF callback, //! before calling WdfDeviceCreate. The class extension initializes private PNP //! and power hooks for the device. //! _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) FORCEINLINE NTSTATUS HidSpiCxDeviceInitConfig( _In_ PWDFDEVICE_INIT DeviceInit ) { return ((PFN_HIDSPICXDEVICEINITCONFIG) HidspicxFunctions[HidSpiCxDeviceInitConfigTableIndex])(HidspicxDriverGlobals, DeviceInit); } // // HIDSPICX Function: HidSpiCxDeviceConfigure // typedef _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) WDFAPI NTSTATUS (NTAPI *PFN_HIDSPICXDEVICECONFIGURE)( _In_ PHIDSPICX_DRIVER_GLOBALS DriverGlobals, _In_ WDFDEVICE Device, _In_ PHIDSPICX_DEVICE_CONFIG DeviceConfiguration ); //! //! HidSpiCxDeviceConfigure //! //! Arguments: //! //! WDFDEVICE Device //! WDF handle to the device object this method is being called for. //! //! PHIDSPICX_DEVICE_CONFIG DeviceConfiguration //! Pointer to a caller initialized HIDSPICX_DEVICE_CONFIG structure, //! specifying the details of the callbacks and queues to be used for //! communication between the class extension and client driver. //! //! Return Value: //! //! NTSTATUS indicating whether HidSpiCx was able to successfully configure //! the device. //! //! Routine Description: //! //! After calling WdfDeviceCreate (and still in its EVT_WDF_DRIVER_DEVICE_ADD callback), //! the client driver then calls this function with a pointer to a HIDSPICX_DEVICE_CONFIG //! structure, specifying interfaces the class extension will use to communicate with the //! device. The class extension will here initialize internal state, returning whether //! or not this is successful. //! //! The client driver may, if necessary, create a default queue before or after //! making this callback, in order to handle (non-HID) IOCTLs not handled //! by the class extension. //! //! The client driver is expected to provide a reset callback, which the class extension //! may call to initiate a synchronous reset of the device. A power down callback is //! also required. The client driver optionally specifies how many requests are to be pended //! in the Input Report Queue at a given time. If this is zero, the class extension //! will choose a default. //! //! The client driver is expected to create and provide pointers to two non-power-managed //! WDFQUEUEs: an Input Report Queue and an Output Report Queue. The client may choose //! how reports are dispatched from these queues (manual, sequential, parallel etc). //! HidSpiCx will not attempt to change the state of this queue at any time ? interaction //! with the provided queues will be limited to forwarding and potentially cancelling requests. //! //! Requests forwarded from the class extension to the provided queues have a //! variable-length buffer, containing a HIDSPICX_REPORT structure. //! //! HidSpiCx uses internal WDF functions to hook certain power transition callbacks //! for the device. This means no intervention is required from the client driver //! in order to notify the class extension of changes in the device state. //! //! Client drivers should not attempt to acquire power policy ownership and configure //! power policy settings because HidClass and HidSpiCx are responsible for //! managing the power policy of the device. //! _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) FORCEINLINE NTSTATUS HidSpiCxDeviceConfigure( _In_ WDFDEVICE Device, _In_ PHIDSPICX_DEVICE_CONFIG DeviceConfiguration ) { return ((PFN_HIDSPICXDEVICECONFIGURE) HidspicxFunctions[HidSpiCxDeviceConfigureTableIndex])(HidspicxDriverGlobals, Device, DeviceConfiguration); } // // HIDSPICX Function: HidSpiCxNotifyDeviceReset // typedef _IRQL_requires_max_(DISPATCH_LEVEL) WDFAPI VOID (NTAPI *PFN_HIDSPICXNOTIFYDEVICERESET)( _In_ PHIDSPICX_DRIVER_GLOBALS DriverGlobals, _In_ WDFDEVICE Device ); //! //! HidSpiCxNotifyDeviceReset //! //! Arguments: //! //! WDFDEVICE Device //! WDF handle to the device object this method is being called for. //! //! Routine Description: //! //! The client driver may call this function at any time when the device is in, or //! transitioning to D0, to inform the class extension of a requirement to reset //! the device (e.g. due to an invalid packet, bus error or other unexpected failure //! in either the controller or the device necessitating a reset). //! The class extension will then call the provided EvtResetDevice callback, either //! before this function returns, or at a later time when appropriate. The //! device will then be reinitialized by the class extension. //! _IRQL_requires_max_(DISPATCH_LEVEL) FORCEINLINE VOID HidSpiCxNotifyDeviceReset( _In_ WDFDEVICE Device ) { ((PFN_HIDSPICXNOTIFYDEVICERESET) HidspicxFunctions[HidSpiCxNotifyDeviceResetTableIndex])(HidspicxDriverGlobals, Device); } WDF_EXTERN_C_END #endif // _HIDSPICX_H_