1 <!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
3 <!-- SECTION: Programming -->
5 <title>Filter and Backend APIs
</title>
6 <meta name='keywords' content='Programming'
>
7 <meta name='creator' content='Mini-XML v2.3'
>
8 <style type='text/css'
><!--
9 h1, h2, h3, p { font-family: sans-serif; text-align: justify; }
10 tt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }
11 pre { font-weight: bold; color: #7f0000; margin-left: 2em; }
12 span.info { background: #000000; border: solid thin #000000; color: #ffffff; font-size: 80%; font-style: italic; font-weight: bold; white-space: nowrap; }
13 h3 span.info { float: right; font-size: 100%; }
14 h1.title, h2.title, h3.title { border-bottom: solid 2px #000000; }
19 "$Id: api-filter.shtml 5138 2006-02-21 10:49:06Z mike $"
21 Filter and backend API introduction for the Common UNIX Printing System (CUPS).
23 Copyright 1997-2006 by Easy Software Products.
25 These coded instructions, statements, and computer programs are the
26 property of Easy Software Products and are protected by Federal
27 copyright law. Distribution and use rights are outlined in the file
28 "LICENSE.txt" which should have been included with this file. If this
29 file is missing or damaged please contact Easy Software Products
32 Attn: CUPS Licensing Information
33 Easy Software Products
34 44141 Airport View Drive, Suite 204
35 Hollywood, Maryland 20636 USA
38 EMail: cups-info@cups.org
39 WWW: http://www.cups.org
42 <h2 class='title'
>Introduction
</h2>
44 <p>The CUPS filter and backend APIs define standard exit codes
45 and provide access to the backchannel data stream. They are only
46 used when writing backends, filters, and port monitors.
</p>
48 <h2 class='title'
>General Usage
</h2>
50 <p>The
<var><cups/backend.h
></var> and
51 <var><cups/cups.h
></var> header files must be included to
52 use the
<tt>CUPS_BACKEND_
</tt> constants and
53 <tt>cupsBackChannel
</tt> functions, respectively.
</p>
55 <p>The
<var><cups/sidechannel.h
></var> header file must be
56 included to use the
<tt>CUPS_SC_
</tt> constants and
<tt>cupsSideChannel
</tt> functions.
</p>
58 <p>Programs using these functions must be linked to the CUPS
59 library:
<var>libcups.a
</var>,
<var>libcups.so
.2</var>,
60 <var>libcups
.2.dylib
</var>,
<var>libcups_s.a
</var>, or
61 <var>libcups2.lib
</var> depending on the platform. The following
62 command compiles
<var>myprogram.c
</var> using GCC and the CUPS
66 <kbd>gcc -o myprogram myprogram.c -lcups
</kbd>
70 <h2 class='title'
>Compatibility
</h2>
72 <p>The
<tt>cupsBackChannel
</tt> functions require CUPS
1.2 or higher. The
<tt>cupsSideChannel
</tt> functions require CUPS
1.3 or higher.
</p>
75 <h2 class='title'
>Using the cupsBackChannel APIs
</h2>
77 <p>The
<tt>cupsBackChannel
</tt> APIs allow your filters, drivers, and port monitors to read data back from a printer and your backends to send data from a printer to the filters, drivers, and port monitors associated with the current job. Back-channel data is normally sent by the printer in response to a command sent from your program to the printer via
<tt>stdout
</tt>.
</p>
79 <p>The
<tt>cupsBackChannelRead()
</tt> function reads data from the printer via the backend. You provide a timeout in seconds along with a buffer pointer and the size of that buffer. It returns the number of bytes or -
1 if there was an error. The following code example shows how to poll for back-channel data in your program:
</p>
82 #include
<cups/cups.h
>
87 /* Use a timeout of
0.0 seconds to poll for back-channel data */
88 bytes = cupsBackChannelRead(buffer, sizeof(buffer),
0.0);
91 <p>If you are writing a backend, the
<tt>cupsBackChannelWrite()
</tt> function sends any back-channel data you have received from the printer to upstream filters in the print filter chain. We recommend using a timeout of
1.0 seconds:
</p>
94 #include
<cups/cups.h
>
99 /* Use a timeout of
1.0 seconds to give filters a chance to read */
100 cupsBackChannelWrite(buffer, bytes,
1.0);
104 <h2 class='title'
>Using the cupsSideChannel APIs
</h2>
106 <p>The
<tt>cupsSideChannel
</tt> APIs allow your filters, drivers, port monitors, and backend to send and receive the following out-of-band commands:
</p>
110 <li><tt>CUPS_SC_CMD_SOFT_RESET
</tt> - Do a soft reset
</li>
111 <li><tt>CUPS_SC_CMD_DRAIN_OUTPUT
</tt> - Drain all pending output
</li>
112 <li><tt>CUPS_SC_CMD_GET_BIDI
</tt> - Return bidirectional capabilities
</li>
113 <li><tt>CUPS_SC_CMD_GET_DEVICE_ID
</tt> - Return the IEEE-
1284 device ID
</li>
114 <li><tt>CUPS_SC_CMD_GET_STATE
</tt> - Return the device state
</li>
119 <h3>Sending Commands from a Filter, Driver, or Port Monitor
</h3>
121 <p>The
<tt>cupsSideChannelDoRequest()
</tt> function is used by filters, drivers, and port monitors to send a command to the backend and read back a response:
</p>
123 <pre class='command'
>
124 cups_sc_status_t cupsSideChannelDoRequest(cups_sc_command_t command,
125 char *data, int *datalen,
129 <p>The
<tt>CUPS_SC_CMD_SOFT_RESET
</tt> and
<tt>CUPS_SC_CMD_DRAIN_OUTPUT
</tt> commands do not return any data values, while the others return one or more bytes. The
<tt>timeout
</tt> parameter allows your program to poll or wait for the command to complete - use a timeout of
30 seconds for
<tt>CUPS_SC_CMD_SOFT_RESET
</tt> and
<tt>CUPS_SC_CMD_DRAIN_OUTPUT
</tt> and a timeout of
1 second for all other commands.
</p>
131 <p><tt>CUPS_SC_CMD_GET_BIDI
</tt> returns a single
<tt>char
</tt> value that tells you whether the backend supports bidirectional communications:
</p>
133 <pre class='command'
>
134 #include
<cups/sidechannel.h
>
139 cups_sc_status_t status;
141 /* Tell cupsSideChannelDoRequest() how big our buffer is... */
144 /* Get the bidirectional capabilities, waiting for up to
1 second */
145 status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI,
&data,
&datalen,
1.0);
147 /* Use the returned value if OK was returned and the length is still
1 */
148 if (status == CUPS_SC_STATUS_OK && datalen ==
1)
149 bidi = (cups_sc_bidi_t)data;
151 bidi = CUPS_SC_BIDI_NOT_SUPPORTED;
154 <p><tt>CUPS_SC_CMD_GET_DEVICE_ID
</tt> returns a string of characters containing the IEEE-
1284 device ID for the connected printer:
</p>
156 <pre class='command'
>
157 #include
<cups/sidechannel.h
>
161 cups_sc_status_t status;
163 /* Tell cupsSideChannelDoRequest() how big our buffer is, less
1 byte for nul-termination... */
164 datalen = sizeof(data) -
1;
166 /* Get the IEEE-
1284 device ID, waiting for up to
1 second */
167 status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_DEVICE_ID, data,
&datalen,
1.0);
169 /* Use the returned value if OK was returned and the length is non-zero */
170 if (status == CUPS_SC_STATUS_OK && datalen
> 0)
171 data[datalen] = '\
0';
176 <p><tt>CUPS_SC_CMD_GET_STATE
</tt> returns a single
<tt>char
</tt> value that tells you the current device state:
</p>
178 <pre class='command'
>
179 #include
<cups/sidechannel.h
>
183 cups_sc_state_t state;
184 cups_sc_status_t status;
186 /* Tell cupsSideChannelDoRequest() how big our buffer is... */
189 /* Get the bidirectional capabilities, waiting for up to
1 second */
190 status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_STATE,
&data,
&datalen,
1.0);
192 /* Use the returned value if OK was returned and the length is still
1 */
193 if (status == CUPS_SC_STATUS_OK && datalen ==
1)
194 state = (cups_sc_state_t)data;
196 state = CUPS_SC_STATE_OFFLINE;
200 <h3>Handling Commands in your Backend
</h3>
202 <p>The
<tt>cupsSideChannelRead()
</tt> function is used by backends to read a command from a filter, driver, or port monitor:
</p>
204 <pre class='command'
>
205 int cupsSideChannelRead(cups_sc_command_t
&command,
206 cups_sc_status_t
&status,
207 char *data, int *datalen, double timeout);
210 <p>Backends can either poll for commands using a
<tt>timeout
</tt> of
0.0, wait indefinitely for commands using a
<tt>timeout
</tt> of -
1.0 (probably in a separate thread for that purpose), or use
<tt>select()
</tt> or
<tt>poll()
</tt> on the
<tt>CUPS_SC_FD
</tt> file descriptor (
4) to handle input and output on several file descriptors at the same time. Backends can pass
<tt>NULL
</tt> for the
<tt>data
</tt> and
<tt>datalen
</tt> parameters, since none of the commands sent by upstream filters contain any data at this time.
</p>
212 <p>Once a command is processed, the backend uses the
<tt>cupsSideChannelWrite()
</tt> function to send its response:
</p>
214 <pre class='command'
>
215 #include
<cups/sidechannel.h
>
217 cups_sc_command_t command;
218 cups_sc_status_t status;
220 /* Poll for a command... */
221 if (!cupsSideChannelRead(
&command,
&status, NULL, NULL,
0.0))
228 ... handle supported commands, file data/datalen/status with values as needed ...
231 status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
236 /* Send a response... */
237 cupsSideChannelWrite(command, status, data, datalen,
1.0);
240 <h2 class='title'
>Contents
</h2>
242 <li><a href='#FUNCTIONS'
>Functions
</a></li>
245 <h2 class='title'
><a name='FUNCTIONS'
>Functions
</a></h2>
247 <li><a href='#cupsBackChannelRead'
><tt>cupsBackChannelRead()
</tt></a> <span class='info'
> CUPS
1.2 </span></li>
248 <li><a href='#cupsBackChannelWrite'
><tt>cupsBackChannelWrite()
</tt></a> <span class='info'
> CUPS
1.2 </span></li>
249 <li><a href='#cupsSideChannelDoRequest'
><tt>cupsSideChannelDoRequest()
</tt></a> <span class='info'
> CUPS
1.3 </span></li>
250 <li><a href='#cupsSideChannelRead'
><tt>cupsSideChannelRead()
</tt></a> <span class='info'
> CUPS
1.3 </span></li>
251 <li><a href='#cupsSideChannelWrite'
><tt>cupsSideChannelWrite()
</tt></a> <span class='info'
> CUPS
1.3 </span></li>
254 <h3 class='title'
><span class='info'
> CUPS
1.2 </span><a name='cupsBackChannelRead'
>cupsBackChannelRead()
</a></h3>
256 <p>Read data from the backchannel.
258 Reads up to
"bytes
" bytes from the backchannel. The
"timeout
"
259 parameter controls how many seconds to wait for the data - use
260 0.0 to return immediately if there is no data, -
1.0 to wait
261 for data indefinitely.
273 <div class='table'
><table align='center' border='
1' width='
80%' cellpadding='
5' cellspacing='
0'
>
274 <thead><tr><th>Name
</th><th>Description
</th></tr></thead>
276 <tr><td><tt>buffer
</tt></td><td>Buffer to read
</td></tr>
277 <tr><td><tt>bytes
</tt></td><td>Bytes to read
</td></tr>
278 <tr><td><tt>timeout
</tt></td><td>Timeout in seconds
</td></tr>
279 </tbody></table></div>
281 <p>Bytes read or -
1 on error
</p>
283 <h3 class='title'
><span class='info'
> CUPS
1.2 </span><a name='cupsBackChannelWrite'
>cupsBackChannelWrite()
</a></h3>
285 <p>Write data to the backchannel.
287 Writes
"bytes
" bytes to the backchannel. The
"timeout
" parameter
288 controls how many seconds to wait for the data to be written - use
289 0.0 to return immediately if the data cannot be written, -
1.0 to wait
296 cupsBackChannelWrite(
302 <div class='table'
><table align='center' border='
1' width='
80%' cellpadding='
5' cellspacing='
0'
>
303 <thead><tr><th>Name
</th><th>Description
</th></tr></thead>
305 <tr><td><tt>buffer
</tt></td><td>Buffer to write
</td></tr>
306 <tr><td><tt>bytes
</tt></td><td>Bytes to write
</td></tr>
307 <tr><td><tt>timeout
</tt></td><td>Timeout in seconds
</td></tr>
308 </tbody></table></div>
310 <p>Bytes written or -
1 on error
</p>
312 <h3 class='title'
><span class='info'
> CUPS
1.3 </span><a name='cupsSideChannelDoRequest'
>cupsSideChannelDoRequest()
</a></h3>
314 <p>Send a side-channel command to a backend and wait for a response.
316 This function is normally only called by filters, drivers, or port
317 monitors in order to communicate with the backend used by the current
318 printer. Programs must be prepared to handle timeout or
"not
319 implemented
" status codes, which indicate that the backend or device
320 do not support the specified side-channel command.
322 The
"datalen
" parameter must be initialized to the size of the buffer
323 pointed to by the
"data
" parameter. cupsSideChannelDoRequest() will
324 update the value to contain the number of data bytes in the buffer.
329 <a href='#cups_sc_status_t'
>cups_sc_status_t
</a>
330 cupsSideChannelDoRequest(
331 cups_sc_command_t command,
337 <div class='table'
><table align='center' border='
1' width='
80%' cellpadding='
5' cellspacing='
0'
>
338 <thead><tr><th>Name
</th><th>Description
</th></tr></thead>
340 <tr><td><tt>command
</tt></td><td>Command to send
</td></tr>
341 <tr><td><tt>data
</tt></td><td>Response data buffer pointer
</td></tr>
342 <tr><td><tt>datalen
</tt></td><td>Size of data buffer on entry, number of bytes in buffer on return
</td></tr>
343 <tr><td><tt>timeout
</tt></td><td>Timeout in seconds
</td></tr>
344 </tbody></table></div>
346 <p>Status of command
</p>
348 <h3 class='title'
><span class='info'
> CUPS
1.3 </span><a name='cupsSideChannelRead'
>cupsSideChannelRead()
</a></h3>
350 <p>Read a side-channel message.
352 This function is normally only called by backend programs to read
353 commands from a filter, driver, or port monitor program. The
354 caller must be prepared to handle incomplete or invalid messages
355 and return the corresponding status codes.
357 The
"datalen
" parameter must be initialized to the size of the buffer
358 pointed to by the
"data
" parameter. cupsSideChannelDoRequest() will
359 update the value to contain the number of data bytes in the buffer.
366 cups_sc_command_t * command,
367 <a href='#cups_sc_status_t'
>cups_sc_status_t
</a> * status,
373 <div class='table'
><table align='center' border='
1' width='
80%' cellpadding='
5' cellspacing='
0'
>
374 <thead><tr><th>Name
</th><th>Description
</th></tr></thead>
376 <tr><td><tt>command
</tt></td><td>Command code
</td></tr>
377 <tr><td><tt>status
</tt></td><td>Status code
</td></tr>
378 <tr><td><tt>data
</tt></td><td>Data buffer pointer
</td></tr>
379 <tr><td><tt>datalen
</tt></td><td>Size of data buffer on entry, number of bytes in buffer on return
</td></tr>
380 <tr><td><tt>timeout
</tt></td><td>Timeout in seconds
</td></tr>
381 </tbody></table></div>
383 <p>0 on success, -
1 on error
</p>
385 <h3 class='title'
><span class='info'
> CUPS
1.3 </span><a name='cupsSideChannelWrite'
>cupsSideChannelWrite()
</a></h3>
387 <p>Write a side-channel message.
389 This function is normally only called by backend programs to send
390 responses to a filter, driver, or port monitor program.
396 cupsSideChannelWrite(
397 cups_sc_command_t command,
398 <a href='#cups_sc_status_t'
>cups_sc_status_t
</a> status,
404 <div class='table'
><table align='center' border='
1' width='
80%' cellpadding='
5' cellspacing='
0'
>
405 <thead><tr><th>Name
</th><th>Description
</th></tr></thead>
407 <tr><td><tt>command
</tt></td><td>Command code
</td></tr>
408 <tr><td><tt>status
</tt></td><td>Status code
</td></tr>
409 <tr><td><tt>data
</tt></td><td>Data buffer pointer
</td></tr>
410 <tr><td><tt>datalen
</tt></td><td>Number of bytes of data
</td></tr>
411 <tr><td><tt>timeout
</tt></td><td>Timeout in seconds
</td></tr>
412 </tbody></table></div>
414 <p>0 on success, -
1 on error
</p>