USB device Driver Development remote Access USB device (two USB device virtual side)

Source: Internet
Author: User

by Fanxiushu 2016-05-22 Reprint or quote please indicate the original author
Then,
After dealing with the problem of USB data acquisition, the next step is to enter the core part, the development work of virtual USB device side.
As explained earlier, virtual bus drivers need to be developed to emulate USB devices.
The so-called virtual bus driver, which is a driver installed under the system device, creates a virtual bus PDO device by the PNP Manager,
Our virtual bus driver attach to this PDO, forming a FDO function device driver,
Then in our drive, we create several child PDO devices as needed,
These child PDO devices are virtual devices that we simulate as needed.
Our bus driver whenever a child PDO is created and initialized,
Call the IoInvalidateDeviceRelations function to notify the PNP manager that our child PDO has changed.
The PNP manager then sends the Irp_mn_query_device_relations Plug and Play message to our driver,
When we tell the PNP manager about all the new child PDO listings, it then compares the new and old PDO lists that he maintains internally,
Know which PDO is newly added and which have been removed.
For newly added devices, the PNP Manager sends the query Device ID message irp_mn_query_id to the child PDO that we created, querying the various IDs of the devices,
The PNP manager then looks from the registry based on the device ID to see if a feature driver has been installed for this child PDO.
If it is already installed, it is loaded and is not installed prompting the user to install a new driver.

This is the approximate framework of the virtual bus driver, which is not complicated in principle, and has the example code provided by Microsoft,
You can read its example code to further deepen your understanding of the bus-driven principle, or you can view the source code I provide on CSDN to deepen understanding.

Our bus driver simulates the USB device interface, so the child PDO must have the features of the USB interface,
The core part of the USB interface to deal with, in fact, the above simple introduction of the USB interface of four kinds of data transmission methods:
One, control transmission, two interrupt transmission, three-batch transmission, four, synchronous transmission.
Interrupt, batch, synchronous transmission are better processing, and control transmission involves a lot of commands, so you need to handle a variety of commands.
The Windows platform uses the USB interface device for data communication using URB packets, each of which specifies a function number,
That is, the URB function type. The type of function is about 20, in fact, it is still derived from the four ways of communication of USB interface,
For example, Urb_function_bulk_or_interrupt_transfer this URB function is the combination of interrupt transfer and bulk transfer.
Urb_function_isoch_transfer is synchronous transmission,
And more than 20 urb_function_xxx can be fully understood as a control transmission of a command.
For example, Urb_function_get_descriptor_from_device is the control transmission, the device descriptor is obtained from the USB device.

Let's start by enumerating the urb_function_xxx commands that we need to handle in our drive:

(The following are interrupts, bulk, synchronous transfer commands)

Urb_function_bulk_or_interrupt_transfer (interrupt or Bulk transfer)
Urb_function_isoch_transfer (synchronous transmission)

(The following are all control transfer commands)

Universal Control Transfer command, which can be used when a USB device transmits a command that is not in the urb_function defined by Microsoft
Urb_function_control_transfer

Get device, interface, endpoint descriptor
Urb_function_get_descriptor_from_device
Urb_function_get_descriptor_from_interface
Urb_function_get_descriptor_from_endpoint

Select configuration descriptor, interface optional descriptor
Urb_function_select_configuration
Urb_function_select_interface

Get the class or vendor information for a USB device
Urb_function_class_device
Urb_function_class_interface
Urb_function_class_endpoint
Urb_function_class_other
Urb_function_vendor_device
Urb_function_vendor_interface
Urb_function_vendor_endpoint
Urb_function_vendor_other

Reset or interrupt transmission at an endpoint
Urb_function_reset_pipe
Urb_function_abort_pipe

Get device, interface, endpoint status
Urb_function_get_status_from_device
Urb_function_get_status_from_interface
Urb_function_get_status_from_endpoint
Urb_function_get_status_from_other

Gets the current configuration, current interface, current Framenumbber. The current framehnumber is used for synchronous transmission
Urb_function_get_configuration
Urb_function_get_interface
Urb_function_get_current_frame_number

The following is the setup or removal of the feature, mainly for the hub, and of course some USB devices may be useful to
Urb_function_set_feature_to_device
Urb_function_set_feature_to_interface
Urb_function_set_feature_to_endpoint
Urb_function_set_feature_to_other
Urb_function_clear_feature_to_device
Urb_function_clear_feature_to_interface
Urb_function_clear_feature_to_endpoint
Urb_function_clear_feature_to_other

Why Windows has so many function commands is estimated to be convenient for understanding and handling USB control commands.
However, before the host controller enters the real USB device, the host controller still has to convert it to a 8-byte setuppacket control command.
This is a hardware requirement, and we are a virtual device, so there is no need to turn into setuppacket format, as long as the network communication is suitable for us.
Our USB data acquisition terminal and virtual USB port, all belong to the Windows platform, turn into setuppacket and then turn into function, instead of trouble,
So the basic is to do some simple conversion according to Urb_function, so convenient and fast.
However, if your acquisition and USB virtual end belong to different platforms, such as Linux,windows,macos, and other platforms, it is necessary to use a unified communication method.
The format estimation specified in the USB communication protocol is a better choice.

Knowing which urb_function commands need to be dealt with, maybe everyone still doesn't understand how to handle these urb, how to fully simulate a USB interface,
In order to realize the remote data acquisition end of the USB device to the virtual side.
Suppose you are already familiar with the virtual bus-driven framework.
The virtual bus driver should have a communication interface with the application layer program, and the application uses the IOCTL to drive the communication.
The application layer program connects to the USB data acquisition terminal through the network, obtains the hardware ID of a USB device that needs to be accessed remotely, the compatible ID and so on preliminary information,
Via the CREATEPDO ioctl to the virtual bus driver, the virtual bus driver creates a child PDO device based on various parameters such as hardware ID,
After a successful creation, call IoInvalidateDeviceRelations to notify the PNP manager, and the next step is what the PnP manager should do.
This feature driver starts working when the PNP manager correctly loads the function driven by the hardware ID. This feature driver starts to construct the URB package,
and send the URB packet to the child PDO device that we created in the virtual bus driver,
Next, our bus driver must pass these URB data correctly to the remote USB data acquisition terminal and get the correct response.
As for how to deal with this major and core process, each engineer may have a different approach, we are using the URB data to pass to the application layer,
Then, the application layer is passed to the data acquisition terminal via socket socket, then the response packet of the acquisition end is passed to the driver,
Finally, our virtual bus driver completes this URB packet that is sent down from the function driver.

We create a semaphore in the application layer, which is passed to the driver, and the bus driver uses this semaphore to notify the application layer that a new URB packet arrives.
For example, the upper function driver has a Urb_function_get_descriptor_from_device URB packet delivered to our bus driver,
The bus driver then mounts the URB packet to the waiting queue of child PDO, then increases the semaphore and notifies the application layer that the URB packet arrives.

The application layer program has one or more threads called The WaitForSingleObject function waits for the semaphore,
when WaitForSingleObject successful return , indicating that there is a URB packet, so through the DeviceIoControl function, the delivery of a BEGIN ioctl to the bus driver,
Our bus driver takes out a URB packet from the wait queue of child PDO, analyzes and processes the URB packet,
Then attach this URB to the busy queue of child PDO and generate a seqno uniquely identify this URB package to complete this begin IOCTL.
The application layer program is sent to the remote USB data acquisition terminal to wait for the response from the request data obtained from the BEGIN ioctl.
after the USB data acquisition terminal responds to this packet, the application layer program calls an end IOCTL To the bus driver,
Our virtual bus driver finds the corresponding URB packet from the busy queue of child PDO based on Seqno, and the data passed from the END ioctl is correctly filled into the URB packet.
Finally complete this URB package.

This is my bus driver for the URB packet processing engineering, this previous article introduced the
The processing framework for the file filtering driver for directory redirection (http://blog.csdn.net/fanxiushu/article/details/43845699) is consistent.
If you are unfamiliar with this process, you can look at the section on filtering drivers for directory redirection.

The urb_function_xxx described above is very much, in order to simplify the packet at the BEGIN IOCTL and end IOCTL,
Unify the use of a data structure and drive interaction。
As follows
struct ioctl_usbtx_header_t
{
ULONGLONG Inter_handle; Is the file that waits to be processed IRP pointer
LONG inter_seqno; The serial number of each IRP, generated by the driver, is used together with the inter_handle to ensure the uniqueness of the request packet validation
LONG data_length; The length of the data; If it is a read device, the number of bytes read, if it is write data to the device, before writing is the number of bytes to write, after the successful write, the actual number of bytes written, ISO transmission will include the iso_packet_hdr_t structure size
LONG result; Returns whether successful
LONG reserved1; Keep
////


int type; 1 Get descriptor, 2 vendor or class, 3 transfer data, 4 Reset, 5 get status, 6 operation feature
int reserved[3]; Keep
/////
union{
///
struct{
int type; 1 Gets or sets the device descriptor, 2 sets the configuration descriptor, 3 Gets or sets the interface descriptor, 4 Gets or sets the port descriptor
int subtype; (type=1,3,4) 1 Gets the device descriptor, 2 Gets the configuration descriptor, 3 gets the string;;;;; (type=2) 1 set config (index=-1 & value=-1 unconfigure), 2 settings interface
int is_read; (type=1,3,4) Is_read to True get descriptor, FALSE set descriptor
int index; Serial number
int value; Value that is defined as language_id when getting a string

}descriptor;
////////
struct{
int type; 1 class request, 2 vendor request
int subtype; 1 device; 2 interface; 3 endpoint; 4 other
int is_read; Whether to read from the device or write to the device
int request;
int index;
int value;
}vendor;
////
struct {
int type; 1 control transmission, 2 interrupt or bulk transfer, 3 synchronous transmission
int ep_address;  Port position if (ep_address &0x80) is read, otherwise written; When controlling transmission, if 0 means using the default port
int is_read; Whether to read from the device or write to the device
union{
int number_packets; Synchronous transmission, the number of packets, if 0, the combination of transmission, >0 is behind the head with the iso_packet_hdr_t structure, the size of Iso_packet_hdr_size + number_packets*sizeof (iso_ packet_t)
struct{
unsigned char setup_packet[8]; Control transmission, 8 bytes of control code sent
};
};
Char Is_split; Interrupt the bulk transfer, or whether the synchronous transfer is split into multiple blocks,
Char reserved[3]; ///
}transfer;
////////
struct {
int type; 1 Ioctl_internal_usb_reset_port Reset device, 2 ioctl_internal_usb_cycle_port reset device, 3 reset port urb_function_reset_pipe; 4 Interrupt Port Urb_function_abort_pipe
int ep_address;
}reset;
/////
struct {
int type; 1 device; 2 interface; 3 endpoint; 4 other status; 5 Gets the current configuration descriptor; 6 obtains the alterantesetting of the current interface according to interface; 7 Get Current frame number
int index; ///
}status;
//////
struct {
int type; 1 set request, 2 clear request
int subtype; 1 device; 2 interface; 3 endpoint; 4 other
int index; ///
int value; ///
}feature;
////////
};
////////////

};

It seems a bit more, actually the BEGIN IOCTL and end IOCTL are used ioctl_usbtx_header_t to pass a variety of URB data, instead of a lot of convenience,
to the data acquisition side, The same structure is used for processing, because it is the Windows platform, and the various transformations that are handled are much less. For the definition or use of the

data structure, download the project provided on CSDN.

So far, a virtual bus-driven remote access to the USB device function, the basic calculation is complete,
but there is a less perfect place, such a virtual USB device like a non-master ghosts exist in the system, it does not attach to a virtual with a hub, The
also does not have a corresponding virtual USB controller, so it is considered to be non-existent in some application-level programs.
For example, some of the USB devices are enumerated on the USB device stack, so that the virtual USB device is not enumerated, because he is not roothub, and there is no USB controller. The concept of
is similar to the virtual disk drive described previously, using the virtual disk drive of Microsoft's Scsiport or Storeport model, will be treated as a real disk,
can find our virtual disk in Disk Manager, and can be partitioned as a real disk, formatted and other basic disk operations.
While a virtual disk drive, similar to the Filedisk framework, is available on-line, it also provides disk access, but does not have disk-driven functionality provided by frameworks such as Storeport, and
is not considered a disk system by the system.
  the virtual USB device we are implementing now is the same as Filedisk, and will not be considered a real USB device by the system.
But it can still cheat most of the software, just like Filedisk.

How to get to our virtual USB perfect? Virtual Roothub and virtual USB controllers need to be implemented.

Please pay attention to the development process of Roothub and USB controller below.



USB device Driver Development remote Access USB device (two USB device virtual side)

Related Article

Cloud Intelligence Leading the Digital Future

Alibaba Cloud ACtivate Online Conference, Nov. 20th & 21st, 2019 (UTC+08)

Register Now >

Starter Package

SSD Cloud server and data transfer for only $2.50 a month

Get Started >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.