]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> |
2 | <html> | |
3 | <!-- SECTION: Programming --> | |
4 | <head> | |
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; } | |
15 | --></style> | |
16 | </head> | |
17 | <body> | |
18 | <!-- | |
bc44d920 | 19 | "$Id: api-filter.shtml 6649 2007-07-11 21:46:42Z mike $" |
ef416fc2 | 20 | |
21 | Filter and backend API introduction for the Common UNIX Printing System (CUPS). | |
22 | ||
bc44d920 | 23 | Copyright 2007 by Apple Inc. |
24 | Copyright 1997-2006 by Easy Software Products, all rights reserved. | |
ef416fc2 | 25 | |
26 | These coded instructions, statements, and computer programs are the | |
bc44d920 | 27 | property of Apple Inc. and are protected by Federal copyright |
28 | law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
29 | which should have been included with this file. If this file is | |
30 | file is missing or damaged, see the license at "http://www.cups.org/". | |
ef416fc2 | 31 | --> |
32 | ||
33 | <h2 class='title'>Introduction</h2> | |
34 | ||
ecdc0628 | 35 | <p>The CUPS filter and backend APIs define standard exit codes |
36 | and provide access to the backchannel data stream. They are only | |
37 | used when writing backends, filters, and port monitors.</p> | |
ef416fc2 | 38 | |
39 | <h2 class='title'>General Usage</h2> | |
40 | ||
41 | <p>The <var><cups/backend.h></var> and | |
42 | <var><cups/cups.h></var> header files must be included to | |
43 | use the <tt>CUPS_BACKEND_</tt> constants and | |
ecdc0628 | 44 | <tt>cupsBackChannel</tt> functions, respectively.</p> |
ef416fc2 | 45 | |
f7deaa1a | 46 | <p>The <var><cups/sidechannel.h></var> header file must be |
47 | included to use the <tt>CUPS_SC_</tt> constants and <tt>cupsSideChannel</tt> functions.</p> | |
48 | ||
ef416fc2 | 49 | <p>Programs using these functions must be linked to the CUPS |
50 | library: <var>libcups.a</var>, <var>libcups.so.2</var>, | |
51 | <var>libcups.2.dylib</var>, <var>libcups_s.a</var>, or | |
52 | <var>libcups2.lib</var> depending on the platform. The following | |
53 | command compiles <var>myprogram.c</var> using GCC and the CUPS | |
54 | library:</p> | |
55 | ||
56 | <pre class='command'> | |
57 | <kbd>gcc -o myprogram myprogram.c -lcups</kbd> | |
58 | </pre> | |
59 | ||
f7deaa1a | 60 | |
ef416fc2 | 61 | <h2 class='title'>Compatibility</h2> |
62 | ||
f7deaa1a | 63 | <p>The <tt>cupsBackChannel</tt> functions require CUPS 1.2 or higher. The <tt>cupsSideChannel</tt> functions require CUPS 1.3 or higher.</p> |
64 | ||
65 | ||
66 | <h2 class='title'>Using the cupsBackChannel APIs</h2> | |
67 | ||
68 | <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> | |
69 | ||
70 | <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> | |
71 | ||
72 | <pre class='command'> | |
73 | #include <cups/cups.h> | |
74 | ||
75 | char buffer[8192]; | |
76 | ssize_t bytes; | |
77 | ||
78 | /* Use a timeout of 0.0 seconds to poll for back-channel data */ | |
79 | bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0.0); | |
80 | </pre> | |
81 | ||
82 | <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> | |
83 | ||
84 | <pre class='command'> | |
85 | #include <cups/cups.h> | |
86 | ||
87 | char buffer[8192]; | |
88 | ssize_t bytes; | |
89 | ||
90 | /* Use a timeout of 1.0 seconds to give filters a chance to read */ | |
91 | cupsBackChannelWrite(buffer, bytes, 1.0); | |
92 | </pre> | |
93 | ||
94 | ||
95 | <h2 class='title'>Using the cupsSideChannel APIs</h2> | |
96 | ||
97 | <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> | |
98 | ||
99 | <ul> | |
100 | ||
101 | <li><tt>CUPS_SC_CMD_SOFT_RESET</tt> - Do a soft reset</li> | |
102 | <li><tt>CUPS_SC_CMD_DRAIN_OUTPUT</tt> - Drain all pending output</li> | |
103 | <li><tt>CUPS_SC_CMD_GET_BIDI</tt> - Return bidirectional capabilities</li> | |
104 | <li><tt>CUPS_SC_CMD_GET_DEVICE_ID</tt> - Return the IEEE-1284 device ID</li> | |
105 | <li><tt>CUPS_SC_CMD_GET_STATE</tt> - Return the device state</li> | |
106 | ||
107 | </ul> | |
108 | ||
109 | ||
110 | <h3>Sending Commands from a Filter, Driver, or Port Monitor</h3> | |
111 | ||
112 | <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> | |
113 | ||
114 | <pre class='command'> | |
115 | cups_sc_status_t cupsSideChannelDoRequest(cups_sc_command_t command, | |
116 | char *data, int *datalen, | |
117 | double timeout); | |
118 | </pre> | |
119 | ||
120 | <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> | |
121 | ||
122 | <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> | |
123 | ||
124 | <pre class='command'> | |
125 | #include <cups/sidechannel.h> | |
126 | ||
127 | char data; | |
128 | int datalen; | |
129 | cups_sc_bidi_t bidi; | |
130 | cups_sc_status_t status; | |
131 | ||
132 | /* Tell cupsSideChannelDoRequest() how big our buffer is... */ | |
133 | datalen = 1; | |
134 | ||
135 | /* Get the bidirectional capabilities, waiting for up to 1 second */ | |
136 | status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, &data, &datalen, 1.0); | |
137 | ||
138 | /* Use the returned value if OK was returned and the length is still 1 */ | |
139 | if (status == CUPS_SC_STATUS_OK && datalen == 1) | |
140 | bidi = (cups_sc_bidi_t)data; | |
141 | else | |
142 | bidi = CUPS_SC_BIDI_NOT_SUPPORTED; | |
143 | </pre> | |
144 | ||
145 | <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> | |
146 | ||
147 | <pre class='command'> | |
148 | #include <cups/sidechannel.h> | |
149 | ||
150 | char data[2049]; | |
151 | int datalen; | |
152 | cups_sc_status_t status; | |
153 | ||
154 | /* Tell cupsSideChannelDoRequest() how big our buffer is, less 1 byte for nul-termination... */ | |
155 | datalen = sizeof(data) - 1; | |
156 | ||
157 | /* Get the IEEE-1284 device ID, waiting for up to 1 second */ | |
158 | status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_DEVICE_ID, data, &datalen, 1.0); | |
159 | ||
160 | /* Use the returned value if OK was returned and the length is non-zero */ | |
161 | if (status == CUPS_SC_STATUS_OK && datalen > 0) | |
162 | data[datalen] = '\0'; | |
163 | else | |
164 | data[0] = '\0'; | |
165 | </pre> | |
166 | ||
167 | <p><tt>CUPS_SC_CMD_GET_STATE</tt> returns a single <tt>char</tt> value that tells you the current device state:</p> | |
168 | ||
169 | <pre class='command'> | |
170 | #include <cups/sidechannel.h> | |
171 | ||
172 | char data; | |
173 | int datalen; | |
174 | cups_sc_state_t state; | |
175 | cups_sc_status_t status; | |
176 | ||
177 | /* Tell cupsSideChannelDoRequest() how big our buffer is... */ | |
178 | datalen = 1; | |
179 | ||
180 | /* Get the bidirectional capabilities, waiting for up to 1 second */ | |
181 | status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_STATE, &data, &datalen, 1.0); | |
182 | ||
183 | /* Use the returned value if OK was returned and the length is still 1 */ | |
184 | if (status == CUPS_SC_STATUS_OK && datalen == 1) | |
185 | state = (cups_sc_state_t)data; | |
186 | else | |
187 | state = CUPS_SC_STATE_OFFLINE; | |
188 | </pre> | |
189 | ||
190 | ||
191 | <h3>Handling Commands in your Backend</h3> | |
192 | ||
193 | <p>The <tt>cupsSideChannelRead()</tt> function is used by backends to read a command from a filter, driver, or port monitor:</p> | |
194 | ||
195 | <pre class='command'> | |
196 | int cupsSideChannelRead(cups_sc_command_t &command, | |
197 | cups_sc_status_t &status, | |
198 | char *data, int *datalen, double timeout); | |
199 | </pre> | |
200 | ||
201 | <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> | |
202 | ||
203 | <p>Once a command is processed, the backend uses the <tt>cupsSideChannelWrite()</tt> function to send its response:</p> | |
204 | ||
205 | <pre class='command'> | |
206 | #include <cups/sidechannel.h> | |
207 | ||
208 | cups_sc_command_t command; | |
209 | cups_sc_status_t status; | |
210 | ||
211 | /* Poll for a command... */ | |
212 | if (!cupsSideChannelRead(&command, &status, NULL, NULL, 0.0)) | |
213 | { | |
214 | char data[2048]; | |
215 | int datalen; | |
216 | ||
217 | switch (command) | |
218 | { | |
219 | ... handle supported commands, file data/datalen/status with values as needed ... | |
220 | ||
221 | default : | |
222 | status = CUPS_SC_STATUS_NOT_IMPLEMENTED; | |
223 | datalen = 0; | |
224 | break; | |
225 | } | |
226 | ||
227 | /* Send a response... */ | |
228 | cupsSideChannelWrite(command, status, data, datalen, 1.0); | |
229 | } | |
230 | </pre> | |
ef416fc2 | 231 | <h2 class='title'>Contents</h2> |
232 | <ul> | |
233 | <li><a href='#FUNCTIONS'>Functions</a></li> | |
234 | </ul> | |
235 | <!-- NEW PAGE --> | |
236 | <h2 class='title'><a name='FUNCTIONS'>Functions</a></h2> | |
237 | <ul> | |
ecdc0628 | 238 | <li><a href='#cupsBackChannelRead'><tt>cupsBackChannelRead()</tt></a> <span class='info'> CUPS 1.2 </span></li> |
239 | <li><a href='#cupsBackChannelWrite'><tt>cupsBackChannelWrite()</tt></a> <span class='info'> CUPS 1.2 </span></li> | |
f7deaa1a | 240 | <li><a href='#cupsSideChannelDoRequest'><tt>cupsSideChannelDoRequest()</tt></a> <span class='info'> CUPS 1.3 </span></li> |
241 | <li><a href='#cupsSideChannelRead'><tt>cupsSideChannelRead()</tt></a> <span class='info'> CUPS 1.3 </span></li> | |
242 | <li><a href='#cupsSideChannelWrite'><tt>cupsSideChannelWrite()</tt></a> <span class='info'> CUPS 1.3 </span></li> | |
ef416fc2 | 243 | </ul> |
244 | <!-- NEW PAGE --> | |
ecdc0628 | 245 | <h3 class='title'><span class='info'> CUPS 1.2 </span><a name='cupsBackChannelRead'>cupsBackChannelRead()</a></h3> |
ef416fc2 | 246 | <h4>Description</h4> |
247 | <p>Read data from the backchannel. | |
bc44d920 | 248 | <p>Reads up to "bytes" bytes from the backchannel. The "timeout" |
ef416fc2 | 249 | parameter controls how many seconds to wait for the data - use |
250 | 0.0 to return immediately if there is no data, -1.0 to wait | |
251 | for data indefinitely. | |
252 | ||
bc44d920 | 253 | |
ef416fc2 | 254 | <h4>Syntax</h4> |
bc44d920 | 255 | <p><tt> |
256 | ssize_t<br> | |
ecdc0628 | 257 | cupsBackChannelRead( |
ef416fc2 | 258 | char * buffer, |
ecdc0628 | 259 | size_t bytes, |
ef416fc2 | 260 | double timeout); |
bc44d920 | 261 | </tt></p> |
ef416fc2 | 262 | <h4>Arguments</h4> |
bc44d920 | 263 | <div class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' summary='Arguments'> |
ef416fc2 | 264 | <thead><tr><th>Name</th><th>Description</th></tr></thead> |
265 | <tbody> | |
266 | <tr><td><tt>buffer</tt></td><td>Buffer to read</td></tr> | |
267 | <tr><td><tt>bytes</tt></td><td>Bytes to read</td></tr> | |
268 | <tr><td><tt>timeout</tt></td><td>Timeout in seconds</td></tr> | |
269 | </tbody></table></div> | |
270 | <h4>Returns</h4> | |
271 | <p>Bytes read or -1 on error</p> | |
272 | <!-- NEW PAGE --> | |
ecdc0628 | 273 | <h3 class='title'><span class='info'> CUPS 1.2 </span><a name='cupsBackChannelWrite'>cupsBackChannelWrite()</a></h3> |
ef416fc2 | 274 | <h4>Description</h4> |
275 | <p>Write data to the backchannel. | |
bc44d920 | 276 | <p>Writes "bytes" bytes to the backchannel. The "timeout" parameter |
ef416fc2 | 277 | controls how many seconds to wait for the data to be written - use |
278 | 0.0 to return immediately if the data cannot be written, -1.0 to wait | |
279 | indefinitely. | |
280 | ||
bc44d920 | 281 | |
ef416fc2 | 282 | <h4>Syntax</h4> |
bc44d920 | 283 | <p><tt> |
284 | ssize_t<br> | |
ecdc0628 | 285 | cupsBackChannelWrite( |
ef416fc2 | 286 | const char * buffer, |
ecdc0628 | 287 | size_t bytes, |
ef416fc2 | 288 | double timeout); |
bc44d920 | 289 | </tt></p> |
ef416fc2 | 290 | <h4>Arguments</h4> |
bc44d920 | 291 | <div class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' summary='Arguments'> |
ef416fc2 | 292 | <thead><tr><th>Name</th><th>Description</th></tr></thead> |
293 | <tbody> | |
294 | <tr><td><tt>buffer</tt></td><td>Buffer to write</td></tr> | |
295 | <tr><td><tt>bytes</tt></td><td>Bytes to write</td></tr> | |
296 | <tr><td><tt>timeout</tt></td><td>Timeout in seconds</td></tr> | |
297 | </tbody></table></div> | |
298 | <h4>Returns</h4> | |
299 | <p>Bytes written or -1 on error</p> | |
f7deaa1a | 300 | <!-- NEW PAGE --> |
301 | <h3 class='title'><span class='info'> CUPS 1.3 </span><a name='cupsSideChannelDoRequest'>cupsSideChannelDoRequest()</a></h3> | |
302 | <h4>Description</h4> | |
303 | <p>Send a side-channel command to a backend and wait for a response. | |
bc44d920 | 304 | <p>This function is normally only called by filters, drivers, or port |
f7deaa1a | 305 | monitors in order to communicate with the backend used by the current |
306 | printer. Programs must be prepared to handle timeout or "not | |
307 | implemented" status codes, which indicate that the backend or device | |
308 | do not support the specified side-channel command. | |
bc44d920 | 309 | <p>The "datalen" parameter must be initialized to the size of the buffer |
f7deaa1a | 310 | pointed to by the "data" parameter. cupsSideChannelDoRequest() will |
311 | update the value to contain the number of data bytes in the buffer. | |
312 | ||
bc44d920 | 313 | |
f7deaa1a | 314 | <h4>Syntax</h4> |
bc44d920 | 315 | <p><tt> |
316 | <a href='#cups_sc_status_t'>cups_sc_status_t</a><br> | |
f7deaa1a | 317 | cupsSideChannelDoRequest( |
318 | cups_sc_command_t command, | |
319 | char * data, | |
320 | int * datalen, | |
321 | double timeout); | |
bc44d920 | 322 | </tt></p> |
f7deaa1a | 323 | <h4>Arguments</h4> |
bc44d920 | 324 | <div class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' summary='Arguments'> |
f7deaa1a | 325 | <thead><tr><th>Name</th><th>Description</th></tr></thead> |
326 | <tbody> | |
327 | <tr><td><tt>command</tt></td><td>Command to send</td></tr> | |
328 | <tr><td><tt>data</tt></td><td>Response data buffer pointer</td></tr> | |
329 | <tr><td><tt>datalen</tt></td><td>Size of data buffer on entry, number of bytes in buffer on return</td></tr> | |
330 | <tr><td><tt>timeout</tt></td><td>Timeout in seconds</td></tr> | |
331 | </tbody></table></div> | |
332 | <h4>Returns</h4> | |
333 | <p>Status of command</p> | |
334 | <!-- NEW PAGE --> | |
335 | <h3 class='title'><span class='info'> CUPS 1.3 </span><a name='cupsSideChannelRead'>cupsSideChannelRead()</a></h3> | |
336 | <h4>Description</h4> | |
337 | <p>Read a side-channel message. | |
bc44d920 | 338 | <p>This function is normally only called by backend programs to read |
f7deaa1a | 339 | commands from a filter, driver, or port monitor program. The |
340 | caller must be prepared to handle incomplete or invalid messages | |
341 | and return the corresponding status codes. | |
bc44d920 | 342 | <p>The "datalen" parameter must be initialized to the size of the buffer |
f7deaa1a | 343 | pointed to by the "data" parameter. cupsSideChannelDoRequest() will |
344 | update the value to contain the number of data bytes in the buffer. | |
345 | ||
bc44d920 | 346 | |
f7deaa1a | 347 | <h4>Syntax</h4> |
bc44d920 | 348 | <p><tt> |
349 | int<br> | |
f7deaa1a | 350 | cupsSideChannelRead( |
351 | cups_sc_command_t * command, | |
352 | <a href='#cups_sc_status_t'>cups_sc_status_t</a> * status, | |
353 | char * data, | |
354 | int * datalen, | |
355 | double timeout); | |
bc44d920 | 356 | </tt></p> |
f7deaa1a | 357 | <h4>Arguments</h4> |
bc44d920 | 358 | <div class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' summary='Arguments'> |
f7deaa1a | 359 | <thead><tr><th>Name</th><th>Description</th></tr></thead> |
360 | <tbody> | |
361 | <tr><td><tt>command</tt></td><td>Command code</td></tr> | |
362 | <tr><td><tt>status</tt></td><td>Status code</td></tr> | |
363 | <tr><td><tt>data</tt></td><td>Data buffer pointer</td></tr> | |
364 | <tr><td><tt>datalen</tt></td><td>Size of data buffer on entry, number of bytes in buffer on return</td></tr> | |
365 | <tr><td><tt>timeout</tt></td><td>Timeout in seconds</td></tr> | |
366 | </tbody></table></div> | |
367 | <h4>Returns</h4> | |
368 | <p>0 on success, -1 on error</p> | |
369 | <!-- NEW PAGE --> | |
370 | <h3 class='title'><span class='info'> CUPS 1.3 </span><a name='cupsSideChannelWrite'>cupsSideChannelWrite()</a></h3> | |
371 | <h4>Description</h4> | |
372 | <p>Write a side-channel message. | |
bc44d920 | 373 | <p>This function is normally only called by backend programs to send |
f7deaa1a | 374 | responses to a filter, driver, or port monitor program. |
375 | ||
bc44d920 | 376 | |
f7deaa1a | 377 | <h4>Syntax</h4> |
bc44d920 | 378 | <p><tt> |
379 | int<br> | |
f7deaa1a | 380 | cupsSideChannelWrite( |
381 | cups_sc_command_t command, | |
382 | <a href='#cups_sc_status_t'>cups_sc_status_t</a> status, | |
383 | const char * data, | |
384 | int datalen, | |
385 | double timeout); | |
bc44d920 | 386 | </tt></p> |
f7deaa1a | 387 | <h4>Arguments</h4> |
bc44d920 | 388 | <div class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' summary='Arguments'> |
f7deaa1a | 389 | <thead><tr><th>Name</th><th>Description</th></tr></thead> |
390 | <tbody> | |
391 | <tr><td><tt>command</tt></td><td>Command code</td></tr> | |
392 | <tr><td><tt>status</tt></td><td>Status code</td></tr> | |
393 | <tr><td><tt>data</tt></td><td>Data buffer pointer</td></tr> | |
394 | <tr><td><tt>datalen</tt></td><td>Number of bytes of data</td></tr> | |
395 | <tr><td><tt>timeout</tt></td><td>Timeout in seconds</td></tr> | |
396 | </tbody></table></div> | |
397 | <h4>Returns</h4> | |
398 | <p>0 on success, -1 on error</p> | |
ef416fc2 | 399 | </body> |
400 | </html> |