CAPS Universe documentation  1.0.4
All you need to know to be successful
Functions
device-monitor.c File Reference

Functions to monitor the attached USB printer device. More...

Functions

static bool caps_drv_printer_is_busy (unsigned status)
 
static bool caps_drv_printer_is_error (unsigned status)
 
static bool caps_drv_printer_is_oop (unsigned status)
 
static bool caps_drv_status_bit_changed (unsigned old_status, unsigned new_status, unsigned check_bit)
 
static void caps_drv_active_state_enter (struct caps_pp_handle *instance, unsigned prn_status, int printing)
 
static void caps_drv_error_state_enter (struct caps_pp_handle *instance, unsigned prn_status)
 
void caps_drv_printer_tweak_status (struct caps_drv *cdrv)
 
static int caps_drv_printer_status_query (int fd, unsigned *prn_status)
 
int caps_drv_is_offline (struct caps_drv *cdrv)
 
int caps_drv_is_fault_state (struct caps_drv *cdrv)
 
int caps_drv_is_empty (struct caps_drv *cdrv)
 
int caps_drv_printer_check (struct caps_drv *cdrv)
 

Detailed Description

Author
Jürgen Borleis
Warning
Use as experimental

The monitor isn't perfect when reporting the printer's state. It tries its best, but some states aren't distinguishable and thus reported wrong. But it seems it is good enough to have some important information at hand (like "out of paper" for example).

Function Documentation

◆ caps_drv_printer_is_busy()

static bool caps_drv_printer_is_busy ( unsigned  status)
static

Check if the printer is busy

Parameters
[in]statusCurrent status read via ioctl() from the printer
Return values
trueIf the printer signals it is busy
falseIf the printer signals it is idle

Interpreting these status bits is always confusing, since some are of negative logic and some other not.

The busy bit (LP_PBUSY) is '1' if the printer is busy.

◆ caps_drv_printer_is_error()

static bool caps_drv_printer_is_error ( unsigned  status)
static

Check if the printer is in error state

Parameters
[in]statusCurrent status read via ioctl() from the printer
Return values
trueIf the printer signals it is in an error state
falseIf the printer signals it is not in an error state

Interpreting these status bits is always confusing, since some are of negative logic and some other not.

The error bit (LP_PERRORP) is '0' if the printer is in error state.

◆ caps_drv_printer_is_oop()

static bool caps_drv_printer_is_oop ( unsigned  status)
static

Check if the printer is out of paper

Parameters
[in]statusCurrent status read via ioctl() from the printer
Return values
trueIf the printer signals it is out of paper
falseIf the printer signals it is out of paper

Interpreting these status bits is always confusing, since some are of negative logic and some other not.

The out of paper bit (LP_POUTPA) is '1' if the printer is out of paper.

◆ caps_drv_status_bit_changed()

static bool caps_drv_status_bit_changed ( unsigned  old_status,
unsigned  new_status,
unsigned  check_bit 
)
static

Check if specific bits in two status differ

Parameters
[in]old_statusOne status
[in]new_statusA second status
[in]check_bitBit mask of to be checked bits
Return values
trueIf the status bit(s) differ
falseIf the status bit(s) is/are still the same

◆ caps_drv_active_state_enter()

static void caps_drv_active_state_enter ( struct caps_pp_handle instance,
unsigned  prn_status,
int  printing 
)
static

Setup the next printer state report to reflect its real state (printing or power save)

Parameters
[in]instanceConnection info to the printing coordinator
[in]prn_statusCurrent printer's state
[in]printing'0' if currently no job is printed, else currently a job is printed

If we return from a printer error state into the printer active state, we need to report the correct printer's and the driver's state . This routine detects if currently a job is processed and returns to the PRINTING state, else in the POWER-SAVE state.

Note
This routine is required, due to the fact the printer reports a busy state in printing and power save mode as well.
Precondition
Busy bit is already checked and set

◆ caps_drv_error_state_enter()

static void caps_drv_error_state_enter ( struct caps_pp_handle instance,
unsigned  prn_status 
)
static

Generate an error report based on the status bits of the USB printer

Parameters
[in]instanceConnection info to the printing coordinator
[in]prn_statusCurrent printer's state

Assumption is: the printer device reports:

  • error bit set + out_of_paper bit set for an "out of paper" state
  • error bit set + out_of_paper bit reset for a "paper jam" state
Precondition
Error bit is already checked and set

◆ caps_drv_printer_tweak_status()

void caps_drv_printer_tweak_status ( struct caps_drv cdrv)

Eval the printer's monitoring setting

Parameters
[in,out]cdrvFull state information

This function deals with the setting described in Feature: control printer monitoring

It always falls back to "never", if it detects the file descriptor points to a file instead of a printer.

Sets up two of the printer tweaks: CAPS_TWEAK_SKIP_STATUS_WHEN_PRINTING and CAPS_TWEAK_SKIP_STATUS

Precondition
The caps_drv::prn_desc must already contain a valid file descriptor

The default is "always" and is documented in Feature: control printer monitoring

Todo:
Error handling!

◆ caps_drv_printer_status_query()

static int caps_drv_printer_status_query ( int  fd,
unsigned *  prn_status 
)
static

Query and return the status of a USB printer

Parameters
[in]fdFile descriptor to access the printer
[out]prn_statusThe printer's current status
Return values
0The prn_status contains the printer's current status
-ENODEVThe printer device behind the file descriptor seems gone (e.g. offline)
-EBADFfd is invalid (should not happen)
negativeMore possible error codes from an ioctl() call

Only three bits are known to work (at least with my printer):

Bit No Bit Name Bit description Mask Macro
7 BUSY low = idle, high = busy LP_PBUSY
5 OOP high = Out of Paper LP_POUTPA
3 ERROR high = Error LP_PERRORP
Attention
Be always prepared for the -ENODEV return value case. Printers can disappear at any time.

◆ caps_drv_printer_check()

int caps_drv_printer_check ( struct caps_drv cdrv)

Monitor the state of the attached printer device and create reports for the printing coordinator accordingly

Parameters
[in,out]cdrvFull state information
Return values
'0'printer is ready to print jobs
-EBUSYThe printer isn't ready to print jobs, due to an error (out of paper for example)
-ENODEVThe printer is gone
-EINVALTerminate current job, but continue.

This function monitors the state of the attached printer and creates printer state reports for the printing coordinator. The main goal is to inform the user in a precise way about the state of the printer. You should call it periodically.

Within three bits the printer informs the host about its current state.

  • BUSY
  • ERROR
  • OutOfPaper

Static states are

  • BUSY = 0: the printer is idle and waits for data to print
  • BUSY = 1, ERROR=0: the printer is printing or in power save state or in its warm up phase
  • BUSY = 1, ERROR=1, OOP=0: the printer is in trouble, mostly paper jam
  • BUSY = 1, ERROR=1, OOP=1: the printer is out of paper

The important facts are the transitions between these static states. Most of them need a report to the printing coordinator about the transition.

'Busy' changed from '0' to '1'

This means the printer changed from some state of waiting for data into an active state (e.g. printing) or into an error state. Or - at least in the case of my printer - if it moves into the power save mode. All of these transitions need a new state report.

Example: you start a new printing job

Example: you remove the paper from your idling printer

Example: your printer is in trouble somehow

Note
Paper Jam cannot be the root cause of this trouble in this case.

'Busy' changed from '1' to '0'

This always means the printer has moved to active idle and waits for data and a new state must be reported.

'Busy' is still '0'

This always means the printer is still in active idle mode and waits for data. No new state needs to be reported.

'Busy' is still '1', but 'Error' changed from '1' to '0'

This means the printer has left the error state. Maybe it now immediately continues to print or needs first a warm-up phase again to do so.

'Busy' is still '1', but 'Error' changed from '0' to '1'

This means the printer changed into an error state, coming from state printing or state warm-up (but not from state idle, because then the 'Busy' status changes first)

'Busy' is still '1', 'Error' is still '1', but 'OOP' changed from '1' to '0'

Here the user can load new paper, but there is still a paper jam in the printer.

Other examples

You start a new printing job and then the paper tray is empty

You start a new printing job and the paper jams

You start a new printing job and it finishes

Your printer is idling for a long time and enters a power save mode.

Note
As you can see, this transition cannot be distinguished from a beginning warm-up phase or printing. In this case you must know, if the driver currently prints something or is idle as well.
Todo:
According to the kernel documentation, the 'LPCAREFUL' feature is enabled by default. This would mean, we receive an error, if we send some data to the printer while it is in error state.
Precondition
Established registration at the printing coordinator
Todo:
Add more state to this routine. At power up (initialization phase) of the printer it reports a printer in "power down" mode. Which isn't true.
When a print job is done (from the driver's point of view) it reports the printer is in "power down" mode again, since it seems not printing at this time (but reports it is still busy).
Precondition
Expectation is, the printer activates its "LP_PBUSY" flag, if an error should be signaled. Else, the monitor state machine cannot detect the error state.