How to Use DriverStudio to construct a simple USB Filter Driver

Source: Internet
Author: User
Tags passthrough lenovo

Author: unintentional language source: driverdevelo

How to construct a simple USB Filter Driver

This article describes how to construct a simple USB filter driver, including "Basic Principles", "Program Implementation", and "install with INF ". The purpose of this article is to hope that you can use the most popular and convenient driver development tool DriverStudio besides DDK to implement your own filter driver and install it correctly.

I. Basic Principles
We know that WDM (and KDM) is layered. When constructing a device stack, the IO manager can append a device object to a device object created by another initial driver. The IRP determined by the driver associated with the initial device object will also be sent to the driver associated with the attached device object. The appended driver is the filter driver. As shown in the right figure, the filter driver can be inserted at any layer of the device stack. The IRP sent by the IO manager is passed from top to bottom and returned in the order of the right graph. Therefore, we can use the filter driver to check, modify, and complete the received IRP, or construct our own IRP.
The above text is boring. Fortunately, "Predecessors" have already written some examples for us to better understand these concepts. Readers who have read waltz oney's programming windows driver mode know that the examples provided by waltz oney include an example of USB filter (Chapter 9, john Hyde, author of USB design by example, implements a USB keyboard filter driver that adds intercept) "function to process the Report of the USB keyboard to implement specific functions: When the completion routine set by the driver in irp_mj_internal_device_control intercepts a get_report_descriptor from the USB device, the interceptor changes the usage value in the descriptor from "keyboard" to "userdefined" and then returns it to the system.
We can get some inspiration from this example. For example, in Win2k, the keyboard is exclusively accessed by the OS. In this way, we can allow users to access it freely; we can also intercept other report_descriptor and redefine some keys to meet special requirements. If you are willing to create another user-State program, you can also pass the intercepted key values to your user-state programs to implement various practical functions on the keyboards produced by domestic computer manufacturers such as Lenovo and Shida.

Ii. Program Implementation
The examples of Waltz oney and John Hyde have been very detailed. Readers can compile a filter driver without having to modify a byte. The purpose of this article is to use the DriverStudio component driverworks to implement the same function.
I believe that when reading this article, the reader has a lot of knowledge about DriverStudio. As a "fast" driver development tool based on C ++, DriverStudio encapsulates basically all DDK functions, which are integrated into driverwizard in VC ++, it can easily guide you through the entire process of device driver development, automatically generate device driver source code based on your hardware type, and provide many sample programs. Of course, these examples contain a USB filter driver framework. Without copyright infringement, it is our consistent practice to make full use of the existing shared, free, and authorized code. The following example is used for modification.
Our goal is to build a hid mini driver hidusb. sys's lower filter, which is attached to the "man-machine interface device". It blocks the get_report_descriptor of USB to modify its return value. When it finds that the usage of the descriptor is "keyboard, change it to "userdefined" so that we can have full control over this keyboard. The specific method is to intercept irp_mj_internal_device_control and check its IOCTL code and urb. If the ioctrl function code is enabled and the urb function code is enabled, that is, when the upper-layer driver sends a get_report_descriptor request, set the value of the temporary shirts to remove the temporary sage from the school wall. Change the usage from "6 (keyboard)" to "0 (userdefined) ".
Open the C:/program files/numbench/DriverStudio/driverworks/examples/WDM/usbfilt directory (the directory varies depending on the directory where your DriverStudio is installed), and then open the project file usbfilt. DSW. Let's take a look at the code first.
A program consists of two classes: Driver Class and device class. Driver classes include:
Entry function DriverEntry:
Declare_driver_class (usbfilterdriver, null)
//////////////////////////////////////// /////////////////////////////
// Driver entry
//
Ntstatus usbfilterdriver: DriverEntry (punicode_string registrypath)
{
T <"usbfilterdriver: DriverEntry/N ";

M_unit = 0;
Return STATUS_SUCCESS;

// The foll wing macro simply allows compilation at warning level 4
// If you reference this parameter in the function simply remove the macro.
Unreferenced_parameter (registrypath );
}
Adddevice Function
Ntstatus usbfilterdriver: A ddevice (pdevice_object PDO)
{
T <"usbfilterdriver: adddevice/N ";
Usbfilterdevice * pfilterdevice = new (
Static_cast <pcwstr> (null ),
File_device_unknown,
Static_cast <pcwstr> (null ),
0,
Do_direct_io
)
Usbfilterdevice (PDO, m_unit );
If (pfilterdevice)
{
Ntstatus status = pfilterdevice-> constructorstatus ();
If (! Nt_success (Status ))
{
T <"failed to construct usbfilterdevice"
<(Ulong) m_unit
<"Status ="
<Status
<"/N ";

Delete pfilterdevice;
}
Else
{
M_unit ++;
}
Return status;
}
Else
{
T <"failed to allocate usbfilterdevice"
<(Ulong) m_unit
<"/N ";
Return status_insufficient_resources;
}
}

These two pieces of code are basically the same as the automatically generated code. Adddevice is used to construct an instance of a filter.
The key code is in the device class. In this class, we insert the filter into the device stack, intercept the IRP, and use our own routines to implement specific functions.
Device Constructor
Usbfilterdevice: usbfilterdevice (pdevice_object PDO, ulong unit ):
Kwdmfilterdevice (PDO, null)
{
T <"usbfilterdevice: usbfilterdevice/N ";
// Check constructor status
If (! Nt_success (m_constructorstatus ))
{
Return;
}
// Remember our unit number
M_unit = unit;
// Initialize the USB lower Dev CE
M_usb.initialize (this, PDO );
Ntstatus status = attachfilter (& m_usb); // attach the filter
If (! Nt_success (Status ))
{
M_constructorstatus = status;
Return;
}
Setfilterpowerpolicy ();
Setfilterpnppolicy ();
}
In DDK, we use ioattachdevice to insert the device object into the device stack. DriverStudio encapsulates this function. In DriverStudio, other drivers need to use initialize to initialize Device objects and interfaces. For filter drivers, the key is to attachfilter to attach them to the stack.
For most irp_mj_system_control IRPs, we only need to use passthrough (IRP) to directly transmit them to the lower layer of the device stack without any work. We will not list these codes one by one. The following part is the key of this article.
We know that hidusb. sys uses internal ioctrl to send urb to USB Drivers (usbd) to read data. Therefore, hidusb must first construct an irp_mj_internal_device_control, its ioctl function code is ioctl_internal_usb_submit_urb (internal IOCTL of urb ). In addition, because we want to check and modify the report description of an interface on the USB keyboard, the urb should be urb_function_get_descriptor_from_interface, as shown below:
Ntstatus usbfilterdevice: internaldevicecontrol (kirp I)
{
T <"usbfilterdevice: internaldevicecontrol/N ";
// Pass through IOCTLs that are not submitting an urb
// Ignore the ioctl that we are not interested in
If (I. ioctlcode ()! = Ioctl_internal_usb_submit_urb)
Return defaultpnp (I );

Purb P = I. urb (current); // get urb pointer from IRP

// Not the urb we are interested in. Ignore it,
If (p-> urbheader. function! =
Urb_function_get_descriptor_from_interface)
Return defaultpnp (I );
// Set the completion routine for the compliant IRP.
Return passthrough (I, linkto (devicecontrolcomplete), this );
}
After the conditions are set, complete the routine. All checks, modifications, and other actions are completed in the completion routine.
Ntstatus usbfilterdevice: devicecontrolcomplete (kirp I)
{
Purb P = I. urb (current );
If (P)
{
// The description table returned by the intercepted device,
Char * descriptorbuffer = (char *) P-> urbcontroldescriptorrequest. transferbuffer;
// Point to the third byte, indicating the value of the device's usage attribute
Descriptorbuffer + = 3;
// If the value is 6, it is changed to 0, 6, indicating the hid keyboard and 0 indicating the unknown device.
// In the Device Manager, the original hid-compatible keyboard no longer exists ?, Replaced by a hid-compatible device.
If (* descriptorbuffer & 0xff) = 6)
* Descriptorbuffer = 0;
}
Return I. Status ();
}
Readers can directly replace (or modify) the above two functions with the example in driverworks, and then compile one ?, You can get a complete keyboard filter driver.
In fact, as long as we figure out what actions we need to do, we only need to write a small amount of key code in DriverStudio to implement our requirements, most of the rest of the work, examples are available for reference, or driver wizard is automatically generated.
As we can see from the above, we only need to modify these two functions to intercept the appropriate IRP, and then we can implement our specific requirements in the completion routine. As mentioned at the beginning, we can also intercept other IRPs, intercept other URBS, or intercept the key values of a specific keyboard to pass them to the user State, to facilitate Lenovo, Shida, and other random multi-function keyboard functions.

3. Use inf to install the driver
After the driver is completed, you must install it into the system to make the driver take effect. In general, we must provide an INF file for our drivers for user installation or maintenance. For beginners, the INF filter driver may be tricky. Therefore, for the driver described in this article, we provide an installation example USB key. inf under Win98. The text after ";" in the example is an annotation to facilitate readers to understand.

 

; USBkey. inf
;
; Installlower level filter for a hid keyboard Device
;
; (C) Copyright 2001 Sino Co., Ltd.
;
[Version]
; "Chicago" indicates the Win9x Platform
Signature = "$ Chicago $"
; Category name of the keyboard
Class = hid
Classguid = {745a17a0-74d3-11d0-b6fe-00a0c90f57da}
Driver provider, which is displayed on the "General" page of device Properties
Provider = % usbdbe %
Layoutfile = layout. inf
; Displayed in the driver file details window
Driverver = 11/12/2001, 4.10.2222.12

; [Controlflags]
; Excludefromselect = *

; Driver Installation Directory, INF will install our driver to the following directory
; Remember that destinationdir must be followed by an "S"
[Destinationdirs]
Defaultdestdir = 10, system32/Drivers

; The registry key to be added
[Classinstall]
Addreg = hidclassreg

[Hidclassreg]
Hkr, % hid. classname %
Hkr, icon,-20

Manufacturer
[Manufacturer]
% Usbdbe % = usbdbe

[Usbdbe]
; We need to append the device ID of the filter driver. This ID can be obtained from the IC specification or
;Use hidview.exe to read the data, or find the data from the HKLM/Enum/hid and USB entries in the registry.
% Hid. devicedesc % = keypad_inst, USB/vid_05af & pid_0805 & mi_00

; The file to be installed and the registry key to be modified
; Install USB key driver
[Keypad_inst]
Copyfiles = keypad_inst.copyfiles
Addreg = keypad_inst.addreg

[Keypad_inst.copyfiles]
Hidusb. sys
Hidparse. sys
Hidclass. sys
Usbfilt. sys

[Keypad_inst.addreg]
Hkr, devloader, * ntkern
Hkr, ntmpdriver, "hidusb. sys"

[Keypad_inst.hw]
Addreg = keypad_inst.addreg.hw

Lowerfilters indicates that it is a low-layer filter driver. If it is an upper-layer filter driver, it must be changed to upperfilters.
[Keypad_inst.addreg.hw]
Hkr, "lowerfilters", 0x00010000, "usbfilt. sys"

The file to be installed on the HID device and the location to be modified in the registry.
; Install usbhiddevice
[Usbhiddevice]
Copyfiles = usbhiddevice. Copy
Addreg = usbhiddevice. addreg

[Usbhiddevice. Copy]
Hidclass. sys
Hidusb. sys
Hidparse. sys

[Usbhiddevice. addreg]
Hkr, devloader, * ntkern
Hkr, ntmpdriver, "hidusb. sys"

; The following defines the string to be replaced in some of the above
[Strings]
Usbdbe = "Sino Co., Ltd ."
Hid. devicedesc = "Sino USB multikeyboard"
Hid. hiddevicedesc = "Human Interface Devices"
Hid. defaultdevice = "hid default device"
Hid. classname = "human input devices (HID )"
Hid. svcdesc = "Microsoft hid class driver"

In fact, the simplest way to write INF is to find some INF files or examples of similar devices to modify. Without infringement, it is our principle to make full use of existing resources.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.