Detailed description of USB host driver development under WinCE

Source: Internet
Author: User

 

All drivers in winceare loaded by the device.exe process in the form of dll. therefore, the dllentry function must be implemented in each driver.

The driver information of the USB host is saved under the HKEY_LOCAL_MACHINE \ drivers \ USB \ loadclients \ key in the registry. The first time we inserted a USB device. Because this information does not exist, a"
Unrecognized USB device "dialog box, ask the user to enter the name of the driver. The name is the file name of the USB host driver DLL. After a name is entered, the system automatically calls the usbinstalldriver function of the DLL. This function
Adds information about the USB host driver to the Registry to identify the USB device when the device is inserted again. The prototype is as follows:

Bool usbinstalldriver (lpcwstr szdriverlibfile );
Szdriverlibfile is the name of the input DLL file. If the return value is true, the registration is successful.
When registering USB host information with the Registry, you cannot use common registry functions. You can only use the registration functions provided by usbd.
Bool registerclientdriverid (lpcwstr szuniquedriverid );
Bool registerclientsettings (maid );
These two functions can be called dynamically or statically in usbd. dll.

The dynamic mode is as follows:
Hinstance hinst = loadlibrary (L "usbd. dll ");
If (hinst ){
Lpregister_client_driver_id lpregisterclientid =
(Lpregister_client_driver_id) getprocaddress (
Hinst,
L "registerclientdriverid ");
If (! Lpregisterclientid)
Return false;
Lpregister_client_settings lpregisterclientsetting =
(Lpregister_client_settings) getprocaddress (
Hinst,
L "registerclientsettings ");
If (! Lpregisterclientsetting)
Return false;
Else
Return false;
After that, you can use the lpregisterclientid and lpregisterclientsetting function pointers to call these functions. Remember to use freelibrary.

Static mode:
Add in the. cpp source file
# Pragma comment (Lib, "usbd. lib ")
Add $ (_ sysgenoakroot) \ Lib \ $ (_ cpuindpath) \ usbd. lib to the targetlibs variable of the source file.
In this way, you can directly use these two functions.
1) bool registerclientdriverid (lpcwstr szuniquedriverid)
This function registers the ID of the USB host driver.
2) bool registerclientsettings (maid, maid, maid)
This function registers driver information.
Set szdriverlibfile to the name of the DLL driver passed in by the usbinstalldriver function.
Szuniquedriverid is set to the driver ID registered by calling registerclientdriverid.
Erved is set to null.
Lpdriversettings this parameter is a usb_driver_settings struct. The statement is as follows:
Typedef struct {
DWORD dwcount;
DWORD dwvendorid;
DWORD dwproductid;
DWORD dwreleasenumber;
DWORD dwdeviceclass;
DWORD dwdevicesubclass;
DWORD dwdeviceprotocol;
DWORD dwinterfaceclass;
DWORD dwinterfacesubclass;
DWORD dwinterfaceprotocol;
} Usb_driver_settings;
Count is the structure size, and other items correspond to the USB descriptor.
The fields except count can be set to usb_no_info if no specific value is set.
The information in this struct reflects the HKEY_LOCAL_MACHINE \ drivers \ USB \ loadclients \ key in the registry, which is used to find the USB driver when the USB device is inserted. The following is an example:
Bool usbinstalldriver (lpcwstr szdriverlibfile)
{
Retailmsg (1, (text ("usbinstalldriver \ r \ n ")));
Retailmsg (1, (text ("usbinstalldriver: % s \ r \ n"), szdriverlibfile ));
Bool fret = false;
Usb_driver_settings driversettings;
Driversettings. dwcount = sizeof (driversettings );
Driversettings. dwvendorid = 0x10c4;
Driversettings. dwproductid = 0x0003;
Driversettings. dwreleasenumber = usb_no_info;

Driversettings. dwdeviceclass = usb_no_info;
Driversettings. dwdevicesubclass = usb_no_info;
Driversettings. dwdeviceprotocol = usb_no_info;

Driversettings. dwinterfaceclass = 0;
Driversettings. dwinterfacesubclass = 0;
Driversettings. dwinterfaceprotocol = 0;

Fret = registerclientdriverid (L "usbtest ");
If (fret ){
Fret = registerclientsettings (
Szdriverlibfile,
L "usbtest ",
Null,
& Driversettings );
If (! Fret)
Retailmsg (1, (text ("registerclientsettings error \ r \ n ")));
} Else
Retailmsg (1, (text ("registerclientdriverid error \ r \ n ")));
Return fret;
}

In wince, the configuration information is divided into three groups, each group has three values,
Group 1:
Dwvendorid, dwproductid, dwreleasenumber
Group 2:
Dwdeviceclass, dwdevicesubclass, and dwdeviceprotocol
Group 3:
Dwinterfaceclass, dwinterfacesubclass, dwinterfaceprotocol
If the registration is successful, "group 1 \ group 2 \ group 3 \ register ID \ DLL" will appear under the HKEY_LOCAL_MACHINE \ drivers \ USB \ loadclients \ key, the key value is the DLL driver name. Each group is composed of three values underlined. If a value is set to usb_no_info, the key name does not include this value. If every value in the entire group is set to usb_no_info, the key name is default.

In the above example, the following key name is generated in my system:
HKEY_LOCAL_MACHINE \ drivers \ USB \ loadclients \ 4292_3 \ Default \ 0_0_0 \ usbtest \ DLL = "myusbtest" (my driver is myusbtest. dll)
When a user inserts a USB device, it reads the descriptor of the USB device and searches for the driver name in the registry based on the value in the descriptor.

Now let's assume that wince only supports the USB keyboard, and we implement a USB mouse driver by ourselves. Without notice, our USB mouse driver cannot be called. The reason is the process of searching for the driver of a USB device. The Registry Information of the usbhid driver provided by wince is
HKEY_LOCAL_MACHINE \ drivers \ USB \ loadclients \ Default \ 3 \ hid_class \ DLL = "usbhid. dll"

The third group of information only uses dwinterfaceclass, while the USB keyboard and USB mouse are only different from dwinterfaceprotocol. So, 3 sums up all the hid, and when we insert the USB mouse into the system, it will call usbhid. DLL driver processing, but it only includes the keyboard driver, no mouse driver, so the mouse cannot be used. To make the custom USB mouse usable, set the value of the third group as follows:
HKEY_LOCAL_MACHINE \ drivers \ USB \ loadclients \ Default \ 3_1_1 \ hid_class \ DLL = "usbhid. dll"

In this way, after the mouse with the value of 3_1_2 is inserted, because the corresponding key value cannot be found, we will be prompted to enter the driver of the USB mouse

When you need to uninstall the driver of the USB host device, the USB uninstalldriver function is called.
Bool usbuninstalldriver ();
It is similar to usbinstalldriver, but it calls the following two functions:
Unregisterclientsettings
Bool unregisterclientsettings (maid, maid );
Bool unregisterclientdriverid (lpcwstr szuniquedriverid );
Szuniquedriverid is the ID used for registration. szreserved is retained, so it is set to null, and lpdriversettings is the driver setting information.

The routine is as follows:
Bool usbuninstalldriver ()
{
Retailmsg (1, (text ("usbuninstalldriver \ r \ n ")));
Bool fret = false;
Usb_driver_settings driversettings;
Driversettings. dwcount = sizeof (driversettings );
Driversettings. dwvendorid = 0x10c4;
Driversettings. dwproductid = 0x0003;
Driversettings. dwreleasenumber = usb_no_info;
 
Driversettings. dwdeviceclass = usb_no_info;
Driversettings. dwdevicesubclass = usb_no_info;
Driversettings. dwdeviceprotocol = usb_no_info;
 
Driversettings. dwinterfaceclass = 0;
Driversettings. dwinterfacesubclass = 0;
Driversettings. dwinterfaceprotocol = 0;
 
Fret = unregisterclientsettings (L "usbtest", null, & driversettings );
If (fret ){
Fret = unregisterclientdriverid (L "usbtest ");
If (! Fret)
Retailmsg (1, (text ("unregisterclientdriverid error \ r \ n ")));
} Else
Retailmsg (1, (text ("unregisterclientsettings error \ r \ n ")));
Return fret;
}
Driversettings must be consistent with driversettings of usbinstalldriver.
Back to the original process, the wince Registry already contains the driver information. The wince system automatically searches for the Registry. After finding the DLL corresponding to the device's key value, it will call the usbdeviceattach function of the DLL.
Bool USB deviceattach (
Usb_handle hdevice,
Lpcusb_funcs lpusbfuncs,
Lpcusb_interface lpinterface,
Lpcwstr szuniquedriverid,
Lpbool facceptcontrol,
DWORD dwunused)
Hdevice device handle, which must be used when operating a USB device
Lpusbfuncs points to a function pointer containing various USB operations
Lpinterface USB interface information. Note that if dwinterfaceclass, dwinterfacesubclass, and dwinterfaceprotocol are set to usb_no_info in driversettings, the pointer is null.

Szuniquedriverid: register the device ID
Facceptcontrol: The value is assigned true, indicating that the driver can operate the device. If the device cannot be operated, the unrecognized USB device dialog box appears again, asking the user to enter the driver name
Dwunused not used

In this function, we mainly perform some checks to determine whether the device can be driven, as well as registering the USB Event Notification callback function and activating the stream driver. The check section is not described in detail here.

First, we will introduce how to activate the stream driver.
The stream Driver provides an interface for applications to access devices. This interface can be used to access devices like files. USB devices can also use this interface to support applications. In the Registry
The HKEY_LOCAL_MACHINE \ drivers \ builtin key stores the entries for various built-in stream drivers of wince. These drivers are activated when the system starts using device.exe. A device like USB has a stream only when it is inserted.
Driver Interface, so we need to manually activate the stream driver. The function used to activate the stream driver is:

Handle activatedevice (lpcwstr lpszdevkey, DWORD dwclientinfo );
The lpszdevkey string specifies the key of the registry where the stream driver is located. Anyone who knows about the stream driver knows that the stream driver must contain two keys, prefix and DLL, in the registry.

All interface functions in the stream driver have a prefix similar to XXX _, And This prefix specifies the string corresponding to XXX, for example, the prefix is com, the stream driver contains interface functions such as com_open, com_close, com_write, and com_read. DLL illustrates the dynamic link library where these functions are located.

In my example, the following registry key exists:
[HKEY_LOCAL_MACHINE \ drivers \ USB \ clientdrivers \ usbtest]
"Prefix" = "TST"
"DLL" = "myusbtest. dll"
Using dwclientinfo, You can indirectly transmit the parameter to the driver's xxx_init. We can place information such as hdevice, lpusbfuncs, and lpinterface in a struct and pass the function to the stream driver for use.
The USB notification callback function can be used to determine the occurrence of various USB events, such as USB pulling. When an event occurs, the system will handle the event based on the registered callback function. After the USB device is pulled out, all you need to do is to uninstall the stream driver and release the various resources occupied.

The registration callback function is a function pointer contained in lpusbfuncs:
Lpun_register_notification_routine lpunregisternotifroutine

The declaration of this function is as follows:
Typedef bool (* lpregister_notification_routine )(
Usb_handle hdevice,
Lpdevice_policy_routine lppolicyroutine,
Lpvoid lpvpolicyparameter
);
Hdevice device handle
Lpnotifyroutine callback function
Parameters passed to the callback function by lpvnotifyparameter
Uninstall the stream driver in the callback function
Bool deactivatedevice (handle hdevice );
The handle returned when hdevice passes in activatedevice.
The following is an example:
Typedef struct {
DWORD dwsize;
Usb_handle hdevice,
Lpcusb_funcs lpusbfuncs,
Lpcusb_interface lpinterface,
Handle hstreamdevice;
} Testusbinfo, ptestusbinfo;
// Callback function
Extern "C" bool usbdevicenotifications (
Lpvoid lpvpolicyparameter,
DWORD dwcode,
Lpdword * dwinfo1,
Lpdword * dwinfo2,
Lpdword * dwinfo3,
Lpdword * dwinfo4)
{
If (dwcode = usb_close_device ){
Ptestusbinfo pdrv = (pdrvcontext) lpvpolicyparameter;
Deactivatedevice (pdrv-> hstreamdevice); // uninstall the stream driver
Localfree (pdrv); // release resources
}
Retailmsg (1, (text ("Free driver resources! \ R \ n ")));
Return true;
}
Bool USB deviceattach (
Usb_handle hdevice,
Lpcusb_funcs lpusbfuncs,
Lpcusb_interface lpinterface,
Lpcwstr szuniquedriverid,
Lpbool facceptcontrol,
DWORD dwunused)
{
Retailmsg (1, (text ("usbdeviceattach \ r \ n ")));
* Facceptcontrol = false;
// Display some information about the USB device
If (lpinterface! = NULL ){
Retailmsg (1, (text ("usbserialhost: deviceattach, if % u, # EP: % u, class: % u, Sub: % u, Prot: % u \ r \ n "),
Lpinterface-> descriptor. binterfacenumber,
Lpinterface-> descriptor. bnumendpoints,
Lpinterface-> descriptor. binterfaceclass,
Lpinterface-> descriptor. binterfacesubclass,
Lpinterface-> descriptor. binterfaceprotocol ));
Retailmsg (1, (text ("endpoint 1: % u \ r \ n "),
Lpinterface-> lpendpoints [0]. descriptor. bmattributes ));
Retailmsg (1, (text ("endpoint 2: % u \ r \ n "),
Lpinterface-> lpendpoints [1]. descriptor. bmattributes ));
Retailmsg (1, (text ("endpoint 3: % u \ r \ n "),
Lpinterface-> lpendpoints [2]. descriptor. bmattributes ));
}
Lpcusb_device lpusbdev = (lpusbfuncs-> lpgetdeviceinfo) (hdevice );
If (! Lpusbdev)
{
Retailmsg (1, (text ("unable to get USB device! \ R \ n ")));
Return false;
}
// Save necessary information for other parts of the driver
Ptestusbinfo pdrv = (ptestusbinfo) localalloc (lptr, sizeof (ptestusbinfo ));
Pdrv-> dwsize = sizeof (drvcontext );
Pdrv-> hdevice = hdevice;
Pdrv-> lpusbfuncs = lpusbfuncs;
Pdrv-> lpinterface = lpinterface;
// Activate the streaming driver
Pdrv-> hstreamdevice = activatedevice (L "Drivers \ USB \ clientdrivers \ usbtest", (DWORD) pdrv );
If (pdrv-> hstreamdevice ){
// Register the callback function
(* Lpusbfuncs-> lpregisternotifroutine )(
Hdevice,
Usbdevicenotifications,
Pdrv );
} Else {
Retailmsg (1, (text ("can't activate stream device! Rc = % d \ r \ n "), getlasterror ()));
Localfree (pdrv );
Return false;
}
// The driver can operate the device.
* Facceptcontrol = true;
Return true;
}

At this point, all the functions required by the driver of the USB host device have been implemented. And connected to the stream driver. The application can use the stream-driven interface to operate the USB device.

 

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.