The SpbTestTool sample serves two purposes. One, 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. Two, it allows for communication with a peripheral using SPB commands to aide in debugging.
This sample is incomplete as a driver and merely demonstrates use of the SPB API and GPIO interrupts. It is not intended for use in a production environment.
1. Navigate to src\SPB\SpbTestTool\sys and launch the vcxproj file
2. Modify SpbTestTool.inx
a. Replace ACPI\SpbTestTool with appropriate peripheral HWID
b. Set the “ConnectInterrupt registery” setting to 1 to connect the first interrupt resource found, otherwise leave at 0 to leave disconnected. See SpbTestTool_AddReg section.
3. Build the project in Visual Studio
a. Produces SpbTestTool.inf and SpbTestTool.sys
1. Navigate to src\SPB\SpbTestTool\exe and launch the vcxproj file
2. Build the project in Visual Studio
a. Produces SpbTestTool.exe
To install the SpbTestTool driver:
1. Ensure that the driver builds without errors
2. Copy the SYS and INF files to a separate folder
3. 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.
a. devcon.exe update SpbTestTool.inf ACPI\<hwid>
The following are relevant functions in the SpbTestTool peripheral 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 |
Closes the handle to the SPB controller. |
|
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. |
|
SpbPeripheralFullDuplex |
Builds a full duplex IO and sends IOCTL_SPB_FULL_DUPLEX to the SPB controller. |
|
SpbPeripheralOnComplete |
Completion callback for all IO. |
The following are relevant functions in the SpbTestTool peripheral 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. |
To launch the SpbTestTool application:
1. Navigate to the directory with SpbTestTool.exe
2. Type the following command in the command window:
a. SpbTestTool.exe
3. An alternate peripheral driver path can also be used. Note, this driver must implement the private SpbTestTool interface
a. SpbTestTool.exe /p \\.\<alternate_path>
4. An input script can used instead of an interactive prompt. The format is one command per line. See below for commands.
a. SpbTestTool.exe /i <script.txt>
The application will loop indefinitely waiting for one of the following commands. The commands are translated to the appropriate SPB API action without any state tracking in the driver. Transfer status, buffers, and error codes are returned as necessary. Type ‘help’ at any time to display this 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 primitive is used to synchronize with op-region accesses by firmware. |
|
unlockconn |
Unlock the shared connection |
|
write {} |
Write byte array to peripherl > write {01, 02, 03} |
|
read <numBytes> |
Read <numBytes> from peripheral > read 5 |
|
writeread {} <numBytes> |
Atomically write byte array to peripheral and read <numBytes> back > writeread {01, 02, 03} 5 |
|
fullduplex {} <numBytes> |
Simultaneously write byte array to peripheral and read <numBytes> back > full duplex {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. |
|
File |
Description |
|
driver.h, driver.cpp |
DriverEntry and Events on the Driver Object. |
|
device.h, device.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 |
|
makefile.inc |
Defines custom build actions. Includes the conversion of the .INX file into a .INF file |
|
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 a .INF |
|
trace.h |
Sets up WPP tracing |
|
File |
Description |
|
command.h, command.cpp |
Classes respresenting each of the SpbTestTool commands. See Executing commands above |
|
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 |
Copyright © Microsoft Corporation. All Rights Reserved.