If the pen stops moving or is lifted beyond the tablet's range of sensitivity, many devices will stop generating hardware interrupts. This ends the normal flow of communication between the pen device and Windows.
However, the recognition model of the Pen API version 2.0 requires the pen driver to continuously call into the system even when there is no pen data available. If the pen hardware maintains its own clock mechanism, it can continue to pulse time-based interrupts even when the pen is out of range. When pen motion ceases, the time-based interrupts ensure the system continues to receive pen information.
If the pen device does not contain its own clock, the pen device driver must compensate by using the system timer. In this case, the driver provides a timer hook that activates at regular intervals. This enables the driver to continue its stream of system calls even if the normal hardware interrupts from the device have ceased.
The pen Unidriver sample code uses the system timer. If the OEM device generates its own time-based interrupts, the developer should remove the code that uses the system timer from the Unidriver source code. Such code is in the sample virtual pen driver source code modules HWINT.C, TIMERCB.C, and APIPROCS.C.
When enabled through the DRV_ENABLE message, the virtual pen driver sets up a callback timer function to use the system timer. The callback is named cTimer_Callback_Entry_Point in the TIMERCB.C source file. cTimer_Callback_Entry_Point receives control at each timer tick, which occurs every 55 milliseconds. If it determines that no pen data has arrived from the tablet since the last timer tick, cTimer_Callback_Entry_Point fabricates an out-of-range packet and schedules a callback to the function registered by PENWIN.DLL so the fabricated packet will be sent to the system. An out-of-range packet is a DRV_PENPACKET structure with the wPDK member set to the defined value PDK_OUTOFRANGE. After completing all this, cTimer_Callback_Entry_Point sets up another timer tick callback and waits.
Handling out-of-range pen packets is a virtual pen driver design issue.
All tablets run in what is called in this documentation shutup mode. In shutup mode, the tablet sends only one out-of-range packet when the pen goes out of range and then sends no more packets until the pen goes back into range. However, serial communications and tablets may be unreliable and the one out-of-range packet is never received by the driver. Sometimes such a lost out-of-range packet can cause Windows 95 to stop processing messages and force the user to restart Windows. For example, suppose the user employs the pen to move a window by dragging the window's title bar. A possible sequence of important pen events during this window dragging operation are:
If both the second and third events are lost because of unreliable communication between the tablet and the virtual pen driver, the user will eventually have to restart Windows.
To guard against this with tablets that run only in shutup mode, the sample virtual pen driver uses a timer function to constantly monitor the time interval between packet receipt events in the virtual pen driver. If the virtual pen driver does not receive a packet within this time interval, the time function generates an out-of-range packet, which gets sent to the pen driver which notifies Windows of the pen event.
Some OEM tablets (such as the Wacom tablets) enable the virtual pen driver to toggle the tablet between two modes:
For such tablets, the following strategy can be used to insure that unreliable pen packet communication between the tablet and the virtual pen driver do not force the user to restart Windows:
If you are writing a virtual pen driver that supports both shutup and speakup modes, using the above strategy will put more responsive pens in the hands of the users than if you use the timer method.
The Windows95 DDK sample pen driver supports only the timer method of guarding against lost out-of-range pen packets. For sample code that implements the method that uses both speakup and shutup modes, see the sample pen driver in the Windows 3.1 DDK.
The timer strategy is implemented in the following blocks of code:
Source Module | Function | Comment |
---|---|---|
TIMERCB.C | cTimer_Callback_Entry_Point | This code determines whether it has been too long since receipt of the last packet and, if so, synthesizes an out-of-range packet. |
APIPROCS.C | cVpenD_API_Enable | Registers the timer callback entry point and, if the HW_TIMERMODEL flag is set, causes monitoring of the interval between interrupts to begin. |
Note that with tablets that support speakup mode, it can also be used to implement playback of stored pen packets. The virtual pen driver puts the tablet in speakup mode and every time it receives an out-of-range packet, the driver substitutes information from the next stored pen packet and sends it on to the pen driver as a pen packet. The blocks of code that implement this strategy in the sample virtual pen driver are:
Source Module | Function | Comment |
---|---|---|
APIPROC.C | cVpenD_API_Proc | See the VPEND_PENPLAYSTART case block in the dwMsg switch structure. |
OEMAPI.C | cOEM_API_Proc | Sends the speak up and shut up command strings to the tablet. |