Code Example: A Timer-Based Driver

< BACK  NEXT >
[oR]

This modified version of the parallel port driver disables interrupts and uses a CustomTimerDpc routine to transfer data at fixed intervals. The code for this example is included on the companion CD and on the companion Web site, http://www.W2KDriverBook.com.

Device Extension Additions

The Device Extension is modified to include the DPC and Timer objects, plus a polling interval value, stored in microseconds.

 typedef struct _DEVICE_EXTENSION {    ...    KDPC pollingDPC;   // reserve custom DPC object    KTIMER pollingTimer;  // and the Timer object    LARGE_INTEGER pollingInterval; // timeout counter    // in us    ... } DEVICE_EXTENSION, *PDEVICE_EXTENSION; // Define the interval between polls of device in us // 100 us #define POLLING_INTERVAL 100 

AddDevice Modifications

AddDevice is changed in that IoConnectInterrupt is no longer called for this polling driver. The polling timer and DPC are initialized.

 NTSTATUS AddDevice(IN PDRIVER_OBJECT pDriverObject,                           IN PDEVICE_OBJECT pdo) {     PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)         pDevObj->DeviceExtension; ... // Near the end of the function, after IoCreateDevice //  has been called... // // Calculate the polling interval in microseconds //  and keep as relative time (negative value)     pDevExt->pollingInterval =           RtlConvertLongToLargeInteger(                POLLING_INTERVAL * -10 ); // // Prepare the polling timer and DPC      KeInitializeTimer( &pDevExt->pollingTimer ); // Notice that the DPC routine receives the fdo      KeInitializeDpc( &pDevExt->pollingDPC,          PollingTimerDpc,          (PVOID) pfdo ); ... } 

TransmitBytes Changes

Each time a transfer is started using the TransmitBytes routine, the timer is initialized so that the polling timer DPC runs when the polling interval expires. Too large a polling interval does not keep the printer busy; too small an interval needlessly wastes CPU time.

 BOOLEAN TransmitBytes( IN PDEVICE_EXTENSION pDevExt) {     // Do all the work necessary to transfer bytes     // to the physical device, as usual    ...    // Then start the polling timer    KeSetTimer( &pDevExt->pollingTimer,                pDevExt->pollingInterval,                &pDevExt->pollingDPC );    return TRUE; } 

PollingTimerDpc Routine

Finally, the DPC routine itself is presented. The DPC routine executes each time the timer object expires. The DPC has the responsibility for checking on the device if more room is available in the printer buffer, more data is sent. If the IRP's requested transfer is complete (or if the transfer encountered an error from the device), the IRP is completed.

 VOID PollingTimerDpc( IN PKDPC pDpc,                       IN PVOID pContext,                       IN PVOID SysArg1,                       IN PVOID SysArg2 ) {      PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)           pContext;      PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)           pDevObj->DeviceExtension;      // Try to send more data      if (!TransmitBytes( pDevExt ) ) {           // Transfer complete (normal or error)           // Complete the IRP appropriately           PIRP pIrp = pDevObj->CurrentIrp;           pIrp->IoStatus.Information =                pDevExt->xferCount;           // Figure out what the final status should be           pIrp->IoStatus.Status = STATUS_SUCCESS;           // Based on HW error status bit, change Status           ...           // Now complete the IRP           IoCompleteRequest( pIrp, IO_PARALLEL_INCREMENT );           // And request another IRP           IoStartNextPacket( pDevObj, FALSE ); } 
< BACK  NEXT >


The Windows 2000 Device Driver Book(c) A Guide for Programmers
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition)
ISBN: 0130204315
EAN: 2147483647
Year: 2000
Pages: 156

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net