The PortIO95 Parallel Port Interface

Sample Source: readstat.c

/* ****************************************************************************
 * readstat.c - This file provides example code illustrating the use of the
 *              PortIO95 VxD. Its function is to read the status register
 *              (pins 15, 13, 12, 10, 11) of the specified LPT port. The status
 *              register of the parallel port is always read_only.  If you hook
 *              up a series of switches and 220 ohm resistors as shown below, you
 *              should be able to affect the results reported by this program.
 *
 *        Pins on the Parallel Port D connector
 *            15 13 12 10 11             18
 *            |  |  |  |  |              |
 *            |  |  |  |  |              |      Note: \ is a dip switch
 *            \  \  \  \  \              |            Z is a 220 ohm resistor
 *            |  |  |  |  |              |
 *            |  |  |  |  |              |      Note: Pin 15 is S3, Pin 11 is S7
 *            Z  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"

/* 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 */

/* 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);

    /* now lets read pin 15 as input */
    retval=DeviceIoControl(hDevice, PORTIO_READPIN15, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READPIN15");
    if (cOutData == '\0') printf("Pin 15 is LOW\n");
       else printf("Pin 15 is HIGH\n");

    /* now lets read pin 13 as input */
    retval=DeviceIoControl(hDevice, PORTIO_READPIN13, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READPIN13");
    if (cOutData == '\0') printf("Pin 13 is LOW\n");
       else printf("Pin 13 is HIGH\n");
       
    /* now lets read pin 12 as input */
    retval=DeviceIoControl(hDevice, PORTIO_READPIN12, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READPIN12");
    if (cOutData == '\0') printf("Pin 12 is LOW\n");
       else printf("Pin 12 is HIGH\n");

    /* now lets read pin 10 as input */
    retval=DeviceIoControl(hDevice, PORTIO_READPIN10, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READPIN10");
    if (cOutData == '\0') printf("Pin 10 is LOW\n");
       else printf("Pin 10 is HIGH\n");

    /* now lets read pin 11 as input */
    retval=DeviceIoControl(hDevice, PORTIO_READPIN11, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READPIN11");
    if (cOutData == '\0') printf("Pin 11 is LOW\n");
       else printf("Pin 11 is HIGH\n");

    /* now lets read the status register in raw mode - we get exactly what the
     * LPT port thinks it has there - the VxD does nothing but read.
     * Note that pins: 15=bit3, 13=Bit4, 12=Bit5, 10=Bit6, 11=Bit7. Bit 7 is
     * hardware NOT'ted by the port so will be the opposite to the true state */
    retval=DeviceIoControl(hDevice, PORTIO_READSREGRAW, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READSREGRAW");
    printf("The raw S Register is: 0x%X hex\n",cOutData);

    /* now lets read the status register in cooked mode. This call is designed
     * to provide a logical 4 bit input mechanism. Thus the values of the
     * Status Register bits are shifted around and flipped (where necessary)
     * by the PortIO95 VxD so that a nice 4 bit nibble is composed and returned
     * to the calling program.
     *
     * Note that pin: 15=bit0, 13=Bit1, 12=Bit2, 11=Bit3 in the returned byte.
     * Bit 3 (pin 11) is logically re-NOT'ted by the VxD and so the returned
     * value will reflect the true pin state. All unused bits will be 0.
     */
     retval=DeviceIoControl(hDevice, PORTIO_READSREG, NULL, 0, &cOutData, sizeof(cOutData), NULL, NULL);
    if (!retval) Handle_Error("PORTIO_READSREG");
    printf("The cooked S Register is: 0x%X hex\n",cOutData);

    /* unset our port, this is desireable 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]