Development example of USB driver for Windows CE

Source: Internet
Author: User

 

The following is a simple example to describe the development process of the driver.

For example, we have a USB mouse device. The device information is described as follows:

Device descriptor:

Bcdusb: 0x0100

Bdeviceclass: 0x00

Bdevicesubclass: 0x00

Bdeviceprotocol: 0x00

Bmaxpacketsize0: 0x08 (8)

Idvendor: 0x05e3 (Genesys Logic Inc .)

Idproduct: 0x0001

Bcddevice: 0x0101

Imanufacturer: 0x00

Iproduct: 0x01

Iserialnumber: 0x00

Bnumconfigurations: 0x01

 

Connectionstatus: deviceconnected

Current Config value: 0x01

Device bus speed: low

Device address: 0x02

Open Pipes: 1

 

Endpoint descriptor:

Bendpointaddress: 0x81

Transfer Type: interrupt

Wmaxpacketsize: 0x0003 (3)

Binterval: 0x0a

It can be seen that the above device has an interrupted pipe, and the maximum value of the package is 3. Someone may ask how to obtain the above value. The ddkfor Win2k has a USB viewer example. Compile the program and insert your USB device to the USB port of the PC. Run usbview.exe to view the corresponding device information.

 

With this basic information, you can write a USB device. First, declare that the following code is taken from Microsoft's USB mouse sample program, and the copyright belongs to Microsoft, here we only use it to describe the development process of the USB mouse driver. If you need to reference this code, you need to get Microsoft's consent.

 

First, you must output the three functions required to be called by usbd. First, when the device is inserted to the USB port, usbd will call the USB deviceattach () function. The corresponding code is as follows:

Extern "C" bool

Usbdeviceattach (

Usb_handle hdevice, // USB device handle

Lpcusb_funcs lpusbfuncs, // function set of usbdi

Lpcusb_interface lpinterface, // Device Interface Description

Lpcwstr szuniquedriverid, // device ID description string.

Lpbool facceptcontrol, // returns true, which indicates that the device can be controlled. Otherwise, the device cannot be controlled.

DWORD dwunused)

{

* Facceptcontrol = false;

// Our mouse device has a specific description to check whether it is our device.

If (lpinterface = NULL)

Return false;

// Print the description of the USB device interface.

Debugmsg (zone_init, (text ("usbmouse: 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 ));

// USB mouse class for initial data, which generates a thread for receiving USB mouse data

Cmouse * pmouse = new cmouse (hdevice, lpusbfuncs, lpinterface );

If (pmouse = NULL)

Return false;

 

If (! Pmouse-> initialize ())

{

Delete pmouse;

Return false;

}

 

// Register a callback function for monitoring USB device events to monitor whether the USB device has been unplugged.

(* Lpusbfuncs-> lpregisternotificationroutine) (hdevice,

Usbdevicenotifications, pmouse );

 

* Facceptcontrol = true;

Return true;

}

 

The second function is the usbinstalldriver () function,

Some basic definitions are as follows:

Const wchar gcszregisterclientdriverid [] = l "registerclientdriverid ";

Const wchar gcszregisterclientsettings [] = l "registerclientsettings ";

Const wchar gcszunregisterclientdriverid [] = l "unregisterclientdriverid ";

Const wchar gcszunregisterclientsettings [] = l "unregisterclientsettings ";

Const wchar gcszmousedriverid [] = l "generic_sample_mouse_driver ";

 

The function interface is as follows:

Extern "C" bool

Usbinstalldriver (

Lpcwstr szdriverlibfile) // @ parm [in]-contains client driver DLL name

{

Bool fret = false;

Hinstance hinst = loadlibrary (L "usbd. dll ");

 

// Register the USB device information

If (hinst)

{

Lpregister_client_driver_id pregisterid = (lpregister_client_driver_id)

Getprocaddress (hinst, gcszregisterclientdriverid );

 

Lpregister_client_settings pregistersettings =

(Lpregister_client_settings) getprocaddress (hinst,

Gcszregisterclientsettings );

 

If (pregisterid & pregistersettings)

{

Usb_driver_settings driversettings;

 

Driversettings. dwcount = sizeof (driversettings );

 

// Set our specific information.

Driversettings. dwvendorid = usb_no_info;

Driversettings. dwproductid = usb_no_info;

Driversettings. dwreleasenumber = usb_no_info;

 

Driversettings. dwdeviceclass = usb_no_info;

Driversettings. dwdevicesubclass = usb_no_info;

Driversettings. dwdeviceprotocol = usb_no_info;

 

Driversettings. dwinterfaceclass = 0x03; // hid

Driversettings. dwinterfacesubclass = 0x01; // boot device

Driversettings. dwinterfaceprotocol = 0x02; // mouse

 

Fret = (* pregisterid) (gcszmousedriverid );

 

If (fret)

{

Fret = (* pregistersettings) (szdriverlibfile,

Gcszmousedriverid, null, & driversettings );

 

If (! Fret)

{

// Bugbug unregister the client driver's ID

}

}

}

Else

{

Retailmsg (1, (text ("! Usbmouse: Error getting usbd function pointers/R/N ")));

}

Freelibrary (hinst );

}

Return fret;

}

The above code is mainly used to generate the registry information required by the driver of the USB device. Note that the driver of the USB device uses registerclientdriverid () instead of the standard registry function () and registerclientsettings to register the corresponding device information.

 

Another function is the usbuninstalldriver () function. The Code is as follows:

Extern "C" bool

Usbuninstalldriver ()

{

Bool fret = false;

Hinstance hinst = loadlibrary (L "usbd. dll ");

 

If (hinst)

{

Lpun_register_client_driver_id punregisterid =

(Lpun_register_client_driver_id)

Getprocaddress (hinst, gcszunregisterclientdriverid );

 

Lpun_register_client_settings punregistersettings =

(Lpun_register_client_settings) getprocaddress (hinst,

Gcszunregisterclientsettings );

 

If (punregistersettings)

{

Usb_driver_settings driversettings;

 

Driversettings. dwcount = sizeof (driversettings );

// The information must be the same as that at registration.

Driversettings. dwvendorid = usb_no_info;

Driversettings. dwproductid = usb_no_info;

Driversettings. dwreleasenumber = usb_no_info;

 

Driversettings. dwdeviceclass = usb_no_info;

Driversettings. dwdevicesubclass = usb_no_info;

Driversettings. dwdeviceprotocol = usb_no_info;

 

Driversettings. dwinterfaceclass = 0x03; // hid

Driversettings. dwinterfacesubclass = 0x01; // boot device

Driversettings. dwinterfaceprotocol = 0x02; // mouse

 

Fret = (* punregistersettings) (gcszmousedriverid, null,

& Driversettings );

}

 

If (punregisterid)

{

Bool frettemp = (* punregisterid) (gcszmousedriverid );

Fret = fret? Frettemp: fret;

}

Freelibrary (hinst );

}

Return fret;

}

This function is mainly used to delete the registry information created during usbinstalldriver (). Similarly, it uses its own function interfaces unregisterclientdriverid () and unregisterclientsettings () for corresponding processing.

Another Registration Monitoring notification function usbdevicenotifications () to be processed ():

Extern "C" bool usbdevicenotifications (lpvoid lpvpolicyparameter, DWORD dwcode,

Lpdword * dwinfo1, lpdword * dwinfo2, lpdword * dwinfo3,

Lpdword * dwinfo4)

{

Cmouse * pmouse = (cmouse *) lpvpolicyparameter;

 

Switch (dwcode)

{

Case usb_close_device:

// Delete related resources.

Delete pmouse;

Return true;

}

Return false;

}

 

The USB mouse class is defined as follows:

Class cmouse

{

Public:

Cmouse: cmouse (usb_handle hdevice, lpcusb_funcs lpusbfuncs,

Lpcusb_interface lpinterface );

~ Cmouse ();

 

Bool initialize ();

PRIVATE:

// Callback function called after transmission is completed

Static DWORD callback mousetransfercompletestub (lpvoid lpvpolicyparameter );

// Interrupt handling function

Static ulong callback cmouse: mousethreadstub (pvoid context );

DWORD mousetransfercomplete ();

DWORD mousethread ();

 

Bool submitinterrupt ();

Bool handleinterrupt ();

 

Bool m_fclosing;

Bool m_freadyformouseevents;

 

Handle m_hevent;

Handle m_hthread;

 

Usb_handle m_hdevice;

Usb_pipe m_hinterruptpipe;

Usb_transfer m_hinterrupttransfer;

 

Lpcusb_funcs m_lpusbfuncs;

Lpcusb_interface m_pinterface;

 

Bool m_fprevbutton1;

Bool m_fprevbutton2;

Bool m_fprevbutton3;

 

// Data accept buffer.

Byte m_pbdatabuffer [8];

};

 

The specific implementation is as follows:

 

// Constructor called during initialization

Cmouse: cmouse (usb_handle hdevice, lpcusb_funcs lpusbfuncs,

Lpcusb_interface lpinterface)

{

M_fclosing = false;

M_freadyformouseevents = false;

M_hevent = NULL;

M_hthread = NULL;

 

M_hdevice = hdevice;

M_hinterruptpipe = NULL;

M_hinterrupttransfer = NULL;

 

M_lpusbfuncs = lpusbfuncs;

M_pinterface = lpinterface;

 

M_fprevbutton1 = false;

M_fprevbutton2 = false;

M_fprevbutton3 = false;

 

Memset (m_pbdatabuffer, 0, sizeof (m_pbdatabuffer ));

}

 

// Destructor, used to clear the requested resources.

Cmouse ::~ Cmouse ()

{

// Notify the system to disable related function interfaces.

M_fclosing = true;

 

// Wake up the connection thread again and give it time to die.

If (m_hevent! = NULL)

{

// Notification to close the data receiving thread.

Setevent (m_hevent );

 

If (m_hthread! = NULL)

{

DWORD dwwaitreturn;

 

Dwwaitreturn = waitforsingleobject (m_hthread, 1000 );

If (dwwaitreturn! = Wait_object_0)

{

Terminatethread (m_hthread, DWORD (-1 ));

}

Closehandle (m_hthread );

M_hthread = NULL;

}

Closehandle (m_hevent );

M_hevent = NULL;

}

 

If (m_hinterrupttransfer)

(* M_lpusbfuncs-> lpclosetransfer) (m_hinterrupttransfer );

 

If (m_hinterruptpipe)

(* M_lpusbfuncs-> lpclosepipe) (m_hinterruptpipe );

}

 

 

// Initialize the USB mouse driver

Bool cmouse: Initialize ()

{

Lpcusb_device lpdeviceinfo = (* m_lpusbfuncs-> lpgetdeviceinfo) (m_hdevice );

 

// Check Configuration: the USB mouse should have only one interrupted Pipe

If (m_pinterface-> lpendpoints [0]. descriptor. bmattributes & usb_endpoint_type_mask )! = Usb_endpoint_type_interrupt)

{

Retailmsg (1, (text ("! Usbmouse: EP 0 wrong type (% u )! /R/N "),

M_pinterface-> lpendpoints [0]. descriptor. bmattributes ));

Return false;

}

Debugmsg (zone_init, (text ("usbmouse: EP 0: maxpacket: % u, interval: % u/R/N "),

M_pinterface-> lpendpoints [0]. descriptor. wmaxpacketsize,

M_pinterface-> lpendpoints [0]. descriptor. binterval ));

 

M_hinterruptpipe = (* m_lpusbfuncs-> lpopenpipe) (m_hdevice,

& M_pinterface-> lpendpoints [0]. descriptor );

 

If (m_hinterruptpipe = NULL ){

Retailmsg (1, (text ("Mouse: Error opening interrupt pipe/R/N ")));

Return (false );

}

M_hevent = createevent (null, false, false, null );

If (m_hevent = NULL)

{

Retailmsg (1, (text ("usbmouse: Error on createevent for connect event/R/N ")));

Return (false );

}

// Create a data receiving thread

M_hthread = createthread (0, 0, mousethreadstub, this, 0, null );

If (m_hthread = NULL)

{

Retailmsg (1, (text ("usbmouse: Error on createthread/R/N ")));

Return (false );

}

 

Return (true );

}

 

// Read data from the USB mouse device to generate mouse events.

Bool cmouse: submitinterrupt ()

{

If (m_hinterrupttransfer)

(* M_lpusbfuncs-> lpclosetransfer) (m_hinterrupttransfer );

 

// Read data from the USB mouse Pipe

M_hinterrupttransfer = (* m_lpusbfuncs-> lpissueinterrupttransfer)

(M_hinterruptpipe, mousetransfercompletestub, this,

Usb_in_transfer | usb_short_transfer_ OK, // indicates reading data.

Min (m_pinterface-> lpendpoints [0]. descriptor. wmaxpacketsize,

Sizeof (m_pbdatabuffer )),

M_pbdatabuffer,

Null );

 

If (m_hinterrupttransfer = NULL)

{

Debugmsg (zone_error, (L "! Usbmouse: Error in issueinterrupttransfer/R/N "));

Return false;

}

Else

{

Debugmsg (zone_transfer, (L "usbmouse: submitinterrupt, transfer: 0x % x/R/N ",

M_hinterrupttransfer ));

}

Return true;

}

 

// Process data that is interrupted by the mouse

Bool cmouse: handleinterrupt ()

{

DWORD dwerror;

DWORD dwbytes;

 

DWORD dwflags = 0;

Int dx = (signed Char) m_pbdatabuffer [1];

Int DY = (signed Char) m_pbdatabuffer [2];

 

Bool fbutton1 = m_pbdatabuffer [0] & 0x01? True: false;

Bool fbutton2 = m_pbdatabuffer [0] & 0x02? True: false;

Bool fbutton3 = m_pbdatabuffer [0] & 0x04? True: false;

 

If (! (* M_lpusbfuncs-> lpgettransferstatus) (m_hinterrupttransfer, & dwbytes, & dwerror ))

{

Debugmsg (zone_error, (text ("! Usbmouse: Error in gettransferstatus (0x % x)/R/N "),

M_hinterrupttransfer ));

Return false;

}

Else

{

Debugmsg (zone_transfer, (text ("usbmouse: handleinterrupt, htransfer 0x % x complete (% u bytes, error: % x)/R/N "),

M_hinterrupttransfer, dwbytes, dwerror ));

}

 

If (! Submitinterrupt ())

Return false;

 

If (dwerror! = Usb_no_error)

{

Debugmsg (zone_error, (text ("! Usbmouse: Error 0x % x in interrupt transfer/R/N "), dwerror ));

Return true;

}

 

If (dwbytes <3)

{

Debugmsg (zone_error, (text ("! Usbmouse: Invalid byte CNT % u from interrupt transfer/R/N "), dwbytes ));

Return true;

}

 

If (dx | Dy)

Dwflags | = mouseeventf_move;

 

If (fbutton1! = M_fprevbutton1)

{

If (fbutton1)

Dwflags | = mouseeventf_leftdown;

Else

Dwflags | = mouseeventf_leftup;

}

 

If (fbutton2! = M_fprevbutton2)

{

If (fbutton2)

Dwflags | = mouseeventf_rightdown;

Else

Dwflags | = mouseeventf_rightup;

}

 

If (fbutton3! = M_fprevbutton3)

{

If (fbutton3)

Dwflags | = mouseeventf_middledown;

Else

Dwflags | = mouseeventf_middleup;

}

 

M_fprevbutton1 = fbutton1;

M_fprevbutton2 = fbutton2;

M_fprevbutton3 = fbutton3;

 

Debugmsg (zone_events,

(Text ("usbmouse event: DX: % d, DY: % d, dwflags: 0x % x (B1: % u, B2: % u, B3: % u) /R/N "),

DX, Dy, dwflags, fbutton1, fbutton2, fbutton3 ));

 

// Notifies the system of mouse events

If (m_freadyformouseevents)

Mouse_event (dwflags, dx, Dy, 0, 0 );

Else

M_freadyformouseevents = isapiready (sh_wmgr );

 

Return true;

}

 

 

DWORD callback cmouse: mousetransfercompletestub (lpvoid lpvpolicyparameter)

{

Cmouse * pmouse = (cmouse *) lpvpolicyparameter;

Return (pmouse-> mousetransfercomplete ());

}

 

// Callback function after data transmission is completed

DWORD cmouse: mousetransfercomplete ()

{

If (m_hevent)

Setevent (m_hevent );

Return 0;

}

 

 

Ulong callback cmouse: mousethreadstub (pvoid context)

{

Cmouse * pmouse = (cmouse *) context;

Return (pmouse-> mousethread ());

}

 

// USB mouse thread

DWORD cmouse: mousethread ()

{

Debugmsg (zone_init, (text ("usbmouse: worker thread started/R/N ")));

Setthreadpriority (getcurrentthread (), thread_priority_highest );

 

If (submitinterrupt ())

{

While (! M_fclosing)

{

Waitforsingleobject (m_hevent, infinite );

 

If (m_fclosing)

Break;

 

If (* m_lpusbfuncs-> lpistransfercomplete) (m_hinterrupttransfer ))

{

If (! Handleinterrupt ())

Break;

}

Else

{

Retailmsg (1, (text ("! Usbmouse: event signalled, but transfer not complete/R/N ")));

// The only time this shoshould happen is if we get an error on the transfer

Assert (m_fclosing | (m_hinterrupttransfer = NULL ));

Break;

}

}

}

Retailmsg (1, (text ("usbmouse: worker thread exiting/R/N ")));

Return (0 );

}

 

See no, in fact, the USB driver is so simple to write, similar to other devices, such as printer devices, there is bulk out pipe, need bulk transmission, you need to understand the application of issuebulktransfer. Of course, if you are developing a USB mass storage disk driver, you need to know more about the protocols, such as the bulk-only transport protocol.

 

The source code of the driver with USB printer and USB mass storage disk already exists in Microsoft's Windows CE platform build. After a good research, you will certainly benefit a lot.

Related Article

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.