CAPS Universe documentation  1.0.4
All you need to know to be successful
Data Structures | Macros | Enumerations | Functions
libcapsdriver-local.h File Reference

The librarie's local declarations. More...

Go to the source code of this file.

Data Structures

struct  caps_drv
 libcapsdriver internal data collection More...
 

Macros

#define caps_print_debug(fmt, ...)
 
#define DSO_VISIBLE
 
#define ARRAY_SIZE(x)   (sizeof(x)/sizeof(x[0]))
 
#define _(string)   (string)
 
#define NLS_(string)   (string)
 
#define MAX(a, b)   ((a) > (b) ? a : b)
 

Enumerations

enum  halftone_type {
  HT_METHOD_NONE ,
  HT_METHOD_AV ,
  HT_METHOD_ORDERED ,
  HT_METHOD_FLS ,
  HT_METHOD_JJN ,
  HT_METHOD_ST ,
  HT_METHOG_AT ,
  HT_METHOD_BU ,
  HT_METHOD_SI1 ,
  HT_METHOD_SI2 ,
  HT_METHOD_SI3
}
 Declaration of some internal dithering/halftone algorithms. More...
 

Functions

static unsigned DOTS_TO_BYTES (unsigned dots)
 
static size_t DOTS_TO_INDEX (size_t dots)
 
static bool job_final_state_already_set (const struct caps_drv *cdrv)
 
int caps_drv_jobs_loop (struct caps_drv *drvi, const char *filename, const char *params)
 
int caps_drv_page_loop (struct caps_drv *drvi)
 
int caps_drv_printer_check (struct caps_drv *drvi)
 
int caps_drv_global_stream_io (struct caps_drv *drvi)
 
void caps_drv_printer_tweak_status (struct caps_drv *drvi)
 
void caps_drv_shutdown (struct caps_pp_handle *instance)
 
void caps_drv_start_up_state (struct caps_pp_handle *instance)
 
void caps_drv_idle (struct caps_pp_handle *instance)
 
void caps_drv_power_saving (struct caps_pp_handle *instance)
 
void caps_drv_printing (struct caps_pp_handle *instance)
 
void caps_drv_out_of_paper (struct caps_pp_handle *instance)
 
void caps_drv_error (struct caps_pp_handle *instance)
 
void caps_drv_job_start (struct caps_drv *cdrv)
 
void caps_drv_job_completed (struct caps_drv *cdrv)
 
void caps_drv_job_stopped (struct caps_drv *cdrv)
 
void caps_drv_job_aborted (struct caps_drv *cdrv, enum caps_printing_job_reason reason, const char *message)
 
void caps_drv_emulation_stop (struct caps_drv *cdrv)
 
int caps_drv_print_medium_default_post_setup (struct caps_drv *cdrv)
 
int caps_drv_emulation_setup (struct caps_drv *cdrv)
 
struct drv_halftone_converterht_get (enum halftone_type t, unsigned cnt)
 
void ht_put (struct drv_halftone_converter *ht)
 
int ht_grey_line_add (struct drv_halftone_converter *ht, unsigned cnt, const struct caps_dot_grey raw[cnt])
 
int ht_emptyline_add (struct drv_halftone_converter *ht)
 
int ht_drain (struct drv_halftone_converter *ht)
 
unsigned ht_monochrome_line_get (struct drv_halftone_converter *ht, enum caps_colour_format cf, unsigned cnt, struct caps_dot_monochrome ln[cnt])
 
static int fd_is_valid (int fd)
 

Detailed Description

Author
Jürgen Borleis
Warning
Use as experimental

Macro Definition Documentation

◆ caps_print_debug

#define caps_print_debug (   fmt,
  ... 
)

Output a debug trace message. Used to track program states in even more detail

◆ DSO_VISIBLE

#define DSO_VISIBLE

◆ ARRAY_SIZE

#define ARRAY_SIZE (   x)    (sizeof(x)/sizeof(x[0]))

◆ _

#define _ (   string)    (string)

◆ NLS_

#define NLS_ (   string)    (string)

◆ MAX

#define MAX (   a,
 
)    ((a) > (b) ? a : b)

Enumeration Type Documentation

◆ halftone_type

Heavily inspired by some work of Tanner Helland (tannerhelland.com) and a document from Lee Daniel Crocker (aka DHALF.txt).

Enumerator
HT_METHOD_NONE 
HT_METHOD_AV 

A simple threshhold based halftone method
https://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/average_dithering.html

Simple threshold conversion
HT_METHOD_ORDERED 

8x8 Bayer ordered dithering
https://en.wikipedia.org/wiki/Ordered_dithering
https://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/ordered_dithering.html

Bayer pattern conversion
HT_METHOD_FLS 

Error diffusion dithering according to Floyd and Steinberg
https://www.visgraf.impa.br/Courses/ip00/proj/Dithering1/floyd_steinberg_dithering.html

Floyd and Steinberg error diffusion conversion
HT_METHOD_JJN 

Error diffusion dithering according to Jarvis, Judice, and Ninke

Jarvis, Judice, and Ninke error diffusion conversion
HT_METHOD_ST 

Stucki, not implemented yet

HT_METHOG_AT 

Atkinson, not implemented yet

HT_METHOD_BU 

Burkes, not implemented yet

HT_METHOD_SI1 

Sierra, not implemented yet

HT_METHOD_SI2 

Two-Row Sierra, not implemented yet

HT_METHOD_SI3 

Sierra Lite, not implemented yet

Function Documentation

◆ DOTS_TO_BYTES()

static unsigned DOTS_TO_BYTES ( unsigned  dots)
inlinestatic

Convert dot count into byte count

Parameters
[in]dotsDot count
Returns
Byte count for this amount of dots

8 dots form a full byte. The byte count is rounded up to also have space for the remainder of dots.

◆ DOTS_TO_INDEX()

static size_t DOTS_TO_INDEX ( size_t  dots)
inlinestatic

Convert a dot count into an array index

Parameters
[in]dotsDot count
Returns
Index into the array

8 dots form a full byte. The index is rounded down.

◆ job_final_state_already_set()

static bool job_final_state_already_set ( const struct caps_drv cdrv)
inlinestatic

◆ caps_drv_jobs_loop()

int caps_drv_jobs_loop ( struct caps_drv drvi,
const char *  filename,
const char *  params 
)

The function returns if:

  • the program should terminate
  • the printer is gone, e.g. the filedescriptor is invalid

◆ caps_drv_page_loop()

int caps_drv_page_loop ( struct caps_drv cdrv)

Loop over all pages to be print of the current document, deal with the printer and possible errors

Parameters
[in,out]cdrvAll required information about the current print job
Return values
-ENODEVTerminate whole driver (from caps_drv_printer_check())
-EINVALCancel current job (from caps_drv_printer_check())
-EBUSYBe patient, the driver is in an error state (paper jam, out of paper etc. from caps_drv_printer_check())
-EOFPremature end of document
-ENOTSUPA setting or some settings in pg aren't possible.
Note
job_data can be NULL for the special usecase of an injected job
We set the job's final state here to "aborted" if we receive a termination signal. Other routines do not need to do so.

◆ 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.

◆ caps_drv_global_stream_io()

int caps_drv_global_stream_io ( struct caps_drv cdrv)

Convert the file descriptor to the printer into stream IO and configure it

Parameters
[in,out]cdrvFull state information
Return values
0On success
negativeThe error codes fdopen() (file descriptor to stream IO) may returns

This functions sets up a stream IO from the given filedescriptor to be used by the printer driver. The filedescriptor is kept to be used later on to query the printer's status.

Some printers are in trouble (or time out) if there are pauses in the printing data between some kind of header data and the following printing data. These pauses can occur due to data processing, at least on slow host systems.
That's why increase the stream IO buffer size is a good idea to have most data already processed, before the printer will "see" the data. The user can control the used buffer size via the corresponding INI file in section interface, variable buffer_size. It is possible to disable a buffer at all. Refer Feature: printing data buffer_size for details.

Precondition
Never call a second time
The open device descriptor to the printer should already be tested and valid

◆ 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_shutdown()

void caps_drv_shutdown ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_start_up_state()

void caps_drv_start_up_state ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_idle()

void caps_drv_idle ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_power_saving()

void caps_drv_power_saving ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_printing()

void caps_drv_printing ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_out_of_paper()

void caps_drv_out_of_paper ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_error()

void caps_drv_error ( struct caps_pp_handle instance)
Parameters
[in]instanceConnection info to the printing coordinator

◆ caps_drv_job_start()

void caps_drv_job_start ( struct caps_drv cdrv)

◆ caps_drv_job_completed()

void caps_drv_job_completed ( struct caps_drv cdrv)

◆ caps_drv_job_stopped()

void caps_drv_job_stopped ( struct caps_drv cdrv)

◆ caps_drv_job_aborted()

void caps_drv_job_aborted ( struct caps_drv cdrv,
enum caps_printing_job_reason  reason,
const char *  message 
)

◆ caps_drv_emulation_stop()

void caps_drv_emulation_stop ( struct caps_drv cdrv)

Clean up the emulated data

◆ caps_drv_print_medium_default_post_setup()

int caps_drv_print_medium_default_post_setup ( struct caps_drv cdrv)

Check if the medium setup is possible

Parameters
[in]cdrvlibcapsdriver handle
Return values
0On success
-EINVALThe setup for the current page cannot be done

Enable emulation of a monochrome raster if the rasterizer supports grey scale but no monochrome.

If the job cannot be printed, a corresponding abort error message is set.

Precondition
This function can be called after caps_drv_print_medium_default_setup() has done its job.

◆ caps_drv_emulation_setup()

int caps_drv_emulation_setup ( struct caps_drv cdrv)

Convert the rasterized image on demand

Return values
0Always

For the case, we need to emulate some colour format, we do it here

Note
This increases the amount of required memory, since the raw raster and the emulated raster exists at the same time.
Precondition
caps_drv::raster_desc must be valid
Todo:
Think about to free the raw raster, when the emulated raster has been created. This might conflict with printing more than one copies of the current page!

◆ ht_get()

struct drv_halftone_converter * ht_get ( enum halftone_type  t,
unsigned  cnt 
)

Create and configure a halftone converter

Parameters
[in]tType of the halftone algorithm to configure
[in]cntPixel count in each line
Returns
A halftone converter configuration

Depending on the selected halftone algorithm, memory to process the input grey scale lines later on will be allocated.

Postcondition
Does not return in case of an unimplemented or unknown halftone method.

◆ ht_put()

void ht_put ( struct drv_halftone_converter ht)

Destroy a halftone converter configuration and free resources

Parameters
[in]htThe halftone converter configuration

◆ ht_grey_line_add()

int ht_grey_line_add ( struct drv_halftone_converter ht,
unsigned  cnt,
const struct caps_dot_grey  raw[cnt] 
)

Add a line with grey scale content to the halftone algorithm's processing buffer

Parameters
[in]htThe halftone converter configuration
[in]cntCount of grey scale dots in raw (can be '0')
[in]rawA raw line of grey scale dots (caps_dot_grey), can be NULL if cnt is '0' as well
Return values
-EAGAINAdd another line first to pre-load the halftone algorithm
0A dithered line awaits its read via ht_monochrome_line_get()

If the call returns with a 0, a line can be read with ht_monochrome_line_get()

Note
If cnt is '0', an empty line (e.g. all dot are white) is added to the halftone converter.

Silently:

  • longer lines are skipped at their right end.
  • shorter lines are filled at their right end.

◆ ht_emptyline_add()

int ht_emptyline_add ( struct drv_halftone_converter ht)

Add an empty line (e.g. all dots are white) to the halftone algorithm's processing buffer

Parameters
[in]htThe halftone converter configuration
Return values
-EAGAINAdd another line first to pre-load the halftone algorithm
0A dithered line awaits its read via ht_monochrome_line_get()
Note
This is just an optimization.

When the call returns with a 0, a line can be read with ht_monochrome_line_get()

◆ ht_drain()

int ht_drain ( struct drv_halftone_converter ht)

Drain the halftone algorithm's processing buffer by padding an empty line

Parameters
[in]htThe halftone converter configuration
Return values
0Finished
-EAGAINRead a dithered line via ht_monochrome_line_get() and call again

Let process the halftone algorithm the next line with a new empty line. Intended to be called at the bottom of the input raster to finish the halftone algorithm. Some algorithm needs more than one line in its buffer to process the current line. Call this routine as often as it returns -EAGAIN. After each call (and -EAGAIN) you can read the next processed line. If it returns 0, you are done.

If the call returns with a -EAGAIN, another line can be read with ht_monochrome_line_get()

Todo:
Better '0' for "read a dithered line…" and -ENODATA for "finished"?

◆ ht_monochrome_line_get()

unsigned ht_monochrome_line_get ( struct drv_halftone_converter ht,
enum caps_colour_format  cf,
unsigned  cnt,
struct caps_dot_monochrome  ln[cnt] 
)

Extract the monochrome data line from the halftone processing buffer

Parameters
[in]htThe halftone converter configuration
[in]cfThe target monochrome colour format (one of CAPS_CF_MONOCHROME0 or CAPS_CF_MONOCHROME1)
[in]cntThe amount of bytes in ln
[out]lnThe buffer for the monochrome data
Returns
Amount of dots in ln (not bytes!)

Converts the top line from the halftone converter into a line of monochrome bits in ln. In order to make this work, this top line must already be processed, e.g. the last call to ht_grey_line_add() and ht_emptyline_add() returned with '0' or a call to ht_drain() returned with -EAGAIN.

If the count of grey scale dots in the halftone converter's line isn't a multiple of eight, the remaining resulting monochrome bits are white, e.g. set to "no dot".

Note
There is an optimized variant (vectorized) of this function, tested on ARM32, ARM64 and X86-64.
And a non-optimized variant for general purpose.
Precondition
ln must be equal or greater than DOTS_TO_BYTES(drv_halftone_converter::cnt) bytes
An already halftoned buffer in monochrome_converter::sliding_line[0]

◆ fd_is_valid()

static int fd_is_valid ( int  fd)
inlinestatic

Check if the given file descriptor is still valid

Parameters
[in]fdFile descriptor to check
Return values
trueFile descriptor is valid
falseFile descriptor is invalid
Attention
This check isn't reliable!
Todo:
If the driver was started from within the template service unit, fcntl() always returns a valid file descriptor, even if the printer is already gone.