]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | <!-- |
bc44d920 | 2 | "$Id: api-filter.shtml 6649 2007-07-11 21:46:42Z mike $" |
ef416fc2 | 3 | |
4 | Filter and backend API introduction for the Common UNIX Printing System (CUPS). | |
5 | ||
bc44d920 | 6 | Copyright 2007 by Apple Inc. |
7 | Copyright 1997-2006 by Easy Software Products, all rights reserved. | |
ef416fc2 | 8 | |
9 | These coded instructions, statements, and computer programs are the | |
bc44d920 | 10 | property of Apple Inc. and are protected by Federal copyright |
11 | law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
12 | which should have been included with this file. If this file is | |
13 | file is missing or damaged, see the license at "http://www.cups.org/". | |
ef416fc2 | 14 | --> |
15 | ||
16 | <h2 class='title'>Introduction</h2> | |
17 | ||
ecdc0628 | 18 | <p>The CUPS filter and backend APIs define standard exit codes |
19 | and provide access to the backchannel data stream. They are only | |
20 | used when writing backends, filters, and port monitors.</p> | |
ef416fc2 | 21 | |
22 | <h2 class='title'>General Usage</h2> | |
23 | ||
24 | <p>The <var><cups/backend.h></var> and | |
25 | <var><cups/cups.h></var> header files must be included to | |
26 | use the <tt>CUPS_BACKEND_</tt> constants and | |
ecdc0628 | 27 | <tt>cupsBackChannel</tt> functions, respectively.</p> |
ef416fc2 | 28 | |
f7deaa1a | 29 | <p>The <var><cups/sidechannel.h></var> header file must be |
30 | included to use the <tt>CUPS_SC_</tt> constants and <tt>cupsSideChannel</tt> functions.</p> | |
31 | ||
ef416fc2 | 32 | <p>Programs using these functions must be linked to the CUPS |
33 | library: <var>libcups.a</var>, <var>libcups.so.2</var>, | |
34 | <var>libcups.2.dylib</var>, <var>libcups_s.a</var>, or | |
35 | <var>libcups2.lib</var> depending on the platform. The following | |
36 | command compiles <var>myprogram.c</var> using GCC and the CUPS | |
37 | library:</p> | |
38 | ||
39 | <pre class='command'> | |
40 | <kbd>gcc -o myprogram myprogram.c -lcups</kbd> | |
41 | </pre> | |
42 | ||
f7deaa1a | 43 | |
ef416fc2 | 44 | <h2 class='title'>Compatibility</h2> |
45 | ||
f7deaa1a | 46 | <p>The <tt>cupsBackChannel</tt> functions require CUPS 1.2 or higher. The <tt>cupsSideChannel</tt> functions require CUPS 1.3 or higher.</p> |
47 | ||
48 | ||
49 | <h2 class='title'>Using the cupsBackChannel APIs</h2> | |
50 | ||
51 | <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> | |
52 | ||
53 | <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> | |
54 | ||
55 | <pre class='command'> | |
56 | #include <cups/cups.h> | |
57 | ||
58 | char buffer[8192]; | |
59 | ssize_t bytes; | |
60 | ||
61 | /* Use a timeout of 0.0 seconds to poll for back-channel data */ | |
62 | bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0.0); | |
63 | </pre> | |
64 | ||
65 | <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> | |
66 | ||
67 | <pre class='command'> | |
68 | #include <cups/cups.h> | |
69 | ||
70 | char buffer[8192]; | |
71 | ssize_t bytes; | |
72 | ||
73 | /* Use a timeout of 1.0 seconds to give filters a chance to read */ | |
74 | cupsBackChannelWrite(buffer, bytes, 1.0); | |
75 | </pre> | |
76 | ||
77 | ||
78 | <h2 class='title'>Using the cupsSideChannel APIs</h2> | |
79 | ||
80 | <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> | |
81 | ||
82 | <ul> | |
83 | ||
84 | <li><tt>CUPS_SC_CMD_SOFT_RESET</tt> - Do a soft reset</li> | |
85 | <li><tt>CUPS_SC_CMD_DRAIN_OUTPUT</tt> - Drain all pending output</li> | |
86 | <li><tt>CUPS_SC_CMD_GET_BIDI</tt> - Return bidirectional capabilities</li> | |
87 | <li><tt>CUPS_SC_CMD_GET_DEVICE_ID</tt> - Return the IEEE-1284 device ID</li> | |
88 | <li><tt>CUPS_SC_CMD_GET_STATE</tt> - Return the device state</li> | |
89 | ||
90 | </ul> | |
91 | ||
92 | ||
93 | <h3>Sending Commands from a Filter, Driver, or Port Monitor</h3> | |
94 | ||
95 | <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> | |
96 | ||
97 | <pre class='command'> | |
98 | cups_sc_status_t cupsSideChannelDoRequest(cups_sc_command_t command, | |
99 | char *data, int *datalen, | |
100 | double timeout); | |
101 | </pre> | |
102 | ||
103 | <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> | |
104 | ||
105 | <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> | |
106 | ||
107 | <pre class='command'> | |
108 | #include <cups/sidechannel.h> | |
109 | ||
110 | char data; | |
111 | int datalen; | |
112 | cups_sc_bidi_t bidi; | |
113 | cups_sc_status_t status; | |
114 | ||
115 | /* Tell cupsSideChannelDoRequest() how big our buffer is... */ | |
116 | datalen = 1; | |
117 | ||
118 | /* Get the bidirectional capabilities, waiting for up to 1 second */ | |
119 | status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, &data, &datalen, 1.0); | |
120 | ||
121 | /* Use the returned value if OK was returned and the length is still 1 */ | |
122 | if (status == CUPS_SC_STATUS_OK && datalen == 1) | |
123 | bidi = (cups_sc_bidi_t)data; | |
124 | else | |
125 | bidi = CUPS_SC_BIDI_NOT_SUPPORTED; | |
126 | </pre> | |
127 | ||
128 | <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> | |
129 | ||
130 | <pre class='command'> | |
131 | #include <cups/sidechannel.h> | |
132 | ||
133 | char data[2049]; | |
134 | int datalen; | |
135 | cups_sc_status_t status; | |
136 | ||
137 | /* Tell cupsSideChannelDoRequest() how big our buffer is, less 1 byte for nul-termination... */ | |
138 | datalen = sizeof(data) - 1; | |
139 | ||
140 | /* Get the IEEE-1284 device ID, waiting for up to 1 second */ | |
141 | status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_DEVICE_ID, data, &datalen, 1.0); | |
142 | ||
143 | /* Use the returned value if OK was returned and the length is non-zero */ | |
144 | if (status == CUPS_SC_STATUS_OK && datalen > 0) | |
145 | data[datalen] = '\0'; | |
146 | else | |
147 | data[0] = '\0'; | |
148 | </pre> | |
149 | ||
150 | <p><tt>CUPS_SC_CMD_GET_STATE</tt> returns a single <tt>char</tt> value that tells you the current device state:</p> | |
151 | ||
152 | <pre class='command'> | |
153 | #include <cups/sidechannel.h> | |
154 | ||
155 | char data; | |
156 | int datalen; | |
157 | cups_sc_state_t state; | |
158 | cups_sc_status_t status; | |
159 | ||
160 | /* Tell cupsSideChannelDoRequest() how big our buffer is... */ | |
161 | datalen = 1; | |
162 | ||
163 | /* Get the bidirectional capabilities, waiting for up to 1 second */ | |
164 | status = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_STATE, &data, &datalen, 1.0); | |
165 | ||
166 | /* Use the returned value if OK was returned and the length is still 1 */ | |
167 | if (status == CUPS_SC_STATUS_OK && datalen == 1) | |
168 | state = (cups_sc_state_t)data; | |
169 | else | |
170 | state = CUPS_SC_STATE_OFFLINE; | |
171 | </pre> | |
172 | ||
173 | ||
174 | <h3>Handling Commands in your Backend</h3> | |
175 | ||
176 | <p>The <tt>cupsSideChannelRead()</tt> function is used by backends to read a command from a filter, driver, or port monitor:</p> | |
177 | ||
178 | <pre class='command'> | |
179 | int cupsSideChannelRead(cups_sc_command_t &command, | |
180 | cups_sc_status_t &status, | |
181 | char *data, int *datalen, double timeout); | |
182 | </pre> | |
183 | ||
184 | <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> | |
185 | ||
186 | <p>Once a command is processed, the backend uses the <tt>cupsSideChannelWrite()</tt> function to send its response:</p> | |
187 | ||
188 | <pre class='command'> | |
189 | #include <cups/sidechannel.h> | |
190 | ||
191 | cups_sc_command_t command; | |
192 | cups_sc_status_t status; | |
193 | ||
194 | /* Poll for a command... */ | |
195 | if (!cupsSideChannelRead(&command, &status, NULL, NULL, 0.0)) | |
196 | { | |
197 | char data[2048]; | |
198 | int datalen; | |
199 | ||
200 | switch (command) | |
201 | { | |
202 | ... handle supported commands, file data/datalen/status with values as needed ... | |
203 | ||
204 | default : | |
205 | status = CUPS_SC_STATUS_NOT_IMPLEMENTED; | |
206 | datalen = 0; | |
207 | break; | |
208 | } | |
209 | ||
210 | /* Send a response... */ | |
211 | cupsSideChannelWrite(command, status, data, datalen, 1.0); | |
212 | } | |
213 | </pre> |