SpbTestTool
The SpbTestTool sample serves two purposes. First, it demonstrates how to open a handle to the SPB controller, use the SPB interface from a KMDF driver, and employ GPIO passive-level interrupts. Second, it implements a set of commands for communicating with a peripheral device to aid in debugging.
This sample is incomplete as a driver and merely demonstrates use of the SPB I/O request interface and GPIO interrupts. It is not intended for use in a production environment.
Run the sample
To install the SpbTestTool peripheral driver, follow these steps:
Ensure that the driver builds without errors.
Copy the SYS and INF files to a separate folder.
Run Devcon.exe. You can find this program in the tools\devcon folder where you installed the WDK. Type the following command in the command window:
devcon.exe update SpbTestTool.inf ACPI\<hwid>
To launch the SpbTestTool application, follow these steps:
Navigate to the directory that contains SpbTestTool.exe.
Type the following command in the command window:
SpbTestTool.exe
By default, the SpbTestTool application uses the SpbTestTool sample driver. However, an alternate peripheral driver can be used instead. To specify an alternate driver, use the following format for the command line:
SpbTestTool.exe /p \\.\<alternate_path>
An input script can used instead of an interactive prompt. The script format requires one command per line. To run the script, use the following format for the command line in the command window:
SpbTestTool.exe /i <script.txt>
Executing commands
The SpbTestTool application loops indefinitely waiting for one of the following commands. The commands are translated to the appropriate SPB I/O request without any state tracking in the driver. Transfer status, buffer contents, and error codes are returned as necessary. Type help
at any time to display this command list. Press Ctrl-C at any time to cancel the current command and exit the application.
Command | Description |
---|---|
open | Open handle to SPB controller. |
close | Close handle to SPB controller. |
lock | Lock the bus for exclusive access. |
unlock | Unlock the bus. |
lockconn | Lock the shared connection for exclusive access. This command is used to synchronize bus transfers by the sample driver with op-region accesses by the ACPI firmware. |
unlockconn | Unlock the shared connection. |
write {} | Write a byte array to the peripheral device. Example: > write {01, 02, 03} |
read <numBytes> | Read <numBytes> from the peripheral device. Example: > read 5 |
writeread {} <numBytes> | Atomically write a byte array to the peripheral device and read <numBytes> back. Example: > writeread {01, 02, 03} 5 |
signal | Inform the SpbTestTool driver that the interrupt has been handled. |
help | Display the list of supported commands. |
Ctrl-C | Press Ctrl-C at any time to cancel the outstanding command and exit the application. |
Code tour
The following are the relevant functions in the SpbTestTool peripheral driver for using the SPB interface from a KMDF driver.
Function | Description |
---|---|
OnPrepareHardware | Traverses the driver's start resources and caches the connection ID of the I2C or SPI resource. This ID will be used to open the SPB controller later on. |
SpbPeripheralOpen | Opens a handle to the underlying SPB controller via the resource hub. This allows the peripheral driver to be developed without any underlying knowledge of the platform or hardware connections. Instead, the dependency between controller and peripheral is described in ACPI. |
SpbPeripheralClose | Sends IOCTL_SPB_LOCK_CONTROLLER to the SPB controller to lock the bus for exclusive access by this peripheral. |
SpbPeripheralLock | Sends IOCTL_SPB_LOCK_CONTROLLER to the SPB controller to lock the bus for exclusive access by this peripheral. |
SpbPeripheralUnlock | Sends IOCTL_SPB_UNLOCK_CONTROLLER to the SPB controller to unlock the bus from exclusive access by this peripheral. |
SpbPeripheralLockConnection | Sends IOCTL_SPB_LOCK_CONNECTION to the SPB controller to lock the shared connection for exclusive access by this target (file handle). |
SpbPeripheralUnlockConnection | Sends IOCTL_SPB_UNLOCK_CONNECTION to the SPB controller to unlock the shared connection from exclusive access by this target (file handle). |
SpbPeripheralRead | Sends a read request to the SPB controller. |
SpbPeripheralWrite | Sends a write request to the SPB controller. |
SpbPeripheralWriteRead | Builds a write-read sequence and sends IOCTL_SPB_EXECUTE_SEQUENCE to the SPB controller. |
SpbPeripheralOnComplete | Completion callback for all I/O requests. |
The following are the relevant functions in the SpbTestTool peripheral driver for managing GPIO passive-level interrupts from a KMDF driver.
Function | Description |
---|---|
OnPrepareHardware | Traverses the driver's start resources. If "ConnectInterrupt" is set to 1 in the registry, the driver connects the first interrupt resource found and registers an interrupt service routine. |
OnInterruptIsr | The interrupt service routine, which has been configured to run at passive-level. Doing so enables the driver to acknowledge or quiesce the interrupt using the SPB interface, which cannot be called at DIRQL. Typically a driver will clear the hardware interrupt and save any volatile information in its ISR, and then it will queue a workitem to continue processing. Our sample driver instead notifies the SpbTestTool app that an interrupt has occurred and calls KeWaitForSingleObject to wait until the interrupt is handled before returning. A "real" driver should never stall in the ISR like this. |
SpbPeripheralWaitOnInterrupt | Called to pend a WaitOnInterrupt request in the driver, which will be completed when the next interrupt occurs. |
SpbPeripheralInterruptNotify | Completes an outstanding WaitOnInterrupt request to inform the SpbTestTool app that an interrupt has occurred. |
SpbPeripheralSignalInterrupt | Notifies the interrupt service routine that the interrupt has been handled and the ISR should return. |
File manifest
The following source files are in the \SpbTestTool\sys folder and are used to build the SpbTestTool.sys and SpbTestTool.inf files.
File | Description |
---|---|
driver.h, driver.cpp | Events on the Device Object, and read, write, and IOCTLs from the SpbTestTool application. Implements the driver's interrupt service routine. |
internal.h | Common includes and typedefs |
makefile | Redirects to the real makefile that is shared by all components of the WDK. |
peripheral.h, peripheral.cpp | Reflection of the SpbTestTool IOCTLs to the SPB API, including opening the controller via the resource hub and using lock, unlock, read, write, and sequence. |
resource.rc | Resource descriptor file used for versioning |
sources | Lists source files and build options. |
sources.dep | Defines build dependencies. |
spbtesttool.asl | Sample ASL file for a peripheral device node. It declares I2C and GPIO interrupt resources. Note each macro specifies an ACPI path to describe direct dependencies. |
spbtesttool.h | Private SpbTestTool IOCTLs for use between the application and peripheral driver, and driver path names. |
spbtesttool.inx | Describes the installation of the driver. The build process converts this into an INF. |
trace.h | Sets up WPP tracing. |
The following source files are in the \SpbTestTool\exe folder and are used to build the SpbTestTool.exe file.
File | Description |
---|---|
command.h, command.cpp | Classes representing each of the SpbTestTool commands. For the list of commands, see Executing commands. |
internal.h | Common includes and function definitions |
main.cpp | Application entry point, input parsing, and main execution loop. Also contains the interrupt notification thread. |
makefile | Redirects to the real makefile that is shared by all components of the WDK. |
sources | Lists source files and build options. |
util.cpp | Helper functions |