Printer data protocol related functions shared by all QL label printer drivers.
More...
|
int | ql_page_print (struct ql_drv *t) |
|
int | ql_last_page_print (struct ql_drv *t) |
|
static int __wur | ql_compression_setup (struct ql_drv *t, unsigned mode) |
|
int | ql_reset (struct ql_drv *t) |
|
int | ql_invalidate_and_initialize (struct ql_drv *t) |
|
static __wur int | ql_extended_mode_set (struct ql_drv *t, unsigned value) |
|
static __wur int | ql_cut_mode_set (struct ql_drv *t, unsigned mode) |
|
static __wur int | ql_cut_on_label_n (struct ql_drv *t, unsigned cut_on_page) |
|
static __wur int | ql_notification_disable (struct ql_drv *t) |
|
static __wur int | _ql_status_request (struct ql_drv *t) |
|
int | ql_status_request (struct ql_drv *t, unsigned char buffer[32]) |
|
static __wur int | ql_dynamic_mode (struct ql_drv *t) |
|
static __wur int | ql_define_tape_margins (struct ql_drv *t, uint16_t margins) |
|
static __wur int | ql_print_information (struct ql_drv *t, int media_type, int media_width, int media_length, int raster, int start_page, int quality) |
|
int | ql_job_header_generate (struct ql_drv *t) |
|
int | ql_page_header_generate (struct ql_drv *t, int first_page) |
|
int | ql_auto_powerdown (struct ql_drv *t, unsigned short time_out) |
|
int | ql_auto_powerup (struct ql_drv *t, unsigned short mode) |
|
A regular print job for a QL printer:
ql_define_tape_margins()
◆ QL_NO_COMPRESSION
#define QL_NO_COMPRESSION 0x00 |
Value to signal the printer, the print data will be sent without any compression. Used in the ql_compression_setup() function as its mode
parameter
◆ QL_TIFF_COMPRESSION
#define QL_TIFF_COMPRESSION 0x02 |
Value to signal the printer, the print data will be sent in TIFF compression. Used in the ql_compression_setup() function as its mode
parameter
- Attention
- Only for reference. Compression isn't supported, yet
◆ QL_BI_COLOR
◆ QL_CUT_AT_END
#define QL_CUT_AT_END 0x08 |
Bit to setup the printer into "cut when job is finished" mode. Used in the ql_extended_mode_set() function as its value
parameter
For: QL-570/580N/700/QL8xx
- Note
- It is still unclear what exactly this bit means in conjunction to the other cutting related bits. If someone has an idea, drop me a note.
-
Can be or'ed with the QL_BI_COLOR and QL_HIGH_RESOLUTION bits.
◆ QL_HIGH_RESOLUTION
#define QL_HIGH_RESOLUTION 0x40 |
◆ QL_AUTO_CUT
Bit to setup the printer into "auto cut" mode. Used in the ql_cut_mode_set() function as its mode
parameter For QL550/560/570/580N/650TD/700/1050/1060N
◆ QL_CUT_EACH_LABEL
#define QL_CUT_EACH_LABEL 0 |
Default value for the ql_cut_on_label_n() function to define "cut each single label" To be used as its cut_on_page
parameter.
◆ QL_WHAT_IS_BIT_0
#define QL_WHAT_IS_BIT_0 0x01 |
Unknown meaning in the #print_inform::valid member
◆ QL_MEDIA_ENTRY_VALID
#define QL_MEDIA_ENTRY_VALID 0x02 |
◆ QL_WIDTH_ENTRY_VALID
#define QL_WIDTH_ENTRY_VALID 0x04 |
◆ QL_LENGTH_ENTRY_VALID
#define QL_LENGTH_ENTRY_VALID 0x08 |
◆ QL_RASTER_ENTRY_VALID
#define QL_RASTER_ENTRY_VALID 0x10 |
◆ QL_HIGH_PRINT_QUALITY
#define QL_HIGH_PRINT_QUALITY 0x40 |
◆ QL_RECOVER_ENTRY_VALID
#define QL_RECOVER_ENTRY_VALID 0x80 |
I found a hint. When set, it means: only print on labels of matching size
◆ QL_MEDIA_TYPE_CONTINUOUS
#define QL_MEDIA_TYPE_CONTINUOUS 0xa |
◆ QL_MEDIA_TYPE_DIE_CUT
#define QL_MEDIA_TYPE_DIE_CUT 0xb |
◆ QL_QUALITY_PRINT
#define QL_QUALITY_PRINT 0x40 |
never use while bi-colour printing (according to the datasheet)
◆ QL_FAST_PRINT
#define QL_FAST_PRINT 0x00 |
Always use with bi-colour printing (according to the datasheet)
◆ ql_page_print()
int ql_page_print |
( |
struct ql_drv * |
t | ) |
|
Finish the current page
- Parameters
-
[in] | t | Full job description |
- Return values
-
This code is to be sent after a page.
It seems, this command is only to be sent, if more than one page in one job should be printed. If the job contains only one page, the ql_last_page_print() is enough to do the right thing.
- Note
- To be sent at the end of a page's raster, if it isn't the last page to be print (according to the manual)
◆ ql_last_page_print()
int ql_last_page_print |
( |
struct ql_drv * |
t | ) |
|
Finish the current print job
- Parameters
-
[in] | t | Full job description |
- Return values
-
This code is to be sent after the last page to finish the whole print job.
- Note
- To be sent at the end of a page's raster, if it is the last page of the job (according to the manual)
◆ ql_compression_setup()
static int __wur ql_compression_setup |
( |
struct ql_drv * |
t, |
|
|
unsigned |
mode |
|
) |
| |
|
static |
Setup the line data compression mode
- Parameters
-
- Return values
-
- Note
- Only a few printers can deal with compression, so QL_TIFF_COMPRESSION isn't supported, yet.
-
To be sent at the beginning of a page's raster and required at each page (according to the manual)
◆ ql_reset()
int ql_reset |
( |
struct ql_drv * |
t | ) |
|
Initialize/reset the printer
- Parameters
-
[in] | t | Full job description |
- Return values
-
This command can also be used every time to terminate a current print
- Note
- To be sent once at the beginning of a print job (according to the manual)
◆ ql_invalidate_and_initialize()
int ql_invalidate_and_initialize |
( |
struct ql_drv * |
t | ) |
|
Start a new print job from the printer's point of view
- Parameters
-
[in] | t | Full job description |
- Return values
-
To be sent at the beginning of a new print job or if the current processing has to be stopped at the printer's side.
From the datasheet: "If data transmission is to be stopped midway, send
the “initialize” command after sending the “invalidate” command for the
appropriate number of bytes to return to the receiving state, where the print
buffer is cleared."
- Note
- invalidate means the specified amount of zero bytes
-
initialize means the *ESC,@* command in ql_reset()
-
To be sent once at the beginning of a print job (according to the manual)
◆ ql_extended_mode_set()
static __wur int ql_extended_mode_set |
( |
struct ql_drv * |
t, |
|
|
unsigned |
value |
|
) |
| |
|
static |
Send expanded mode
- Parameters
-
- Return values
-
- Note
- With the cutter related bit 3 cutting at the end (whatever 'end' here is meant) can be controlled
-
To be sent at the beginning of a page and required at each page (according to the manual)
◆ ql_cut_mode_set()
static __wur int ql_cut_mode_set |
( |
struct ql_drv * |
t, |
|
|
unsigned |
mode |
|
) |
| |
|
static |
Setup "various mode"
- Parameters
-
[in] | t | Full job description |
[in] | mode | Cutter mode, '0' or QL_AUTO_CUT |
- Return values
-
- Attention
- When this function/command is used to enable "auto cut", the ql_cut_on_label_n() must be called as well.
Older documentation defines the bits of mode
to:
- bit 7: Mirror print (0 = do not mirror)
- bit 6: Auto cut (0 = no auto cut)
- bit 5: unknown
- bit 0…4: Feed amount (0-7=none, 8-11=small, 12-25=medium, 26-31=large)
- Note
- This information might be valid for ptouch printers and not for QL printers (with the auto cut feature as an exception)
-
To be sent at the beginning of a page and required at each page (according to the manual)
◆ ql_cut_on_label_n()
static __wur int ql_cut_on_label_n |
( |
struct ql_drv * |
t, |
|
|
unsigned |
cut_on_page |
|
) |
| |
|
static |
Setup the label count when to cut (makes sense only if auto-cut is enabled)
- Parameters
-
[in] | t | Full job description |
[in] | cut_on_page | Auto cut after this amount of pages (can be QL_CUT_EACH_LABEL for cut every label) |
- Return values
-
- Attention
- Makes sense only if auto-cut is enabled and with pre-cut labels
- Note
- Nothing happens (at least with the cutter), if this command wasn't sent.
-
To be sent at the beginning of a page and required at each page (according to the manual)
- Precondition
- A call to ql_cut_mode_set() which enables "auto cut"
◆ ql_notification_disable()
static __wur int ql_notification_disable |
( |
struct ql_drv * |
t | ) |
|
|
static |
Disable the printer's notification capability
- Parameters
-
[in] | t | Full job description |
- Return values
-
We do not have a real back channel, so we can't recieve its data
- Todo:
- But it would be useful to have a back channel!
◆ _ql_status_request()
static __wur int _ql_status_request |
( |
struct ql_drv * |
t | ) |
|
|
static |
Request status report from printer.
- Parameters
-
[in] | t | Full job description |
After sending this command, it:
- takes a while until the data hits the printer
- it must go through the system's memory
- it must go through the USB subsystem
- it must go over the USB line
- it must be processed by the printer
- takes a while until the printer's respond hits our memory
- the USB controller must request the printer for data
- the data must go over the USB line
- the data must go through the USB subsystem
- the data must go through the system's memory
Sometimes this request fails:
- at least if the printer is in trouble due to bad data or empty cassette.
- you see the red LED blinking slowly in this case
- the printer's USB interface status in this case is: error=no and or paper empty=1
- it responds with a report in this case without a request
- this report is of type "phase change"
- after this last report, it doesn't respond to requests anymore
- after opening and closing the cover manually it responds again on a request
- Attention
- Until the data hits our memory the printer's filedescriptor
is in state EOF and for example a select() on it does't work!
-
If the printer is in trouble (e.g. error state), sending this command string will block!
◆ ql_status_request()
int ql_status_request |
( |
struct ql_drv * |
t, |
|
|
unsigned char |
buffer[32] |
|
) |
| |
Request and read status from printer.
- Parameters
-
[in] | t | Full job description |
[out] | buffer | Storage for the 32 status bytes read from the printer |
- Return values
-
0 | Status read successfully |
-ENODATA | No status information from the printer. buffer content is invalid |
-ENODEV | If the printer is gone in the meanwhile. This is serious! |
-errno | All error values from ql_driver_data_send(). They are serious! |
Some run-time experiences:
- the printer reports always the inserted cassette, even if the cover is opened (QL800 tested)
- if no cassette is inserted, it returns 0x00 as the 'media_type' and width and length as 0.
- whenever an error occur, the report is marked as an error report (field 'status_type')
- if the cover is closed but whithout an inserted cassette the report isn't marked as an error report
- it seems, the 'automatic status notification mode' works differently. At my side it didn't work at all
- Precondition
- Printer must be idle
◆ ql_dynamic_mode()
static __wur int ql_dynamic_mode |
( |
struct ql_drv * |
t | ) |
|
|
static |
Configure the printer to a sepcifc "dynamic mode"
- Parameters
-
[in] | t | Full job description |
- Return values
-
For some QL models this has to be done at most once per run-time. The printer operates in this mode until it is turned off again. But read the note below!
- Note
- No rule without exception: according to its datasheet, the QL600 requires this command right after the reset command and requires it again after the ql_last_page_print() but with mode 'default' (eg. mode = 0xff)
-
To be sent at the beginning of a page and required at each page (according to the manual). The real requirement is unclear, since the datasheet lists different requirements at different pages.
◆ ql_define_tape_margins()
static __wur int ql_define_tape_margins |
( |
struct ql_drv * |
t, |
|
|
uint16_t |
margins |
|
) |
| |
|
static |
Setup the margins (top and bottom) to be used for this print
- Parameters
-
[in] | t | Full job description |
[in] | margins | Top and bottom margins [dots] TODO maybe better in mm? |
- Return values
-
- Precondition
- According to the QL800 manual, the margins must be at least 3 mm (or 35 dots) and max. 127 mm (or 1500 dots).
- Attention
- Since the margin is defined in dots, it is resolution dependend (vertical!)
- Note
- From the manual: "since a margin amount cannot be specified with die-cut labels,
this command is sent with a margin amount of 0."
(from section 2.2.3 Explanation of print data for the test page)
Continuous tape:
cut cut
-----------|--------------------------------------------|--------------
| | | | | |
----->| | |<------- printable area ----------->| | |<---------
| | | | | |
-----------|--------------------------------------------|--------------
|<->|<->| < margins margins > |<->|<->|
Die-cut labels (assumption, but was wrong!):
cut cut
-----------|--------------------------------------------|-------------------
-------+ | +------------------------------------+ | +---------------
| | | | | |
------>| | |<---------- printable area -------->| | |<--------------
| | | | | |
-------+ | +------------------------------------+ | +---+-----------
-----------|--------------------------------------------|-------------------
Die-cut labels, margin handling (reality):
cut cut
-----------|--------------------------------------------|-------------------
-------+ | +------------------------------------+ | +---------------
| | | | | | | |
------>| | | |<------- printable area ----->| | | |<--------------
| | | | | | | |
-------+ | +------------------------------------+ | +---+-----------
-----------|--------------------------------------------|-------------------
|<->|<>| < margins margins > |<>|<->|
^---- implicit margin added by the printer
^------- implicit margin added by the printer
*
- Attention
- The top and bottom margins of 35 dots are implicit for die-cut labels. The printer doesn't print in these areas, even if data was sent for them.
It is even more worse: data sent for these areas (e.g. lines of data) will not be ignored. The printer increases the size of the label instead.
And the next cut is made inside the following label - instead of inbetween them.
- Note
- To be sent at the beginning of a page and required at each page (according to the manual)
◆ ql_print_information()
static __wur int ql_print_information |
( |
struct ql_drv * |
t, |
|
|
int |
media_type, |
|
|
int |
media_width, |
|
|
int |
media_length, |
|
|
int |
raster, |
|
|
int |
start_page, |
|
|
int |
quality |
|
) |
| |
|
static |
Send information about the job or the next page
- Parameters
-
[in] | t | Full job description |
[in] | media_type | QL_MEDIA_TYPE_CONTINUOUS or QL_MEDIA_TYPE_DIE_CUT, negative value for not defined |
[in] | media_width | Width of the to be printed medium in [mm], negative value for not defined |
[in] | media_length | Length of the to be printed media in [mm] ('0' for continuous roll), negative value for not defined |
[in] | raster | Count of rasterlines of one "page", negative value for not defined |
[in] | start_page | '0' for the first page, '1' for continuous page |
[in] | quality | QL_QUALITY_PRINT or QL_FAST_PRINT |
- Return values
-
The manual encodes this info (as an example):
- This is the command for “1.1" × 3.5" (29 mm × 90 mm)” die-cut labels.
into:
1b 69 7A 8F 0B 1D 5A DF 03 00 00 00 00
^^___ Starting page
^^_^^_^^_^^______ 991 raster lines ~83 mm
^^__________________ 90 mm length
^^_____________________ 29 mm width
^^________________________ Media type: die cut
^^___________________________ 8F: 10x0 1111
^_ ????
^__ Media type valid
^___ Width valid
^____ Length valid
^______ Raster invalid (vague interpretation!)
^________ fast print
^_________ Recovery
For the DK1201 roll (die-cut 29 mm x 90 mm label), the QL800 datasheet defines:
- width: 342 dots
- heigt: 1061 dots (= top margin + printable height + top/bottom margin)
- printable width: 306 dots
- printable height: 991 dots
- left/right margin: 18 dots
- top/bottom margin: 35 dots Note: all at 300 DPI
- Note
- To be sent at the beginning of a page and required at each page (according to the manual)
◆ ql_job_header_generate()
int ql_job_header_generate |
( |
struct ql_drv * |
t | ) |
|
Send the heading commands to setup the printer prior a print job
- Parameters
-
[in] | t | Full job description |
Called once per print job at the beginning
◆ ql_page_header_generate()
int ql_page_header_generate |
( |
struct ql_drv * |
t, |
|
|
int |
first_page |
|
) |
| |
- Parameters
-
- Return values
-
0 | On success |
-ENODEV | Device seems gone (e.g. channel to the next stage is gone) |
Called once per page at the beginning
- Note
- In case of -ENODEV it makes no sense trying to send any further data or commands
- Precondition
- The ql_job::trim member must be up to date, e.g. its content matches the current raster page header
- Todo:
Deal with QL_FAST_PRINT/QL_QUALITY_PRINT for monochrome use case
Do the QL_QUALITY_PRINT and QL_HIGH_RESOLUTION bits depend on each other?
Deal with auto cut setting and when to cut (and if the printer has a cutter). To make it simple: only "cut at end" and "cut each" should be supported
◆ ql_auto_powerdown()
int ql_auto_powerdown |
( |
struct ql_drv * |
t, |
|
|
unsigned short |
time_out |
|
) |
| |
- Note
- This command is reverse-engineered, it isn't listed in the programming manual
-
The big endian format for the subcommand's data (here
time_val
) is guessed only. All other printer commands use little endian for multibyte parameter. So, the command's data might have a different format/content than listed here
◆ ql_auto_powerup()
int ql_auto_powerup |
( |
struct ql_drv * |
t, |
|
|
unsigned short |
mode |
|
) |
| |
- Note
- This command is reverse-engineered, it isn't listed in the programming manual
-
The big endian format for the subcommand's data (here
mode
) is guessed only. All other commands use little endian for multibyte parameter. So, the command's data might have a different format/content than listed here