#!/usr/bin/env python
# parallel port access using the ppdev driver

import sys
import struct
import fcntl
import os

#----
# Generated by h2py 0.1.1 from <linux/ppdev.h>,
# then cleaned up a bit by Michael P. Ashton and then a gain by chris ;-)
# Changes for Python2.2 support (c) September 2004 Alex.Perry@qm.com


def sizeof(type): return struct.calcsize(type)
def _IOC(dir, type, nr, size):  return int((dir << _IOC_DIRSHIFT ) | (type << _IOC_TYPESHIFT ) |\
                                       (nr << _IOC_NRSHIFT ) | (size << _IOC_SIZESHIFT))
def _IO(type, nr):      return _IOC(_IOC_NONE,  type, nr, 0)
def _IOR(type,nr,size): return _IOC(_IOC_READ,  type, nr, sizeof(size))
def _IOW(type,nr,size): return _IOC(_IOC_WRITE, type, nr, sizeof(size))

_IOC_SIZEBITS   = 14
_IOC_SIZEMASK   = (1 << _IOC_SIZEBITS ) - 1
_IOC_NRSHIFT    = 0
_IOC_NRBITS     = 8
_IOC_TYPESHIFT  = _IOC_NRSHIFT + _IOC_NRBITS
_IOC_TYPEBITS   = 8
_IOC_SIZESHIFT  = _IOC_TYPESHIFT + _IOC_TYPEBITS
IOCSIZE_MASK    = _IOC_SIZEMASK << _IOC_SIZESHIFT
IOCSIZE_SHIFT   = _IOC_SIZESHIFT

# Python 2.2 uses a signed int for the ioctl() call, so ...
if ( sys.version_info[0] < 3 ) or ( sys.version_info[1] < 3 ):
 _IOC_WRITE      =  1
 _IOC_READ       = -2
 _IOC_INOUT      = -1
else:
 _IOC_WRITE      =  1
 _IOC_READ       =  2
 _IOC_INOUT      =  3

_IOC_DIRSHIFT   = _IOC_SIZESHIFT + _IOC_SIZEBITS
IOC_INOUT       = _IOC_INOUT << _IOC_DIRSHIFT
IOC_IN          = _IOC_WRITE << _IOC_DIRSHIFT
IOC_OUT         = _IOC_READ << _IOC_DIRSHIFT

_IOC_NONE       = 0
PP_IOCTL        = ord('p')
PPCLAIM         = _IO(PP_IOCTL,  0x8b)
PPCLRIRQ        = _IOR(PP_IOCTL, 0x93, 'i')

PPDATADIR       = _IOW(PP_IOCTL, 0x90, 'i')
PPEXCL          = _IO(PP_IOCTL,  0x8f)
PPFCONTROL      = _IOW(PP_IOCTL, 0x8e, 'BB')
PPGETFLAGS      = _IOR(PP_IOCTL, 0x9a, 'i')
PPGETMODE       = _IOR(PP_IOCTL, 0x98, 'i')
PPGETMODES      = _IOR(PP_IOCTL, 0x97, 'I')
PPGETPHASE      = _IOR(PP_IOCTL, 0x99, 'i')
PPGETTIME       = _IOR(PP_IOCTL, 0x95, 'll')
PPNEGOT         = _IOW(PP_IOCTL, 0x91, 'i')
PPRCONTROL      = _IOR(PP_IOCTL, 0x83, 'B')
PPRDATA         = _IOR(PP_IOCTL, 0x85, 'B')
#'OBSOLETE__IOR' undefined in 'PPRECONTROL'
PPRELEASE       = _IO(PP_IOCTL,  0x8c)
#'OBSOLETE__IOR' undefined in 'PPRFIFO'
PPRSTATUS       = _IOR(PP_IOCTL, 0x81, 'B')
PPSETFLAGS      = _IOW(PP_IOCTL, 0x9b, 'i')
PPSETMODE       = _IOW(PP_IOCTL, 0x80, 'i')
PPSETPHASE      = _IOW(PP_IOCTL, 0x94, 'i')
PPSETTIME       = _IOW(PP_IOCTL, 0x96, 'll')
PPWCONTROL      = _IOW(PP_IOCTL, 0x84, 'B')
PPWCTLONIRQ     = _IOW(PP_IOCTL, 0x92, 'B')
PPWDATA         = _IOW(PP_IOCTL, 0x86, 'B')
#'OBSOLETE__IOW' undefined in 'PPWECONTROL'
#'OBSOLETE__IOW' undefined in 'PPWFIFO'
#'OBSOLETE__IOW' undefined in 'PPWSTATUS'
PPYIELD         = _IO(PP_IOCTL, 0x8d)
PP_FASTREAD     = 1 << 3
PP_FASTWRITE    = 1 << 2
PP_W91284PIC    = 1 << 4
PP_FLAGMASK     = PP_FASTWRITE | PP_FASTREAD | PP_W91284PIC
PP_MAJOR        = 99
_ASMI386_IOCTL_H= None
_IOC_DIRBITS    = 2
_IOC_DIRMASK    = (1 << _IOC_DIRBITS) - 1
_IOC_NRMASK     = (1 << _IOC_NRBITS) - 1
_IOC_TYPEMASK   = (1 << _IOC_TYPEBITS ) - 1

def _IOC_DIR(nr):       return (nr >> _IOC_DIRSHIFT)  & _IOC_DIRMASK
def _IOC_NR(nr):        return (nr >> _IOC_NRSHIFT)   & _IOC_NRMASK
def _IOC_SIZE(nr):      return (nr >> _IOC_SIZESHIFT) & _IOC_SIZEMASK
def _IOC_TYPE(nr):      return (nr >> _IOC_TYPESHIFT) & _IOC_TYPEMASK
def _IOWR(type, nr, size): return _IOC(_IOC_READ | _IOC_WRITE, type, nr , sizeof(size))

__ELF__         = 1
__i386          = 1
__i386__        = 1
__linux         = 1
__linux__       = 1
__unix          = 1
__unix__        = 1
i386            = 1
linux           = 1
unix            = 1

#-------- Constants from <linux/parport.h>

PARPORT_CONTROL_STROBE  = 0x1
PARPORT_CONTROL_AUTOFD  = 0x2
PARPORT_CONTROL_INIT    = 0x4
PARPORT_CONTROL_SELECT  = 0x8
PARPORT_STATUS_ERROR    = 8
PARPORT_STATUS_SELECT   = 0x10
PARPORT_STATUS_PAPEROUT = 0x20
PARPORT_STATUS_ACK      = 0x40
PARPORT_STATUS_BUSY     = 0x80

IEEE1284_MODE_NIBBLE    = 0
IEEE1284_MODE_BYTE      = 1
IEEE1284_MODE_COMPAT    = 1<<8
IEEE1284_MODE_BECP      = 1<<9
IEEE1284_MODE_ECP       = 1<<4
IEEE1284_MODE_ECPRLE    = IEEE1284_MODE_ECP | (1<<5)
IEEE1284_MODE_ECPSWE    = 1<<10
IEEE1284_MODE_EPP       = 1<<6
IEEE1284_MODE_EPPSL     = 1<<11
IEEE1284_MODE_EPPSWE    = 1<<12
IEEE1284_DEVICEID       = 1<<2
IEEE1284_EXT_LINK       = 1<<14

IEEE1284_ADDR           = 1<<13
IEEE1284_DATA           = 0

PARPORT_EPP_FAST        = 1
PARPORT_W91284PIC       = 2
#----

class Parallel:
    """Class for controlling the pins on a parallel port

    This class provides bit-level access to the pins on a PC parallel
    port.  It is primarily designed for programs which must control
    special circuitry - most often non-IEEE-1284-compliant devices
    other than printers - using 'bit-banging' techniques.

    The current implementation makes ioctl() calls to the Linux ppdev
    driver, using the Python fcntl library.  It might be rewritten in
    C for extra speed.  This particular implementation is written for
    Linux; all of the upper-level calls can be ported to Windows as
    well.

    On Linux, the ppdev device driver, from the Linux 2.4 parallel
    port subsystem, is used to control the parallel port hardware.
    This driver must be made available from a kernel compile.  The
    option is called "Support user-space parallel-port drivers".  When
    using the module, be sure to unload the lp module first: usually
    the lp module claims exclusive access to the parallel port, and if
    it is loaded, this class will fail to open the parallel port file,
    and throw an exception.

    The primary source of information about the Linux 2.4 parallel
    port subsystem is Tim Waugh's documentation, the source for which
    is available in the kernel tree.  This document (called,
    appropriately enough, "The Linux 2.4 Parallel Port Subsystem"),
    thoroughly describes the parallel port drivers and how to use
    them.

    This class provides a method for each of the ioctls supported by
    the ppdev module.  The ioctl methods are named, in uppercase, the
    same as the ioctls they invoke.  The documentation for these
    methods was taken directly from the documentation for their
    corresponding ioctl, and modified only where necessary.

    Unless you have special reason to use the Linux ioctls, you should
    use instead the upper-level functions, which are named in
    lowerCase fashion and should be portable between Linux and
    Windows.  This way, any code you write for this class will (or
    should) also work with the Windows version of this class.
    
    """
    def __init__(self, port = 0):
        if type(port) == type(""):
            self.device = port
        else:
            self.device = "/dev/parport%d" % port
        self._fd = None
        self._fd = os.open(self.device, os.O_RDWR)
        try:
            self.PPEXCL()
            self.PPCLAIM()
            self.setDataDir(1)
            self.setData(0)
        except IOError:
            os.close(self._fd)
            self._fd = None
            raise

    def __del__(self):
        if self._fd is not None:
            self.PPRELEASE()
            os.close(self._fd)

    def timevalToFloat(self, timeval):
        t=struct.unpack('ll', timeval)
        return t[0] + (t[1]/1000000.0)

    def floatToTimeval(self, time):
        sec = int(time)
        usec = int(time*1000000.0)
        return struct.pack('ll', sec, usec)

    def PPCLAIM(self):
        """
        Claims access to the port. As a user-land device driver
        writer, you will need to do this before you are able to
        actually change the state of the parallel port in any
        way. Note that some operations only affect the ppdev driver
        and not the port, such as PPSETMODE; they can be performed
        while access to the port is not claimed.
        """
        fcntl.ioctl(self._fd, PPCLAIM)

    def PPEXCL(self):
        """
        Instructs the kernel driver to forbid any sharing of the port
        with other drivers, i.e. it requests exclusivity. The PPEXCL
        command is only valid when the port is not already claimed for
        use, and it may mean that the next PPCLAIM ioctl will fail:
        some other driver may already have registered itself on that
        port.

        Most device drivers don't need exclusive access to the
        port. It's only provided in case it is really needed, for
        example for devices where access to the port is required for
        extensive periods of time (many seconds).

        Note that the PPEXCL ioctl doesn't actually claim the port
        there and then---action is deferred until the PPCLAIM ioctl is
        performed.
        """
        fcntl.ioctl(self._fd, PPEXCL)

    def PPRELEASE(self):
        """
        Releases the port. Releasing the port undoes the effect of
        claiming the port. It allows other device drivers to talk to
        their devices (assuming that there are any).
        """
        fcntl.ioctl(self._fd, PPRELEASE)

    def PPYIELD(self):
        """
        Yields the port to another driver. This ioctl is a kind of
        short-hand for releasing the port and immediately reclaiming
        it. It gives other drivers a chance to talk to their devices,
        but afterwards claims the port back. An example of using this
        would be in a user-land printer driver: once a few characters
        have been written we could give the port to another device
        driver for a while, but if we still have characters to send to
        the printer we would want the port back as soon as possible.

        It is important not to claim the parallel port for too long,
        as other device drivers will have no time to service their
        devices. If your device does not allow for parallel port
        sharing at all, it is better to claim the parallel port
        exclusively (see PPEXCL).
        """
        fcntl.ioctl(self._fd, PPYIELD)

    def PPNEGOT(self, mode):
        """
        Performs IEEE 1284 negotiation into a particular
        mode. Briefly, negotiation is the method by which the host and
        the peripheral decide on a protocol to use when transferring
        data.

        An IEEE 1284 compliant device will start out in compatibility
        mode, and then the host can negotiate to another mode (such as
        ECP).

        The 'mode' parameter should be one of the following constants
        from PPDEV:

        - IEEE1284_MODE_COMPAT
        - IEEE1284_MODE_NIBBLE
        - IEEE1284_MODE_BYTE
        - IEEE1284_MODE_EPP
        - IEEE1284_MODE_ECP

        The PPNEGOT ioctl actually does two things: it performs the
        on-the-wire negotiation, and it sets the behaviour of
        subsequent read/write calls so that they use that mode (but
        see PPSETMODE).
        """
        fcntl.ioctl(self._fd, PPNEGOT, struct.pack('i', mode))

    def PPSETMODE(self, mode):
        """
        Sets which IEEE 1284 protocol to use for the read and write
        calls.

        The 'mode' parameter should be one of the following constants
        from PPDEV:

        - IEEE1284_MODE_COMPAT
        - IEEE1284_MODE_NIBBLE
        - IEEE1284_MODE_BYTE
        - IEEE1284_MODE_EPP
        - IEEE1284_MODE_ECP
        """
        fcntl.ioctl(self._fd, PPSETMODE, struct.pack('i', mode))

    def PPGETMODE(self):
        """
        Retrieves the IEEE 1284 mode being used for read and
        write.  The return value is one of the following constants
        from PPDEV:

        - IEEE1284_MODE_COMPAT
        - IEEE1284_MODE_NIBBLE
        - IEEE1284_MODE_BYTE
        - IEEE1284_MODE_EPP
        - IEEE1284_MODE_ECP
        """
        ret = struct.pack('i', 0)
        ret = fcntl.ioctl(self._fd, PPGETMODE, ret)
        return struct.unpack('i', ret)[0]

    def PPGETTIME(self):
        """
        Retrieves the time-out value. The read and write calls will
        time out if the peripheral doesn't respond quickly enough. The
        PPGETTIME ioctl retrieves the length of time that the
        peripheral is allowed to have before giving up.

        Returns the timeout value in seconds as a floating-point value.
        """
        ret = struct.pack('ll', 0, 0)
        ret = fcntl.ioctl(self._fd, PPGETTIME, ret)
        return timevalToFloat(ret)

    def PPSETTIME(self, time):
        """
        Sets the time-out (see PPGETTIME for more information).
        'time' is the new time-out in seconds; floating-point values
        are acceptable.
        """
        fcntl.ioctl(self._fd, PPSETTIME, floatToTimeval(time))

    def PPGETMODES(self):
        """
        Retrieves the capabilities of the hardware (i.e. the modes
        field of the parport structure).
        """
        raise NotImplementedError

    def PPSETFLAGS(self):
        """
        Sets flags on the ppdev device which can affect future I/O
        operations. Available flags are:

        - PP_FASTWRITE
        - PP_FASTREAD
        - PP_W91284PIC
        """
        raise NotImplementedError

    def PPWCONTROL(self, lines):
        """
        Sets the control lines.  The 'lines' parameter is a bitwise OR
        of the following constants from PPDEV:

        - PARPORT_CONTROL_STROBE
        - PARPORT_CONTROL_AUTOFD
        - PARPORT_CONTROL_INIT
        - PARPORT_CONTROL_SELECT
        """
        fcntl.ioctl(self._fd, PPWCONTROL, struct.pack('B', lines))

    def PPRCONTROL(self):
        """
        Returns the last value written to the control register, in the
        form of an integer, for which each bit corresponds to a control
        line (although some are unused).

        This doesn't actually touch the hardware; the last value
        written is remembered in software. This is because some
        parallel port hardware does not offer read access to the
        control register.

        The control lines bits are defined by the following constants
        from PPDEV:

        - PARPORT_CONTROL_STROBE
        - PARPORT_CONTROL_AUTOFD
        - PARPORT_CONTROL_SELECT
        - PARPORT_CONTROL_INIT
        """
        ret = struct.pack('B',0)
        ret = fcntl.ioctl(self._fd, PPRCONTROL, ret)
        return struct.unpack('B', ret)[0]

    def PPFCONTROL(self, mask, val):
        """
        Frobs the control lines. Since a common operation is to change
        one of the control signals while leaving the others alone, it
        would be quite inefficient for the user-land driver to have to
        use PPRCONTROL, make the change, and then use PPWCONTROL. Of
        course, each driver could remember what state the control
        lines are supposed to be in (they are never changed by
        anything else), but in order to provide PPRCONTROL, ppdev must
        remember the state of the control lines anyway.

        The PPFCONTROL ioctl is for "frobbing" control lines, and is
        like PPWCONTROL but acts on a restricted set of control
        lines. The ioctl parameter is a pointer to a struct
        ppdev_frob_struct:
        
        struct ppdev_frob_struct {
            unsigned char mask;
            unsigned char val;
        };

        The mask and val fields are bitwise ORs of control line names
        (such as in PPWCONTROL). The operation performed by PPFCONTROL
        is:

        new_ctr = (old_ctr & ~mask) | val

        In other words, the signals named in mask are set to the
        values in val.
        """
        fcntl.ioctl(self._fd, PPFCONTROL, struct.pack('BB', mask, val))

    def PPRSTATUS(self):
        """
        Returns an unsigned char containing bits set for each status
        line that is set (for instance, PARPORT_STATUS_BUSY). The
        ioctl parameter should be a pointer to an unsigned char.
        """
        ret = struct.pack('B',0)
        ret = fcntl.ioctl(self._fd, PPRSTATUS, ret)
        return struct.unpack('B', ret)[0]

    def PPDATADIR(self, out):
        """
        Controls the data line drivers. Normally the computer's
        parallel port will drive the data lines, but for byte-wide
        transfers from the peripheral to the host it is useful to turn
        off those drivers and let the peripheral drive the
        signals. (If the drivers on the computer's parallel port are
        left on when this happens, the port might be damaged.)
        This is only needed in conjunction with PPWDATA or PPRDATA.

        The 'out' parameter indicates the desired port direction.  If
        'out' is true or non-zero, the drivers are turned on (forward
        direction); otherwise, the drivers are turned off (reverse
        direction).
        """
        if out:
            msg=struct.pack('i',0)
        else:
            msg=struct.pack('i',1)
        fcntl.ioctl(self._fd, PPDATADIR, msg)

    def PPWDATA(self, byte):
        """
        Sets the data lines (if in forward mode). The ioctl parameter
        is a pointer to an unsigned char.
        """
        fcntl.ioctl(self._fd, PPWDATA,struct.pack('B',byte))

    def PPRDATA(self):
        """
        Reads the data lines (if in reverse mode). The ioctl parameter
        is a pointer to an unsigned char.
        """
        ret=struct.pack('B',0)
        ret=fcntl.ioctl(self._fd, PPRDATA,ret)
        return struct.unpack('B',ret)[0]

    def PPCLRIRQ(self):
        """
        Returns the current interrupt count, and clears it.  The ppdev
        driver keeps a count of interrupts as they are triggered.
        """
        ret=struct.pack('i',0)
        ret=fcntl.ioctl(self._fd, PPCLRIRQ,ret)
        return struct.unpack('i',ret)[0]

    def PPWCTLONIRQ(self, lines):
        """
        Set a trigger response. Afterwards when an interrupt is
        triggered, the interrupt handler will set the control lines as
        requested. The ioctl parameter is a pointer to an unsigned
        char, which is interpreted in the same way as for PPWCONTROL.

        The reason for this ioctl is simply speed. Without this ioctl,
        responding to an interrupt would start in the interrupt
        handler, switch context to the user-land driver via poll or
        select, and then switch context back to the kernel in order to
        handle PPWCONTROL. Doing the whole lot in the interrupt
        handler is a lot faster.
        """
        fcntl.ioctl(self._fd, PPWCTLONIRQ,struct.pack('B',lines))

    #data lines
##    def data(self):
##        """Returns the states of the data bus line drivers (pins 2-9)"""
##        return self._data

    def setDataDir(self,out):
        """Activates or deactivates the data bus line drivers (pins 2-9)"""
        self._dataDir = out
        self.PPDATADIR(out)

    def dataDir(self):
        """Returns true if the data bus line drivers are on (pins 2-9)"""
        return self._dataDir

    #control lines
##    def strobe(self):
##        """Returns the state of the nStrobe output (pin 1)"""
##        return (self.PPRCONTROL()&PARPORT_CONTROL_STROBE)==0

    def setDataStrobe(self, level):
        """Sets the state of the nStrobe output (pin 1)"""
        if level:
            self.PPFCONTROL(PARPORT_CONTROL_STROBE, 0)
        else:
            self.PPFCONTROL(PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE)

##    def autoFd(self):
##        """Returns the state of the nAutoFd output (pin 14)"""
##        return (self.PPRCONTROL()&PARPORT_CONTROL_AUTOFD)==0

    def setAutoFeed(self, level):
        """Sets the state of the nAutoFd output (pin 14)"""
        if level:
            self.PPFCONTROL(PARPORT_CONTROL_AUTOFD, 0)
        else:
            self.PPFCONTROL(PARPORT_CONTROL_AUTOFD, PARPORT_CONTROL_AUTOFD)

##    def init(self):
##        """Returns the state of the nInit output (pin 16)"""
##        return (self.PPRCONTROL()&PARPORT_CONTROL_INIT)!=0

    def setInitOut(self, level):
        """Sets the state of the nInit output (pin 16)"""
        if level:
            self.PPFCONTROL(PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT)
        else:
            self.PPFCONTROL(PARPORT_CONTROL_INIT, 0)

##    def selectIn(self):
##        """Returns the state of the nSelectIn output (pin 17)"""
##        return (self.PPRCONTROL()&PARPORT_CONTROL_SELECT)==0

    def setSelect(self,level):
        """Sets the state of the nSelectIn output (pin 17)"""
        if level:
            self.PPFCONTROL(PARPORT_CONTROL_SELECT, 0)
        else:
            self.PPFCONTROL(PARPORT_CONTROL_SELECT, PARPORT_CONTROL_SELECT)

    def setData(self,d):
        """Sets the states of the data bus line drivers (pins 2-9)"""
        self._data=d
        return self.PPWDATA(d)
    
    def getData(self):
        """Gets the states of the data bus line (pin 2-9)"""
        return self.PPRDATA()

    # status lines
    def getInError(self):
        """Returns the level on the nFault pin (15)"""
        return (self.PPRSTATUS() & PARPORT_STATUS_ERROR) != 0

    def getInSelected(self):
        """Returns the level on the Select pin (13)"""
        return (self.PPRSTATUS() & PARPORT_STATUS_SELECT) != 0

    def getInPaperOut(self):
        """Returns the level on the paperOut pin (12)"""
        return (self.PPRSTATUS() & PARPORT_STATUS_PAPEROUT) != 0

    def getInAcknowledge(self):
        """Returns the level on the nAck pin (10)"""
        return (self.PPRSTATUS() & PARPORT_STATUS_ACK) != 0

    def getInBusy(self):
        """Returns the level on the Busy pin (11)"""
        return (self.PPRSTATUS() & PARPORT_STATUS_BUSY) == 0

