i am using an x86 processor. the interface used to connect to the printer is a usb parallel port ieee1284.
i can send data to the printer no problem. i have tested it with the following command.
cat file.txt > /dev/usbpar0
i have read on several forums that there is no base address for a usb parallel port. what would be the easiest way of reading the status of the printer. I need to know if it is out of paper or there is a paper jam. that is why i need to read the status registers.
I have included the source code i have tried to copy from [here][1]
#include <iostream>
#include <iomanip>
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include "stdlib.h"
#include "unistd.h"
#include "sys/io.h"
#include <hw/inout.h>
#include <stdint.h>
#include <sys/mman.h>
#include <stdio.h>
#include <fcntl.h> /* open() */
#include <sys/types.h> /* open() */
#include <sys/stat.h> /* open() */
#include <sys/ioctl.h>
#include "parport.h"
#include "ppdev.h"
#define DEVICE "/dev/usbpar0"
int write_data(int fd, unsigned char data);
int status_pins(int fd);
using namespace std;
int main(int argc, char **argv)
{
struct ppdev_frob_struct frob;
int fd;
int mode;
if((fd=open(DEVICE, O_RDWR)) < 0) {
fprintf(stderr, "can not open %s\n", DEVICE);
return 10;
}
ThreadCtl(_NTO_TCTL_IO, 0);
status_pins(fd);
close(fd);
return 0;
}
/* trivial example how to write data */
int write_data(int fd, unsigned char data)
{
return(ioctl(fd, PPWDATA, &data));
}
/* example how to read 8 bit from the data lines */
int read_data(int fd)
{
int mode, res;
unsigned char data;
mode = IEEE1284_MODE_ECP;
res=ioctl(fd, PPSETMODE, &mode); /* ready to read ? */
mode=255;
res=ioctl(fd, PPDATADIR, &mode); /* switch output driver off */
printf("ready to read data !\n");
fflush(stdout);
sleep(10);
res=ioctl(fd, PPRDATA, &data); /* now fetch the data! */
printf("data=%02x\n", data);
fflush(stdout);
sleep(10);
data=0;
res=ioctl(fd, PPDATADIR, data);
return 0;
}
/* example how to read the status lines. */
int status_pins(int fd)
{
int val;
ioctl(fd, PPRSTATUS, &val);
val^=PARPORT_STATUS_BUSY; /* /BUSY needs to get inverted */
printf("BUSY = %s\n",
((val & PARPORT_STATUS_BUSY)==PARPORT_STATUS_BUSY)?"HI":"LO");
printf("ERROR = %s\n",
((val & PARPORT_STATUS_ERROR)==PARPORT_STATUS_ERROR)?"HI":"LO");
printf("SELECT = %s\n",
((val & PARPORT_STATUS_SELECT)==PARPORT_STATUS_SELECT)?"HI":"LO");
printf("PAPEROUT = %s\n",
((val & PARPORT_STATUS_PAPEROUT)==PARPORT_STATUS_PAPEROUT)?"HI":"LO");
printf("ACK = %s\n",
((val & PARPORT_STATUS_ACK)==PARPORT_STATUS_ACK)?"HI":"LO");
return 0;
}
/* example how to use frob ... toggle STROBE on and off without messing
around the other lines */
int strobe_blink(int fd)
{
struct ppdev_frob_struct frob;
frob.mask = PARPORT_CONTROL_STROBE; /* change only this pin ! */
while(1) {
frob.val = PARPORT_CONTROL_STROBE; /* set STROBE ... */
ioctl(fd, PPFCONTROL, &frob);
usleep(500);
frob.val = 0; /* and clear again */
ioctl(fd, PPFCONTROL, &frob);
usleep(500);
}
}
"parport.h"
/* $Id: parport.h,v 1.1 1998/05/17 10:57:52 andrea Exp andrea $ */
/*
* Any part of this program may be used in documents licensed under
* the GNU Free Documentation License, Version 1.1 or any later version
* published by the Free Software Foundation.
*/
#ifndef _PARPORT_H_
#define _PARPORT_H_
/* Start off with user-visible constants */
/* Maximum of 16 ports per machine */
#define PARPORT_MAX 16
/* Magic numbers */
#define PARPORT_IRQ_NONE -1
#define PARPORT_DMA_NONE -1
#define PARPORT_IRQ_AUTO -2
#define PARPORT_DMA_AUTO -2
#define PARPORT_DMA_NOFIFO -3
#define PARPORT_DISABLE -2
#define PARPORT_IRQ_PROBEONLY -3
#define PARPORT_IOHI_AUTO -1
#define PARPORT_CONTROL_STROBE 0x1
#define PARPORT_CONTROL_AUTOFD 0x2
#define PARPORT_CONTROL_INIT 0x4
#define PARPORT_CONTROL_SELECT 0x8
#define PARPORT_STATUS_ERROR 0x8
#define PARPORT_STATUS_SELECT 0x10
#define PARPORT_STATUS_PAPEROUT 0x20
#define PARPORT_STATUS_ACK 0x40
#define PARPORT_STATUS_BUSY 0x80
/* Type classes for Plug-and-Play probe. */
typedef enum {
PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */
PARPORT_CLASS_PRINTER,
PARPORT_CLASS_MODEM,
PARPORT_CLASS_NET,
PARPORT_CLASS_HDC, /* Hard disk controller */
PARPORT_CLASS_PCMCIA,
PARPORT_CLASS_MEDIA, /* Multimedia device */
PARPORT_CLASS_FDC, /* Floppy disk controller */
PARPORT_CLASS_PORTS,
PARPORT_CLASS_SCANNER,
PARPORT_CLASS_DIGCAM,
PARPORT_CLASS_OTHER, /* Anything else */
PARPORT_CLASS_UNSPEC, /* No CLS field in ID */
PARPORT_CLASS_SCSIADAPTER
} parport_device_class;
/* The "modes" entry in parport is a bit field representing the
capabilities of the hardware. */
#define PARPORT_MODE_PCSPP (1<<0) /* IBM PC registers available. */
#define PARPORT_MODE_TRISTATE (1<<1) /* Can tristate. */
#define PARPORT_MODE_EPP (1<<2) /* Hardware EPP. */
#define PARPORT_MODE_ECP (1<<3) /* Hardware ECP. */
#define PARPORT_MODE_COMPAT (1<<4) /* Hardware 'printer protocol'. */
#define PARPORT_MODE_DMA (1<<5) /* Hardware can DMA. */
#define PARPORT_MODE_SAFEININT (1<<6) /* SPP registers accessible in IRQ. */
/* IEEE1284 modes:
Nibble mode, byte mode, ECP, ECPRLE and EPP are their own
'extensibility request' values. Others are special.
'Real' ECP modes must have the IEEE1284_MODE_ECP bit set. */
#define IEEE1284_MODE_NIBBLE 0
#define IEEE1284_MODE_BYTE (1<<0)
#define IEEE1284_MODE_COMPAT (1<<8)
#define IEEE1284_MODE_BECP (1<<9) /* Bounded ECP mode */
#define IEEE1284_MODE_ECP (1<<4)
#define IEEE1284_MODE_ECPRLE (IEEE1284_MODE_ECP | (1<<5))
#define IEEE1284_MODE_ECPSWE (1<<10) /* Software-emulated */
#define IEEE1284_MODE_EPP (1<<6)
#define IEEE1284_MODE_EPPSL (1<<11) /* EPP 1.7 */
#define IEEE1284_MODE_EPPSWE (1<<12) /* Software-emulated */
#define IEEE1284_DEVICEID (1<<2) /* This is a flag */
#define IEEE1284_EXT_LINK (1<<14) /* This flag causes the
* extensibility link to
* be requested, using
* bits 0-6. */
/* For the benefit of parport_read/write, you can use these with
* parport_negotiate to use address operations. They have no effect
* other than to make parport_read/write use address transfers. */
#define IEEE1284_ADDR (1<<13) /* This is a flag */
#define IEEE1284_DATA 0 /* So is this */
/* Flags for block transfer operations. */
#define PARPORT_EPP_FAST (1<<0) /* Unreliable counts. */
#define PARPORT_W91284PIC (1<<1) /* have a Warp9 w91284pic in the device */
/* The rest is for the kernel only */
#endif /* _PARPORT_H_ */
"ppdev.h"
/*
* linux/include/linux/ppdev.h
*
* User-space parallel port device driver (header file).
*
* Copyright (C) 1998-9 Tim Waugh <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Added PPGETTIME/PPSETTIME, Fred Barnes, 1999
* Added PPGETMODES/PPGETMODE/PPGETPHASE, Fred Barnes <[email protected]>, 03/01/2001
*/
#define PP_IOCTL 'p'
/* Set mode for read/write (e.g. IEEE1284_MODE_EPP) */
#define PPSETMODE _IOW(PP_IOCTL, 0x80, int)
/* Read status */
#define PPRSTATUS _IOR(PP_IOCTL, 0x81, unsigned char)
#define PPWSTATUS OBSOLETE__IOW(PP_IOCTL, 0x82, unsigned char)
/* Read/write control */
#define PPRCONTROL _IOR(PP_IOCTL, 0x83, unsigned char)
#define PPWCONTROL _IOW(PP_IOCTL, 0x84, unsigned char)
struct ppdev_frob_struct {
unsigned char mask;
unsigned char val;
};
#define PPFCONTROL _IOW(PP_IOCTL, 0x8e, struct ppdev_frob_struct)
/* Read/write data */
#define PPRDATA _IOR(PP_IOCTL, 0x85, unsigned char)
#define PPWDATA _IOW(PP_IOCTL, 0x86, unsigned char)
/* Read/write econtrol (not used) */
#define PPRECONTROL OBSOLETE__IOR(PP_IOCTL, 0x87, unsigned char)
#define PPWECONTROL OBSOLETE__IOW(PP_IOCTL, 0x88, unsigned char)
/* Read/write FIFO (not used) */
#define PPRFIFO OBSOLETE__IOR(PP_IOCTL, 0x89, unsigned char)
#define PPWFIFO OBSOLETE__IOW(PP_IOCTL, 0x8a, unsigned char)
/* Claim the port to start using it */
#define PPCLAIM _IO(PP_IOCTL, 0x8b)
/* Release the port when you aren't using it */
#define PPRELEASE _IO(PP_IOCTL, 0x8c)
/* Yield the port (release it if another driver is waiting,
* then reclaim) */
#define PPYIELD _IO(PP_IOCTL, 0x8d)
/* Register device exclusively (must be before PPCLAIM). */
#define PPEXCL _IO(PP_IOCTL, 0x8f)
/* Data line direction: non-zero for input mode. */
#define PPDATADIR _IOW(PP_IOCTL, 0x90, int)
/* Negotiate a particular IEEE 1284 mode. */
#define PPNEGOT _IOW(PP_IOCTL, 0x91, int)
/* Set control lines when an interrupt occurs. */
#define PPWCTLONIRQ _IOW(PP_IOCTL, 0x92, unsigned char)
/* Clear (and return) interrupt count. */
#define PPCLRIRQ _IOR(PP_IOCTL, 0x93, int)
/* Set the IEEE 1284 phase that we're in (e.g. IEEE1284_PH_FWD_IDLE) */
#define PPSETPHASE _IOW(PP_IOCTL, 0x94, int)
/* Set and get port timeout (struct timeval's) */
#define PPGETTIME _IOR(PP_IOCTL, 0x95, struct timeval)
#define PPSETTIME _IOW(PP_IOCTL, 0x96, struct timeval)
/* Get available modes (what the hardware can do) */
#define PPGETMODES _IOR(PP_IOCTL, 0x97, unsigned int)
/* Get the current mode and phaze */
#define PPGETMODE _IOR(PP_IOCTL, 0x98, int)
#define PPGETPHASE _IOR(PP_IOCTL, 0x99, int)
/* get/set flags */
#define PPGETFLAGS _IOR(PP_IOCTL, 0x9a, int)
#define PPSETFLAGS _IOW(PP_IOCTL, 0x9b, int)
/* flags visible to the world */
#define PP_FASTWRITE (1<<2)
#define PP_FASTREAD (1<<3)
#define PP_W91284PIC (1<<4)
/* only masks user-visible flags */
#define PP_FLAGMASK (PP_FASTWRITE | PP_FASTREAD | PP_W91284PIC)
I managed to find a solution to my problem by using the devctl command. i could read the status of the printer.
#include <iostream>
#include <iomanip>
#include <devctl.h>
#include <sys/dcmd_chr.h>
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include "stdlib.h"
#include "unistd.h"
#include "sys/io.h"
#include <hw/inout.h>
#include <stdint.h>
#include <sys/mman.h>
#include <stdio.h>
#include <fcntl.h> /* open() */
#include <sys/types.h> /* open() */
#include <sys/stat.h> /* open() */
#include <sys/ioctl.h>
#include "parport.h"
#include "ppdev.h"
#define DEVICE "/dev/usbpar0"
int status_pins(int fd);
using namespace std;
int main(int argc, char **argv)
{
int fd;
if((fd=open(DEVICE, O_RDWR)) < 0) {
fprintf(stderr, "can not open %s\n", DEVICE);
return 10;
}
// ThreadCtl(_NTO_TCTL_IO, 0);
int data = 0, error;
if (error = devctl (fd, DCMD_CHR_LINESTATUS, &data,
sizeof(data), NULL))
{
fprintf(stderr, "Error setting RTS: %s\n",
strerror ( error ));
exit(EXIT_FAILURE);
}
if (data & _LINESTATUS_PAR_NOERROR)
{
printf("No Error Detected!\n");
}
else
{
printf("Error Detected\n");
}
if (data & _LINESTATUS_PAR_PAPEROUT)
{
printf("Paper Empty\n");
}
else
{
printf("Paper OK!\n");
}
close(fd);
return 0;
}