Jump to content

PDDREF:Character Device Monitors

From EDM2
Physical Device Driver Reference
  1. Introduction
  2. Physical Device Driver Overview
  3. Physical Device Driver Architecture and Structure
  4. OS/2 Physical Device Driver Operations
  5. OS/2 Physical Device Driver Design Issues
  6. Character Device Monitors
  7. Installation of External Loadable Device Drivers
  8. Physical Device Driver Strategy Commands
  9. Device Helper (DevHlp) Services
  10. Resource Management
  11. Linking Resource Manager Services
  12. Generic IOCtl Commands
Appendixes
OS/2 Version Compatibility Considerations
Running OS/2 Version 1.3 16-Bit PDDs on OS/2
Using Advanced Bios
Notices
Glossary

A character device monitor is an application, or part of an application, that uses standard OS/2 function calls to interact with the physical device driver and its data streams.

Through the use of character device monitors, applications can directly access and intercept data flowing through data streams belonging to some character device drivers. The applications can then filter (remove, insert, or modify) data passin through a character device by registering one or more character device monitors with the physical device driver. The character device monitors require support by the character device driver, as well as by the application.

The following figure shows Data Interception by Device Monitors.

          ÚÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄ¿
          ³Device ³    ³Device ³    ³Device ³
          ³Monitor³    ³Monitor³    ³Monitor³
          ³       ³    ³       ³    ³       ³
          ÀÄ�ÄÄÄ�ÄÙ    ÀÄ�ÄÄÄ�ÄÙ    ÀÄ�ÄÄÄ�ÄÙ
            ³   ³        ³   ³        ³   ³
            ³   ÀÄÄÄÄÄÄÄÄÙ   ÀÄÄÄÄÄÄÄÄÙ   ³
          ÚijÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄijĿ
   INT    ³ ³          Character          ³ ³ INT
  ÄÄÄÄÄÄ�ÄÄÄÙ           Device            ÀÄÄÄÄÄÄÄÄ�
   WRITE  ³             Driver              ³ READ
          ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

Applications that monitor data passing through a character device can perform a variety of functions. They can serve as:

  • User-extensions of a character device driver. Data passing through a data stream can be manipulated to modify the state of the device as viewed by another application.
  • Dialog managers. Command sequences or control keys can be activated on a given keystroke. These include pop-up facilities and notepad applications.
  • Language translators. Characters can be translated from one language to another.
  • Redirection mechanisms. Data can be redirected from one device to another by character device monitors, as shown in the following illustration. An application can register two monitors with two separate character devices. Data taken from the data stream belonging to the first device by the first monitor can be placed into the data stream belonging to the second device by the second monitor.

The following figure shows Data Redirection Using Device Monitors.

         ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
         ³        DATA REDIRECTION APPLICATION           ³
         ³                                               ³
         ³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿       ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿  ³
         ³  ³    Keyboard    ³       ³    Printer     ³  ³
         ³  ³ Device Monitor ³       ³ Device Monitor ³  ³
         ³  ³               ÄÄÄÄÄÄÄÄ�³                ³  ³
         ³  ÀÄÄÄ�ÄÄÄÄÄÄÄÄÄÄÄÄÙ       ÀÄÄÄÄÄÄÄÄÄÄÄÄ�ÄÄÄÙ  ³
         ÀÄÄÄÄÄijÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄijÄÄÄÄÄÄÙ
 ÚÄÄÄÄÄÄÄÄÄÄ¿   ³                                 ³   ÚÄÄÄÄÄÄÄÄÄÄ¿
 ³ Keyboard ³   ³                                 ³   ³  Printer ³
 ³  Device  ³   ³                                 ³   ³  Device  ³
 ÀÄÄÄÄ�ÄÄÄÄÄÙ   ³                                 ³   ÀÄÄÄÄ�ÄÄÄÄÄÙ
      ³      ÚÄijÄÄÄÄÄÄÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄijĿ      ³
      ÀÄÄÄÄÄÄÄÄÄÙ Keyboard    ³    ³ Parallel PortÀÄÄÄÄÄÄÄÄÙ
             ³ Device Driver  ³    ³ Device Driver  ³
             ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

OS/2 character device drivers that provide monitor support include the keyboard, mouse, and parallel port device drivers.

The OS/2 monitor mechanism includes the character device monitor process and the support required by a character device driver that enables device monitoring to be performed. Guidelines are given below for developing a character device monitor and for implementing monitor support in the character device driver.


Monitoring Character Device Data Streams

A physical device driver receives data from a device or receives requests from applications to send data to a device. The physical keyboard and mouse device drivers receive data from the keyboard and mouse devices, respectively. The physical parallel port device driver receives requests from applications to write data to the printer device.

The flow of data between a physical device driver and its device is called a data stream. The physical device driver defines the data streams for its device, and associates the data it receives from a device or application with a particular data stream. Physical device drivers can have more than one data-stream model within, or between, sessions. For example, the physical keyboard device driver supports three different data-stream models for DOS, Presentation Manager, and OS/2 sessions. Of these, only the OS/2-mode data stream supports keystroke monitors.

Note: OS/2 1.2, 1.3, 2.0, 2.1, and 3 do not allow an application to register a keyboard or mouse device monitor for a Presentation Manager session.

There are several ways in which a physical device driver can define its data streams. When the physical keyboard or mouse device driver receives data from its device, it associates that data with the current foreground OS/2 session (which can be the Presentation Manager session) and places the data into the data stream defined for that session. These physical device drivers define data streams for each session. When the physical parallel port device driver receives a request from an application to write data to the printer, it places the data into the data stream defined for that printer device. This physical device driver defines data streams for each physical device.

A single data stream can be filtered by one or more character device monitors that are linked together in a monitor chain. That is, the first character device monitor in a monitor chain receives data directly from the physical device driver. This character device monitor filters the data and passes it on to the next character device monitor in the chain. This character device monitor filters the filtered data and passes it on to the next character device monitor in the chain, and so forth. The last character device monitor in the chain passes the filtered data back to the physical device driver.

Just as physical device drivers define their data streams, they also determine how character monitors are chained. The physical keyboard and mouse device drivers, for example, support a monitor chain for each OS/2 session. The physical parallel port device driver supports two monitor chains for each physical printer device. Refer to the OS/2 Input/Output Device Driver Reference for more information about the physical keyboard device driver, the physical mouse device driver and the physical parallel port device driver for a description of how these device drivers support device monitors.


Device Monitor Support Limitations

Data streams for character devices can be monitored by a character-device monitor only when the character device driver provides device monitor support. Applications, including both OS/2-mode and Presentation Manager applications, can monitor keystrokes and mouse clicks for all OS/2 sessions. However, the applications cannot monitor keystrokes and mouse clicks for Presentation Manager or DOS session.

The keystroke and mouse click mechanism for Presentation Manager sessions differs from the mechanism for OS/2 sessions. The physical keyboard and mouse device drivers manage keystrokes and mouse clicks respectively for each OS/2 session. These physical device drivers create monitor chains for each OS/2 session. Applications can register keystroke and mouse device monitors for each OS/2 session.

The Presentation Manager manages both keystrokes and mouse clicks for each of its extended sessions, but does not create monitor chains for each of its extended sessions. Applications cannot register a keystroke or mouse device monitor for a Presentation Manager extended session. Notice that applications cannot intercept keystrokes or mouse clicks associated with the Presentation Manager session through keystroke or mouse monitors.

However, all applications (including OS/2 and Presentation Manager applications) can monitor printer data. The physical parallel port device driver bases the definition of its data streams on the physical device. In general, data streams for character devices that do not base the definition of their data streams on sessions can be monitored by the character device monitor when the character device driver provides device monitor support.

The following figure shows the OS/2 Monitors and Presentation Manager Applications.

   Data Flow to an OS/2 Application ³ Data Flow to a PM Application
      Running in an OS/2 Session    ³    Running in a PM Session
 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
   ÚÄÄÄÄÄÄÄÄÄÄ¿                     ³     ÚÄÄÄÄÄÄÄÄÄÄ¿
   ³ Keyboard ³                     ³     ³ Keyboard ³
   ³ or mouse ³                     ³     ³ or mouse ³
   ³ devices  ³         ÚÄÄÄÄÄÄÄÄÄ¿ ³     ³ devices  ³
   ÀÄÄÄÄÂÄÄÄÄÄÙ     ÚÄÄ�³ Monitor ³ ³     ÀÄÄÄÄÂÄÄÄÄÄÙ
        ³           ³   ÀÄÄÄijÄÄÄÄÙ ³          ³
ÚÄÄÄÄÄÄÄ�ÄÄÄÄÄÄÄÄ¿  ³        ³      ³  ÚÄÄÄÄÄÄÄ�ÄÄÄÄÄÄÄÄ¿
³       ÀÄÄÄÄÄÄÄÄ�ÄÄÙ        ³      ³  ³       ³        ³
³    Keyboard    ³      ÚÄÄÄÄ�ÄÄÄÄ¿ ³  ³    Keyboard    ³
³    or mouse    ³      ³ Monitor ³ ³  ³    or mouse    ³
³ device drivers ³      ÀÄÄÄÄ¿ÄÄÄÄÙ ³  ³ device drivers ³
³       ÚÄÄÄÄÄÄÄÄ�ÄÄ¿        ³      ³  ³       ³        ³
ÀÄÄÄÄÄÄijÄÄÄÄÄÄÄÄÙ  ³        ³      ³  ÀÄÄÄÄÄÄÄ�ÄÄÄÄÄÄÄÄÙ
        ³           ³   ÚÄÄÄÄ�ÄÄÄÄ¿ ³          ³
        ³           ÀÄÄÄ´ Monitor ³ ³   ÚÄÄÄÄÄÄ�ÄÄÄÄÄÄÄ¿
        ³               ÀÄÄÄÄÄÄÄÄÄÙ ³   ³      ³       ³
   ÚÄÄÄÄ�ÄÄÄÄÄ¿                     ³   ³ Presentation ³
   ³ OS/2 App ³                     ³   ³    Manager   ³
   ÀÄÄÄÄÄÄÄÄÄÄÙ                     ³   ³      ³       ³
                                    ³   ÀÄÄÄÄÄÄ�ÄÄÄÄÄÄÄÙ
                                    ³   ÚÄÄÄÄÄÄÅÄÄÄÄÄÄÄ¿
                                    ³ ÚÄ�Ä¿  ÚÄ�Ä¿   ÚÄ�Ä¿
                                    ³ ³PM ³  ³PM ³   ³PM ³
                                    ³ ³App³  ³App³   ³App³
                                    ³ ÀÄÄÄÙ  ÀÄÄÄÙ   ÀÄÄÄÙ

A Presentation Manager application can filter keyboard and mouse events (messages) through hook procedures. These procedures are registered by an application and are called when certain events occur. More than one procedure can be called when a single event occurs. In this case, procedures are chained together so that each event is passed first to one procedure and then to the next, and so on down the chain. This chain of procedures is called a hook chain.

There are two kinds of hook procedures, system hook and queue hook. System hook procedures are called when an event occurs in the Presentation Manager's system queue. Queue hook procedures are called when an event occurs in the Presentation Manager application's queue. There are several kinds of events that can be hooked. These include messages input to an application and messages sent by an application. For detailed descriptions of hook procedures, refer to the OS/2 Programming Guide, Volume 2, and the OS/2 Presentation Manager Programming Reference.


The OS/2 Monitor Mechanism

The OS/2 monitor mechanism consists of monitor buffers, monitor threads, and signals. This mechanism is supported by the OS/2 Monitor Dispatcher, which consists of:

OS/2 monitor dispatcher functions, a set of five dynamic link routines:

       DosMonOpen
       DosMonReg
       DosMonClose
       DosMonRead
       DosMonWrite 

Monitor Dispatcher Device Helper, a set of five OS/2 DevHlp services:

           MonitorCreate
           Register
           DeRegister
           MonWrite
           MonFlush 

The OS/2 monitor dispatcher functions are part of the MONCALLS dynamic link function library. These routines are loaded on demand at privilege level 2 and can be called from applications loaded at privilege level 2 or 3. Using these routines, applications can intercept and filter data passing through a device. The OS/2 monitor functions provide the interface for monitor applications to interact with the physical device driver (to request registration and termination of monitor activity) and the data stream.

The Monitor Dispatcher Device Helper (DevHlp) services are part of the OS/2 Device Helper, available to all character device drivers. Through these routines, a character device driver provides the support for applications that monitor its data streams. The Monitor Dispatcher Device Helper provides the interface for character device drivers to interact with the monitor dispatcher (for itself and for applications requesting registration and termination of monitors) and applications monitoring its data streams. In addition, the Monitor Dispatcher Device Helper provides the mechanism for passing data from one monitor to another.

Character device monitor applications are generally multithreaded, with child monitor threads that take data from the data stream and return filtered data to the data stream. Monitor threads use signals in two ways:

When no data is available for the monitor in the data stream, a monitor thread can wait for a signal from the monitor dispatcher when data is available for the monitor. When the data stream cannot accept data from the monitor (for example, there is a blockage downstream in the monitor chain or at the physical device driver), a monitor thread will wait for a signal from the monitor dispatcher when the data stream can accept data from the monitor.

When a monitor thread has finished taking data from, or returning data to, the data stream, it signals the monitor dispatcher that it has completed its work.

Notice that signaling between monitor threads is managed by the monitor dispatcher and is transparent to the monitor application.

Character Device Monitor Process

A character device monitor can monitor only one data stream belonging to a character device driver. An application, however, can include one or more character device monitors that monitor one or more data streams belonging to one or more character device drivers. For example, an application can monitor keystrokes and mouse clicks for each OS/2 session. This application will include a character device monitor for each OS/2 session for each of the physical keyboard and mouse device drivers.

To monitor a data stream belonging to a character device driver, an application must first gain access to that data stream. An application gains access to a data stream by calling:

  • DosMonOpen to establish a connection to the physical device driver. DosMonOpen returns a device handle for monitors to the application. The application will use this handle to direct subsequent DosMonReg and DosMonClose calls to the physical device driver.
  • DosMonReg to register a monitor with a particular data stream belonging to the physical device driver. Once the monitor is installed in the monitor chain, the monitor dispatcher automatically moves data between monitors (if there is more than one in the chain) and returns filtered data to the physical device driver.

After an application has gained access to a data stream, it can remove, insert, modify, or view all characters passing through the data stream. An application intercepts data flowing through a data stream by calling:

  • DosMonRead to take data from the data stream and place it into a private data area where the application can freely access it for filtering.
  • DosMonWrite to take filtered data from the application's private data area and return it to the data stream.

When an application no longer needs to monitor data streams belonging to a single character device driver, it must relinquish access to all data streams belonging to that physical device driver, in addition to terminating its monitor threads. An application terminates a monitor by calling:

  • DosMonClose to close the device handle (that is, terminate the connection to the physical device driver for the monitors).
  • DosExit to terminate its monitor threads that are directly accessing the data streams.

Refer to the OS/2 Control Program Programming Reference for more information on the 16-bit Dosxxx functions. The following figure illustrates pseudocode for a simple character device monitor.

      A Simple, Single-Threaded Character Device Monitor

Get access to the device's data stream:

  CALL DosMonOpen to open the device and get a monitor handle
    for the device
  CALL DosSetPrty to set priority of the monitor thread high
  CALL DosMonReg to register a monitor for the data stream of
    the device

WHILE monitoring the data stream:

  CALL DosMonRead to take a data record from the data stream
  Filter the data record
  CALL DosMonWrite to return the filtered data record to the
    data stream

END WHILE

After monitoring the data stream:

  CALL DosMonClose to terminate the monitor and close the
    monitor handle to the device
  CALL DosExit to terminate this application

Character Device Driver with Monitor Support

For an application to monitor data passing through a character device, the character device driver must provide monitor support. For each data stream that can be monitored by applications, the character device driver must first create a monitor chain. For each monitor chain, the character device driver must define a monitor chain buffer in its first data segment, where the monitor dispatcher will place filtered data that has passed through all monitors registered with the monitor chain. In addition, the character device driver must define a notification routine within its first code segment. This routine is called by the monitor dispatcher when filtered data has been placed into the monitor chain buffer. Note that a character device driver creates a monitor chain by calling the DevHlp_MonitorCreate.

When an application registers a monitor (that is, calls DosMonReg), the character device driver receives the IOCtl request MON_REGISTERMONITOR Register Monitor from the monitor dispatcher on behalf of the application. This registers the monitor with the monitor chain belonging to one of its data streams. A character device driver registers a monitor with the monitor chain belonging to one of its data streams by calling the DevHlp_Register.

When one or more monitors are registered with a monitor chain belonging to one of its data streams, a character device driver can send data to its monitors. A character device driver sends data to monitors registered with one of its monitor chains by calling the DevHlp_MonWrite. Under certain conditions, a character device driver can guarantee that all data sent to its monitors in a monitor chain has been filtered and returned to the data stream. A character device driver flushes all data from all monitors registered with a monitor chain by calling the DevHlp_MonFlush.

When a monitor application stops monitoring data streams belonging to a character device driver, or when a monitor application abnormally terminates (for example, the user presses the Ctrl+C key sequence), the character device driver receives a monitor close request from the file system. Because an application can have one or more monitors registered with one or more monitor chains belonging to the physical device driver, the character device driver must remove all monitors belonging to the application that are registered on any of its monitor chains. A character device driver removes monitors belonging to an application by calling the DevHlp_DeRegister for each monitor chain that belongs to each of its data streams.

Character Device Driver and Monitors

A character device driver and its monitors are interdependent. The implementation of the character device driver determines the ground rules for its monitors, including:

  • The definition of its data streams and monitor chains
  • The format of the data flowing through its monitor chains
  • The rules on consuming, modifying, and returning data

Because a monitor directly interacts with a data stream, there is a danger of severely affecting the data stream if a monitor is not well-behaved (that is, if the monitor does not adhere to the rules of the character device driver). The interdependence of a character device driver and its monitors can be directly demonstrated by presenting a description of the sequence of events occurring in the character device driver and its monitors during:

  • Monitor registration and termination
  • Movement of data through a monitor chain
Registering and Terminating a Monitor

During monitor registration and termination, the monitor dispatcher communicates with the character device driver on behalf of the monitor application through the OS/2 file system and IOCtl interface. The application initiates OS/2 monitor functions, and the character device driver receives and responds to the corresponding requests. The following figure illustrates the monitor function calls made by the application and the corresponding responses by the character device driver.

The following figure shows an Application to the Device Driver Interface.

                                                              MONITOR
APPLICATION         FILE SYSTEM          DEVICE DRIVER      DISPATCHER
ÚÄÄÄÄÄ¿               ÚÄÄÄÄÄ¿               ÚÄÄÄÄÄ¿            ÚÄÄÄÄÄ¿
³  (1)³ DosMonOpen    ³     ³ Open request  ³     MonitorCreate³     ³
³    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�³    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�³    ÄÄÄÄÄÄÄÄÄÄÄÄÄ�³     ³
³  (3)³ DosMonClose   ³     ³ Close request ³     ³ DeRegister ³     ³
³    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�³    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�³    ÄÄÄÄÄÄÄÄÄÄÄÄÄ�³     ³
³     ³               ÀÄÄÄÄÄÙ               ³     ³            ³     ³
³     ³           IOCtl INTERFACE           ³     ³            ³     ³
³     ³               ÚÄÄÄÄÄ¿               ³     ³            ³     ³
³  (2)³ DosMonReg     ³     Register request³     ³ Register   ³     ³
³    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�³    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�³    ÄÄÄÄÄÄÄÄÄÄÄÄÄ�³     ³
³     ³               ³     ³               ³     ³            ³     ³
ÀÄÄÄÄÄÙ               ÀÄÄÄÄÄÙ               ÀÄÄÄÄÄÙ            ÀÄÄÄÄÄÙ

For example, Character Device Driver Z defines only one data stream for its device. Application X wishes to monitor Character Device Driver Z's data stream:

  • Application X calls DosMonOpen to get a handle to Character Device Driver Z. Through the file system, the monitor dispatcher sends an Open request for monitors to Character Device Driver Z on behalf of Application X. It is recommended to wait until Step 2, when the device driver receives the monitor Register IOCtl.

If Character Device Driver Z has not already created a monitor chain for its data stream, Character Device Driver Z can call the DevHlp_MonitorCreate to create the monitor chain.

  • Application X calls DosMonReg to register Monitor Y with the monitor chain for Character Device Driver Z's data stream. On behalf of Application X, the monitor dispatcher issues a monitor register IOCtl request to Character Device Driver Z.

If Character Device Driver Z has not already defined a monitor chain for its data stream, Character Device Driver Z must now call MonitorCreate to create the monitor chain.

On receiving the monitor register IOCtl request, Character Device Driver Z calls the DevHlp_Register so that the monitor dispatcher can install Application X in the monitor chain.

  • When Application X stops monitoring Character Device Driver Z's data stream, Application X calls DosMonClose.

The monitor dispatcher sends a Close request for monitors through the file system to Character Device Driver Z on behalf of Application X.

On receiving the monitor close request, Character Device Driver Z must call the DevHlp_DeRegister so the monitor dispatcher can remove Application X from the monitor chain.

Data Passing Through a Monitor Chain

A character device can be an input device or an output device. A physical device driver receives data from an input device (for example, the keyboard or mouse) and makes it available to users through its API (Application Programming Interface) buffers. A physical device driver also receives requests from applications to send data to an output device. Using the example above, when Character Device Driver Z has created a monitor chain for its data stream, and Application X has registered Monitor Y with that monitor chain, data flows through the monitor chain as illustrated below:

The following figure shows Data Flow Through a Monitor Chain.

                  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
                  ³   Application X's   ³
                  ³    Address Space    ³
                  ³                     ³
                  ³      Monitor Y      ³
                  ³   ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿   ³
                  ³   ³   Private   ³   ³
                  ³   ³  Data Area  ³   ³
                  ³   ÀÄÄÄ�ÄÄÄÄijÄÄÄÙ   ³
                  ÀÄÄÄÄÄÄijÄÄÄÄijÄÄÄÄÄÄÄÙ
           (3) DosMonRead ³     ³ DosMonWrite (4)
                          ³     ³
 Privilege Level 2 or 3   ³     ³
--------------------------³-----³------------------------
 Privilege Level 0        ³     ³
                          ³     ³
                  ÚÄÄÄÄÄÄijÄÄÄÄÄ�ÄÄÄÄÄÄÄ¿
                  ³  Monitor Dispatcher ³
                  ³     Device Helper   ³
                  ÀÄÄÄÄÄÄÄ�ÄÄÄÄijÄÄÄÄÄÄÄÙ
                          ³     ³
             MonWrite (2) ³     ³ (5)
                          ³     ³
          ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
  INT (1) ³               ³ |   ³            ³  INT (6)
  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�ÄÄÄÄÄÄÄÄÄÙ |   ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ�
  WRITE   ³    Character    |  Monitor Chain ³  READ
          ³ Device Driver Z |      Buffer    ³
          ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

1.- Character Device Driver Z receives data in one of the following ways:

If Character Device Z is an input device, the data received by its physical device driver comes directly from the device.

If Character Device Z is an output device, the data received by its physical device driver comes from an application requesting output to the device.

2. Character Device Driver Z determines where to place the data (that is, into which data stream and monitor chain, if any). In this example, Character Device Driver Z has defined only one data stream for its device. Because a monitor chain has been created for the data stream, Character Device Driver Z places the data into the monitor chain by calling the DevHlp_MonWrite.

3. Monitor Y calls DosMonRead to take data from the data stream and place it into a private data area where it can freely access and process the data.

4. When Monitor Y has processed, or filtered, the data, it returns the filtered data to the data stream by calling DosMonWrite.

5. Since Monitor Y is the only monitor registered with the monitor chain, the monitor dispatcher automatically returns the filtered data from the output buffer of Monitor Y to the monitor chain buffer of Character Device Driver Z, and calls Character Device Driver Z's notification routine.

6. Character Device Driver Z processes the data received in its monitor chain buffer before returning to the monitor dispatcher:

  • If Character Device Z is an input device, Character Device Driver Z moves the filtered data from its monitor chain buffer into its API buffer, where it can be read from an application.
  • If Character Device Z is an output device, character Device Driver Z sends the filtered data to the device.

OS/2 Monitor Functions

An application process that monitors data passing through a character device uses the OS/2 monitor functions to:

  • Gain access to the data stream (DosMonOpen, DosMonReg)
  • Take data from the data stream (DosMonRead), and return filtered data to the data stream (DosMonWrite)
  • Relinquish access to the data stream (DosMonClose)

Monitor applications use the OS/2 monitor functions to communicate with a character device driver and to directly intercept data from a data stream belonging to the character device driver. The OS/2 monitor functions are part of the OS/2 monitor dispatcher. They are shipped with OS/2 2.1 (and later) as the MONCALLS dynamic link subroutine library. These routines are loaded at privilege level 2 and are callable from applications running at privilege level 2 or 3. Each OS/2 monitor function uses the OS/2 System Trace Facility, tracing entry, and exit parameters when tracing is enabled for monitors. This facility provides assistance for the monitor application developer during the debug phase of the application's development cycle.

OS/2 API standards require that a General Protection (GP) fault occurs when a null selector is passed as an address parameter to an API call. To conform to this standard, the monitor functions generate a GP fault when a null selector is passed as an address parameter. A pop-up message notifies the user that the process is being terminated.

DosMonOpen

An application that monitors data passing through a character device must first obtain a handle to the device by calling DosMonOpen. The application will need this handle to communicate with the character device driver in subsequent monitor functions, DosMonReg (for monitor registration) and DosMonClose (for monitor termination).

The parameters for DosMonOpen are shown in the table below. The address parameters are selector:offset addresses. Refer to the OS/2 I/O Subsystems and Device Support for a detailed description of these parameters.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³Parameter Description         ³Size                          ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Address of Device Name String ³DWORD                         ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Address of Device Handle      ³DWORD                         ³
³Returned                      ³                              ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

DosMonOpen calls DosOpen to open a handle to a character device for monitors. DosMonOpen returns the device handle returned from DosOpen to the application. The character device driver differentiates a DosOpen request from a DosMonOpen request by the 08h value specified in the Status field of the request packet. On receiving the monitor open request, the character device driver can optionally issue a call to the DevHlp_MonitorCreate to create a monitor chain. A character device driver can create a monitor chain anytime prior to issuing a call to the DevHlp_Register, including at initialization time during device driver installation.

Note: An application needs to call DosMonOpen only once per character device. Repeated DosMonOpen calls by an application to open the same device for monitors will return the same handle. An application can register one or more monitors with data streams belonging to the same character device using the same handle. For example, an application can open the keyboard device for monitors (call DosMonOpen). Using the handle returned from this call, the application can register a monitor for each OS/2 session. Each OS/2 session has its own keystroke data stream and associated monitor chain.

DosMonReg

Before calling this function, an application previously must have called DosMonOpen to get a handle to the character device driver. The application needs this handle so a monitor register request can be sent to the character device driver.

The parameters for DosMonReg are shown in the table below. The address parameters are selector:offset addresses. Refer to the OS/2 I/O Subsystems and Device Support for a detailed description of the parameters to this function.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³Parameter Description         ³Size                          ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Device Handle Returned from   ³WORD                          ³
³DosMonOpen                    ³                              ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Address of Monitor's Input    ³DWORD                         ³
³Buffer                        ³                              ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Address of Monitor's Output   ³DWORD                         ³
³Buffer                        ³                              ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Positional Placement Flag     ³WORD                          ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Index (defined by the         ³WORD                          ³
³individual device driver)     ³                              ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

The monitor's input and output buffers are allocated by the application from the same data segment. The first WORD of each buffer must contain the length of the private data area plus 20 bytes, length WORD inclusive. To maintain data movement through all monitor buffers in a monitor chain (more than one application can register monitors with the same monitor chain), the minimum size of these private data areas must be the length of the character device driver's monitor chain buffer. The monitor chain buffer is located at the end of a monitor chain, and receives filtered data that has passed through all monitors in the monitor chain. Because it is defined and owned by the character device driver, its length is documented in the descriptions of the individual character device drivers that support monitors. See the descriptions of the physical keyboard, mouse, and parallel port device drivers for this information.

The Index parameter indicates the data stream for the character device that the application is monitoring. The individual character device driver defines this parameter. For example, index indicates the OS/2 session number for the physical keyboard and mouse device drivers. See the descriptions of the physical keyboard, mouse, and parallel port device drivers for details.

The Positional Placement Flag is used to specify the placement (first, last, or default) of a monitor's buffers within the monitor chain. Location of a monitor within a monitor chain is relative to monitors that are already registered with the monitor chain. See Positioning of Monitors in a Monitor Chain for details.

DosMonReg issues a monitor registration Category 0AH MON_REGISTERMONITOR. Register Monitor. On receiving a monitor register request, a physical device driver must call the Monitor Dispatcher Device Helper to:

  • Create a monitor chain by calling the DevHlp_MonitorCreate routine, if no monitor chain was previously created.
  • Establish the monitor placement within a monitor chain by calling the DevHlp_Register.

Until there is a successful return from the call to DosMonReg, no character will enter the monitor's input buffer. That is, the monitor will not have access to the device driver's data stream. The application is responsible for synchronizing completion of the call to DosMonReg and the subsequent monitoring of the data stream with device input into the data stream. For an example and solution to this problem, see the Type-Ahead Characters.

DosMonRead

After an application has registered as a monitor for a device, it can take data from the data stream for filtering by calling DosMonRead. DosMonRead has three primary actions:

  • Wait (optionally) for a signal from the monitor dispatcher that data is available to be read.
  • Move that data from the data stream into a private data area where it can be accessed freely by the monitor for filtering.
  • Signal the monitor dispatcher that data has been removed from the data stream.

The parameters for DosMonRead are shown in the table below. The address parameters are selector:offset addresses of the following data areas within its address space:

  • The input buffer address previously registered with the monitor chain for the device �
  • A private data area into which the data record read from the data stream is to be placed �
  • A Byte Count variable that on entry indicates the size of the private data area, and on exit indicates the size of the data record read from the data stream

In addition, the application can specify whether to block (wait) if no data is available in the data stream

    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
    ³Parameter Description         ³Size                          ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Address of Monitor's Input    ³DWORD                         ³
    ³Buffer                        ³                              ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Waitflag                      ³WORD                          ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Address of Private Data Area  ³DWORD                         ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Address of Byte Count Variable³DWORD                         ³
    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

For each DosMonRead call, a single data record is taken from the data stream and is placed into the monitor's private data area for filtering. A monitor data record is constructed by the physical device driver. It consists of a flag WORD, that can be followed by actual device data. Monitor data records are variable length (that is, some consist only of a flag WORD, while some consist of a flag WORD followed by actual device data of differing lengths). The maximum length of a monitor data record passing through a monitor chain is the length of the device driver's monitor chain buffer minus 2 bytes.

The physical device driver uses flags within the flag WORD to indicate the type of data that is part of this data record. The device driver also uses flags to indicate the action it expects its monitors to take when this data record is received. In addition, physical device drivers have specific requirements for the return of data records to the data stream. Because of this, character device monitors must not indiscriminately consume data records from the data stream. See the chapters on the individual character device drivers for descriptions of their monitor records and expected actions.

Flushing a data stream is an important operation. At certain times it is necessary to guarantee that all data is removed from the data stream. At these times, a specially marked record called a flush record is placed into the data stream by the physical device driver and must pass through all monitors in the chain. The flush data record consists of a single flag WORD, with the third bit of the first byte set. It is the only data record created by the monitor dispatcher, and it is placed into a monitor chain by the monitor dispatcher for the physical device driver. See MonFlush for more information. When a flush record is received by a monitor, the monitor must return the record to the data stream by calling DosMonWrite after taking the appropriate action. The action to be taken in response to the flush record varies with the type of device and type of support required. To guarantee that all data has been removed from all buffers in the monitor chain, the monitor dispatcher prevents the character device driver from placing additional data into the data stream until the flush record has passed through all monitors in the monitor chain.

Note: If the flush record is not returned to the data stream, the data stream will be severely and permanently affected.

Separate monitor threads from the same application can call DosMonRead to take data from the data stream. To protect the data stream during data movement, the monitor dispatcher guarantees that only one thread at a time from a single process can take data from the data stream. Therefore, the application does not have to synchronize calls to DosMonRead made by its separate threads.

If a monitor thread calls DosMonRead during monitor termination (for example, DosMonClose has been called from another thread belonging to the same application), it will receive an error return indicating that there is no data present in the data stream. If a monitor thread is blocked on a call to DosMonRead when monitor termination begins, it will be awakened and receive the same error return. In both cases, the monitor thread must handle the error return code. The application is responsible for the orderly termination of its individual monitor threads.


DosMonWrite

After an application has registered as a monitor for a device, it can return filtered data to the data stream by calling DosMonWrite. DosMonWrite has three primary actions:

  • Wait for a signal from the monitor dispatcher that data has been removed from the data stream if there is not enough room for the data.
  • Move filtered data from the monitor's private data area into the data stream.
  • Signal the monitor dispatcher that data has been placed into the data stream.

The parameters for DosMonWrite are shown in the table below. The address parameters are selector:offset addresses of the following data areas within its address space:

  • The output buffer address previously registered with the monitor chain for character device. �
  • The private data area, which contains the filtered data record to be returned to the data stream.

In addition, the application must specify a Byte Count variable, indicating the size of the data record to be returned to its output buffer.

    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
    ³Parameter Description         ³Size                          ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Address of Monitor's Output   ³DWORD                         ³
    ³Buffer                        ³                              ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Address of Private Data Area  ³DWORD                         ³
    ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
    ³Byte Count                    ³WORD                          ³
    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

For each call to DosMonWrite, a single filtered data record is placed into the data stream. See DosMonRead for a description of the monitor data record format, the flushing of monitor buffers, and the restrictions on data record consumption by a monitor.

Separate monitor threads from the same application can call DosMonWrite to return filtered data to the same data stream. To protect the data stream during data movement, the monitor dispatcher guarantees that only one thread at a time from a single process can return data to a data stream. Therefore, the application does not have to synchronize calls to DosMonWrite made by its separate threads.

If a monitor thread calls DosMonWrite during monitor termination (for example, DosMonClose has been called from another thread belonging to the same application), it will receive an error return indicating that it cannot return data to the data stream. If a monitor thread is blocked on a call to DosMonWrite when monitor termination begins, it is awakened and receives the same error return. In both cases, the monitor thread must handle the error return code. The application is responsible for the orderly termination of its individual monitor threads.

DosMonClose

When an application no longer needs to monitor data passing through a character device, it must call DosMonClose to remove all monitors that it has previously registered with the device. The parameters for DosMonClose are shown in the table below.

ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³Parameter Description         ³Size                          ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³Device Handle                 ³WORD                          ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

DosMonClose calls on the OS/2 File System to close the application's device handle for monitors by calling DosClose. The file system, in turn, sends a monitor close request to the physical device driver.

The character device driver differentiates a DosClose request from a DosMonClose request by the 08h value specified in the Status field of the request packet. At this time, the physical device driver must call the DevHlp_DeRegister for each of its monitor chains to remove all monitors registered by the application. (The application might have registered monitors with more than one monitor chain for the same device.) On the return from each call to DeRegister, if the monitor chain is empty (that is, there are no more monitors in the monitor chain) and the physical device driver no longer needs to use it, the device driver can (optionally) issue a call to the DevHlp_MonitorCreate with the Delete option to remove the monitor chain.

Note: The physical device driver must receive notification that a monitor process is terminating so that the monitor dispatcher can be called to remove the monitors from the monitor chain. The monitor dispatcher has the responsibility to guarantee an orderly removal of the monitor from the monitor chain with minimal data loss, while maintaining the integrity of data movement through other monitors in the monitor chain.

The OS/2 File System is already aware that a monitor has opened a handle to the device during a previous call to DosMonOpen. When a monitor process terminates (normally or abnormally), all handles opened by that process are closed. The file system notifies the physical device driver that monitor termination is occurring by sending a monitor close request to the physical device driver.

If an application calls DosExit to terminate the process without calling DosMonClose, the file system sends a monitor close request to the physical device driver so that the monitor dispatcher can remove the monitors from all monitor chains.

Guidelines for a Character Device Monitor

       Monitor Buffers
       Monitor Data Records
       Positioning of Monitors in a Monitor Chain
       Monitor Thread Priorities 

Special Considerations for Character Device Monitors

       Performance
           Separate Threads
           Task Synchronization
           I/O Requests
           Data Consumption
           Expected Responses
           Error Handling 
       Monitor Termination 

Well-Behaved Monitor Applications

Monitor Problems and Solutions

       Type-Ahead Characters
       Redirecting Data to Another Device 

Providing Monitor Support in a Character Device Driver

       MonitorCreate
       Register
       MonWrite
       MonFlush
       DeRegister 

Guidelines for a Character Device Driver

       Buffer Requirements
       Code Requirements 

Special Considerations for Character Device Drivers

       Device-Specific Monitor Information
       Performance 

Device Driver Problems