The PortIO95 Parallel Port Interface

Sample Source: writectl.c

/* ****************************************************************************
 * writectl.c - This file provides example code illustrating the use of the
 *              PortIO95 VxD. Its function is to write the ctl register
 *              (pins 1, 14, 16, 17) of the specified LPT port. The ctl
 *              register of the parallel port is read/write.  This sample
 *              script only illustrates writing the ctl port. If you hook
 *              up a series of LED's and 330 ohm resistors as shown below, you
 *              should be able see this program cycle the LEDS on and off
 *
 *        Pins on the Parallel Port D connector
 *            1  14 16 17                18
 *            |  |  |  |                 |
 *            |  |  |  |                 |      Note: V is a LED Diode
 *            V  V  V  V                 |            Z is a 330 ohm resistor
 *            |  |  |  |                 |
 *            |  |  |  |                 |      Note: Pin 1  is C0, Pin 17 is C3
 *            Z  Z  Z  Z                 |            Pin 18 is Gnd
 *            |  |  |  |                 |
 *            ----------------------------
 *
 *              As written, this program compiles cleanly under Visual C++ 4.0 
 *              using the command line compiler. It is designed to work only
 *              with the PortIO95 parallel port handler VxD
 *              
 * Note: This file is best viewed with tab stops of 4
 *
 * DISCLAIMER !!!
 * There is no warranty - you use PortIO95 entirely at your own risk.  Net 2000 Ltd. does
 * not warrant PortIO95's suitability for any purpose, does not guarantee PortIO95's
 * uninterrupted functionality, or even its functionality. Net 2000 Ltd. is not liable
 * for any damage or loss that may occur to you, your computer or the things that your
 * computer is controlling.
 *
 * NOTE: This program uses LPT1 by default. See the variable cPortToUse below to change this.
 *
 * See the PortIO95 documentation and FAQ at http://ds.dial.pipex.com/town/close/ec63 for
 * more information.
 *
 * Copyright (c) 1997 Net 2000 Ltd.
 */
 
#include 
#include 
#include 
#include 
#include "portio95.h"

#define PAUSETIME 250    /* led on time in milli seconds */

/* function prototypes */
void Handle_Error(char *);

/* ##### IMPORTANT ##### Change this to the port you wish to use */
char cPortToUse='1';     /* set it for '1'=LPT1, '2'=LPT2, '3'=LPT3 */
char cOutData;           /* use this byte to get data from PortIO95 */
char cInData;            /* use this byte to get data from PortIO95 */

/* global variables */
HANDLE        hDevice;

void main(int ac, char* av[])
    {
    BOOL    retval;
    int     i;
    DWORD    err;

    /* Load the name of the vxd in here where we can pass it as a pointer
     * Note that the format is really "\\.\VXDNAME.VXD" but we have to
     * escape the back slashes with more back slashes because of the
     * special significance the backslash has in C */
    const PCHAR VxDName = "\\\\.\\PORTIO95.VXD";
    printf("\n");
    printf("Preparing to Dynamically Load VxD ->%s\n",VxDName);

    /* the VxD opens just like a regular file. Windows will look for it as follows:
     *   * if it has an .VXD extension
     *     - current directory
     *     - windows directory
     *     - on the path (the autoexec.bat one that win95 sees when it starts)
     *   * if there is no .VXD extension
     *     - in the registry under the KnownVxD's Key
     * see [HAZZAH 227]. The FILE_FLAG_DELETE_ON_CLOSE will cause the VxD to
     * be dynamically removed when the program ends. */
    hDevice = CreateFile(VxDName, 0,0,0,CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0);

    /* By now the PortIO95 VxD should be loaded - lets check */
    if (hDevice == INVALID_HANDLE_VALUE)
        {
        /* Get the Last Error Value see also [PortIO95.doc, Appendix A] */
        err = GetLastError();
           printf("Could Not Load VxD, error=%08lx\n", err );

        /* There is one error we have to handle carefully. It implies that
         * the PortIO95 VxD was found ok but didn't handle the dyamic
         * loading properly. This error shouldn't happen. But if it
         * does we cope with it here. We dynamically unload the vxd
         * before we exit. NOTE there is no .VXD extension on this call
         * otherwise you really do delete the VXD file rather than just
         * forcing an unload. */
        if (err == ERROR_NOT_SUPPORTED) DeleteFile("\\\\.\\PORTIO95");
         exit(1);
        }

    /* now lets set the PortIO95 Vxd to use an LPT for its Input and output */
    retval=DeviceIoControl(hDevice, PORTIO_SETPORT, &cPortToUse, sizeof(cPortToUse), NULL, 0, NULL, NULL);
    if (!retval) Handle_Error("PORTIO_SETPORT");
    printf("PortIO95 set to use LPT%c\n",cPortToUse);

    /* In order to write from the LPT ports control register we
     * must first set the pins up for output. This is required
     * due to the design of the PC LPT port. PortIO95 offers
     * the ability to mix and match the pins in the control port
     * as input and output. - just make calls like:
     * PORTIO_SETPIN14INPUT or PORTIO_SETPIN1OUTPUT
     * If you try to write to a pin that is set as an input or
     * vice-versa an error will be returned. There are also
     * functions to set the entire register as input or output.
     * We use this in the example below. Note that setting the
     * control port up for output has the effect of causing the
     * pins to present a logical low (until they are specifically
     * set high) to any equipment reading the pins */

    retval=DeviceIoControl(hDevice, PORTIO_SET_PINS_1_14_16_17_AS_OUTPUT, NULL, 0, NULL, 0, NULL, NULL);
    if (!retval) Handle_Error("PORTIO_SET_PINS_1_14_16_17_AS_OUTPUT");

    /* now lets set pin1 high then low */
    retval=DeviceIoControl(hDevice, PORTIO_PIN1HIGH, NULL, 0, NULL, 0, NULL, NULL);
    Sleep(PAUSETIME);        /* wait for a short time */
    retval=DeviceIoControl(hDevice, PORTIO_PIN1LOW, NULL, 0, NULL, 0, NULL, NULL);
    
    /* now lets set pin14 high then low */
    retval=DeviceIoControl(hDevice, PORTIO_PIN14HIGH, NULL, 0, NULL, 0, NULL, NULL);
    Sleep(PAUSETIME);        /* wait for a short time */
    retval=DeviceIoControl(hDevice, PORTIO_PIN14LOW, NULL, 0, NULL, 0, NULL, NULL);
    
    /* now lets set pin16 high then low */
    retval=DeviceIoControl(hDevice, PORTIO_PIN16HIGH, NULL, 0, NULL, 0, NULL, NULL);

    Sleep(PAUSETIME);        /* wait for a short time */
    retval=DeviceIoControl(hDevice, PORTIO_PIN16LOW, NULL, 0, NULL, 0, NULL, NULL);
    
    /* now lets set pin17 high then low */
    retval=DeviceIoControl(hDevice, PORTIO_PIN17HIGH, NULL, 0, NULL, 0, NULL, NULL);
    Sleep(PAUSETIME);        /* wait for a short time */
    retval=DeviceIoControl(hDevice, PORTIO_PIN17LOW, NULL, 0, NULL, 0, NULL, NULL);

    /* now lets write the ctl register in raw mode - we put (the low nibble)
     * of the byte we send right into the parallel ports control reg 
     * Note that pins: 1=bit0, 14=Bit1, 16=Bit2, 17=Bit3. Bits 0,1,3 are
     * hardware NOT'ted by the port so will be the opposite to the state set
     * ie 0xE will turn bits 0 and 2 on */
    cInData=0xE;     
    retval=DeviceIoControl(hDevice, PORTIO_WRITECREGRAW, &cInData, sizeof(cInData), NULL, 0,  NULL, NULL);
    if (!retval) Handle_Error("PORTIO_WRITECREGRAW");

    Sleep(PAUSETIME*4);        /* wait for a short time */

    /* now lets write a nibble out to the ctl register in cooked mode.
     * This call is designed to simplify the matter by setting the
     * pins to the logical values you provide. Basically PortIO95 does
     * some bit twiddling before writing to the ctl port. 
     *
     * Note that pin: 1=bit0, 14=Bit1, 16=Bit2, 17=Bit3 in the input byte.
     * Bits  0,1,3 are logically NOT'ted by the VxD and so the
     * true pin states will reflect the logical state of the nibble.
     * ie 0xA will turn bits 1 and 3 on */
    cInData=0xA;     
     retval=DeviceIoControl(hDevice, PORTIO_SEND_BYTE_TO_PINS1_14_16_17, &cInData, sizeof(cInData), NULL, 0,  NULL, NULL);
    if (!retval) Handle_Error("PORTIO_SEND_BYTE_TO_PINS1_14_16_17");

    /* unset our port, this is desirable as it resets things */
    retval=DeviceIoControl(hDevice, PORTIO_UNSETPORT, NULL, 0, NULL, 0, NULL, NULL);

    CloseHandle( hDevice );
    }

/* ********************************************************************
 * Handle_Error - a simple function to print out errors for us
 *               Saves having to put this code after every call
 *
 */
void Handle_Error(char * szErrStr)
        {
        printf("%s DeviceIoControl failed, error=%d\n", szErrStr, GetLastError() );
        exit (1);
        }
    

[Previous] [PortIO95 Home][PortIO95 Source Home] [Next]