Step 2. Adapting the OEMDONGL.C Source Code

The DDK supplied with the DDK has VxD support for the following IR devices:

If your IR device is not one listed above or is not compatible with one of those devices, then you must modify the OEMDONGL.C source code to support your device and create a new VxD. In order to produce a VxD that works with the generic serial IrFramer to support your device, adapt the OEMDONGL.C sample source code to your dongle hardware, compile it, and link it to DONGLE.LIB and CVXDCTRL.ASM.

Establishing the Microsoft Infrared Communications for Windows 95 Build Environment

The first step in creating your own IrFramer is to establish a build environment. In order to build binary files that are comparable with the current shipping versions, you will need to use the same tools that were used to build the shipping versions. The build environment includes a C Compiler, Assembler, Linker, include files and libraries - all of the tools necessary to build executable modules from the sample source code provided in this DDK.

If you install both the Win32 SDK and Windows 95 DDK on your development system, then you will have all the header files and libraries you need. You also have to install a set of compilers and an assembler.

Follow this sequence of steps in establishing your build environment:

1. Install the compilers and assembler. The following are all necessary: Microsoft Visual C, version 2.x (for 32-bit development), Microsoft Visual C, version 1.5x (for 16-bit development), and Microsoft Assembler, version 6.11c.

2. Next, install the Win32 SDK.

3. Lastly, install the Windows 95 DDK.

Introducing the Sample Source Code

The sample source code for your VxD is in the DDK subdirectory. The source code modules in the DDK subdirectory that you must modify are described in the following table:

File

Description

Comment

OEMDONGL.C

Contains the OEMDongleTable which is an array of DONGLE_TYPE structures that list the supported dongles and their support functions.

Contains the OEMDongleTableLen variable that specifies the number of dongles that support is being added for.

Contains the functions to support initializing the dongle, setting the dongle's speed (from 2400 baud to 115,200 baud), and turning off the dongle.

The functions currently in OEMDONGL.C are for the ACTiSYS 200L dongle, except the content of the OEMDongleTable array and the names of the type_Init, type_SetSpeed, and type_Deinit functions have been changed to highlight the parts of the code you must change. Note that the name of the OEMDongleTable array and the OEMDongleTableLen variable must not be changed. More details about this are given below.

CVXDCTRL.ASM

Wrapper that can be linked with OEMDONGL.C to produce a dynamically loadable VxD.

The sample CVXDCTRL.ASM source code is for the ACTiSYS 200L dongle. You will have to edit this code to establish the name of your VxD.


Editing the OEMDongleTable Array and Registry

To add a dongle type that can be used by the framer, add the dongle type's identifying string and pointers to its type_Init, type_SetSpeed, and type_Deinit functions to the OEMdongleTable array. The sample source code that defines the array in OEMDONGLE.C looks like this:


    DONGLE_TYPE OEMDongleTable[] =
    {
        {"OEM", OEM_Init, OEM_SetSpeed, OEM_Deinit }
    };
        
    U32 OEMDongleTableLen = (sizeof(OEMDongleTable)/sizeof(DONGLE_TYPE));
        

The DONGLE_TYPE structure is defined in _DONGLE.H:


    // Data structure used to hold Dongle information
    typedef struct _DONGLE_TYPE
    {
        char*                  typeName; // Name of dongle in the registry
        IRLAPFRM_DONGLE_INIT   init;     // Pointer to init function
        IRLAPFRM_DONGLE_SET    set;      // Pointer to setSpeed function
        IRLAPFRM_DONGLE_DEINIT deinit;   // Pointer to deinit function
    } DONGLE_TYPE, *PDONGLE_TYPE;

So, for example, if your IR dongle device model is named the REDEYE-88 you could edit the OEMDongleTable array in OEMDONGLE.C to look like this:


    DONGLE_TYPE OEMDongleTable[] =
    {
      {"RED88", RED88_Init, RED88_SetSpeed, RED88_Deinit}
    };

You also have to write the name of your dongle type into the registry. The framer gets the names of the dongle types installed on a Windows 95 computer by reading the registry. To add your own dongle type name to the registry during development, you will have to adapt the INFRARED.INF file shipped with the DDK or use the Regedit utility. Continuing with the example, your dongle type name is "RED88." At the registry path HKEY_LOCAL_MACHINE\Enum\Infrared\Framer add the following key and value:


DongleType="RED88"

You must also add the name of your VxD to the registry. For example, if the name of your VxD is RED88.VXD, then at the registry path HKEY_LOCAL_MACHINE\Enum\Infrared\Framer you must add the following key and value:


SpeedDriver="RED88.VXD"

For information on editing the INFRARED.INF file to accomplish these changes to the registry when your VxD is installed using Setup, see Creating an Installation Diskette and Installing the IR Communications Software.

Adapting the Interface Exposed to the IrFramer

The interface that a specific dongle-type source code module exposes to the generic IrFramer (through the function pointer table in OEMDONGLE.C) can have three functions:

Function

Description

type_Init

Initializes your IR hardware and returns the capabilities mask.

type_SetSpeed

Sets the send and receive speed of your IR hardware and sets VCOMM to handle that speed.

type_Deinit

Powers down or deinitializes your IR hardware.


Using the Available Support Functions

A number of functions are available to the OEMDONGL.C module. You have the option of using the VCOMM functions directly and/or indirectly through the functions listed below. It is strongly recommended that you not use the VCOMM functions directly for two-way communication with the dongle. Use the provided functions wherever applicable. The function prototypes are in _DONGLE.H and are shown below:


//************************************************************************
//
// Function prototypes of utility functions that should be used by
// dongle functions.

// IrLapFrmSetSpeed will set the speed of the UART to the given speed
// using VCOMM calls.

BOOL IrLapFrmSetSpeed(U32 hCom, LM_BAUD_RATE speed);

// IrLapFrmReadChar is used to read a character from the UART using VCOMM calls
// It assumes that events are turned off so it polls. If no character is read in
// in 12 ms it will return FALSE. If a VCOMM error occurs it will return false.
// If it returns TRUE the character read is placed in the variable pointed to by
// c.

BOOL IrLapFrmReadChar(U32 hCom, PU8 c);

// IrLapFrmWriteChar is used to write a character to the UART using VCOMM calls.
// It returns TRUE if successful otherwise it returns FALSE.

BOOL IrLapFrmWriteChar(U32 hCom, U8 c);

// VMM_GetSystemTime returns the number of milliseconds since Windows started. It is
// accurate to 1ms. This is the standard VMM call.

UINT VMM_GetSystemTime( VOID );
Adapting the type_Init Function

The type_Init function is called by the framer to initialize your IR hardware and to get the dongle capabilities masks. When type_Init is called, the hCom (VCOMM handle) will be set for 9600 baud, 8 data bits, no parity, and 1 stop bit. When type_Init returns, the dongle must be active and ready to receive and send data and the VCOMM handle must be set to 9600 baud, 8 data bits, no parity, and 1 stop bit.

If the dongle cannot be initialized type_Init must return IRDA_STATUS_FAILED.

The syntax of the function call is:


BOOL type_Init(
                   U32 hCom, 
                   PDONGLE_CAPABILITIES cap
    )

type_Init assumes

The cap parameter points to the DONGLE_CAPABILITIES structure that type_Init returns to the framer; type_Init can, as an option, set bits in the masks that make up this structure to register Baud Rate, Minimum Turn Around Time, and Number of BOFs capabilities with the framer.

The DONGLE_CAPABILITIES structure is defined in _DONGLE.H and is shown below:


// DONGLE_CAPABILITIES - is a structure that contains the IrDA
    // capabilities a dongle can effect. The order of the elements in 
    // this structure must be the same as those in the IRLAPFRM_CAPABILITIES
    // structure.

    typedef struct
    {
      U32 supportedSpeeds;    // Supported speeds of the dongle
      U32 minTurnAroundTime;  // Min turn around time on the dongle
      U32 additionalBOFs;     // Additional BOFs required by the dongle.
    } DONGLE_CAPABILITIES, *PDONGLE_CAPABILITES;

The meaning of the pattern of bit settings in the three capabilities bit masks is defined fully in Infrared Data Association Serial Infrared Link Access Protocol (IrLAP), but summary tables are presented here.

Baud Rate

The bit settings in the baud rate mask indicate the speed(s) at which the IR device can transmit over the data link:

bit 0 =

2400 bps (LSB, transmitted first)

bit 1 =

9600 bps

bit 2 =

19200 bps

bit 3 =

38400 bps

bit 4 =

57600 bps

bit 5 =

115200 bps

bit 6 =

reserved and must be set to 0

bit 7 =

reserved and must be set to 0


Minimum Turn Around Time

Minimum turn around time is the time delay required by the IR device from the time it receives the last byte from one device until it is ready to receive the first byte from another device.

bit 0 =

10 ms (LSB, transmitted first)

bit 1 =

5 ms

bit 2 =

1 ms

bit 3 =

0.5 ms

bit 4 =

0.1 ms

bit 5 =

0.05 ms

bit 6 =

0.01 ms

bit 7 =

0.005 ms


Number of BOFs

These bit settings indicate the number of additional flags needed at the beginning of every frame to provide a delay at the beginning of each frame for devices with long interrupt latency. The bit settings in this mask depend on the baud rate. See Infrared Data Association Serial Infrared Link Access Protocol (IrLAP) for all the different possible values.

The following shows an example of adapting the OEMDONGLE.C sample source code function OEM_Init. The supportedSpeeds mask is set to support all speeds between 9600 baud and 115.2 baud and is set for a 1 ms turnaround, using the following code:


#define  CRYSTAL_SPEEDMASK  0x3F     /*supported speeds 115.2Kbps->9600 Kbps*/
        #define  CRYSTAL_MINTURN    0x00     /*0 turn around*/
         .
         .
         .
    //*********************************************************************
    BOOL OEM_Init(U32 hCom, PDONGLE_CAPABILITIES cap)
    {
          .
          .
               .

        cap->supportedSpeeds &= CRYSTAL_SPEEDMASK;
          .
               .
               .
    }

Suppose your RED88 dongle only supports 9600, 19200, and 115200 baud. You can change the supportedSpeeds mask to reflect that by changing two lines of the sample code:


    #define RED88_SPEEDMASK      0x00000026
        .
          .
               .

        cap->supportedSpeeds &= RED88_SPEEDMASK;
          .
               .
               .
Adapting the type_SetSpeed Function

The type_SetSpeed function is called by the framer IRLAPFRM_SetSpeed function to set the send and receive speed of your IR hardware. type_SetSpeed must also set VCOMM to handle the new speed because IRLAPFRM_SetSpeed does not do that.

The syntax of the type_SetSpeed function call is:


BOOL type_SetSpeed(
                      U32 hCom, 
                      LM_BAUD_RATE speed
   )

type_SetSpeed can send and receive characters with no interference from the IR framer because IRLAPFRM_SetSpeed disables VCOMM event callbacks before it calls type_SetSpeed.

type_SetSpeed can also assume that the framer will not reset the VCOMM speed setting. Therefore, when type_SetSpeed is called, the VCOMM speed setting is either the same as the last time type_SetSpeed set it, or 9600 baud immediately after a call to type_Init.

When type_SetSpeed returns, the framer assumes it can start sending or receiving data at the new speed and restores the VCOMM event callbacks. If it fails to set the IR device speed or the VCOMM speed setting, type_SetSpeed must return IRDA_STATUS_FAILED.

It is not particularly useful to make up an example here for the hypothetical RED88 dongle device. The convention that notifies each particular dongle device of a speed change differs from device to device. Two things to notice about the sample code, however, are:

Adapting the type_Deinit Function

The type_Deinit function is called to power down or otherwise deactivate your hardware. It is called by the framer just before it calls VCOMM_CloseComm to close the port.

The type_Deinit function can send and receive characters with no interference from the IR framer because VCOMM event callbacks are disabled before the call to the dongle function.

The syntax of the type_Deinit function call is:


BOOL type_Deinit(
                      U32 hCom
     )

The OEM_Deinit function in OEMDONGL.C (which uses the Crystal chip in the ACTiSYS 200L as an IR device) does the following: