]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/scsi-linux.c
Import CUPS 1.4svn r7023 into easysw/current.
[thirdparty/cups.git] / backend / scsi-linux.c
CommitLineData
ef416fc2 1/*
2e4ff8af 2 * "$Id: scsi-linux.c 6834 2007-08-22 18:29:25Z mike $"
ef416fc2 3 *
4 * Linux SCSI printer support for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 by Apple Inc.
ef416fc2 7 * Copyright 2003-2005 by Easy Software Products, all rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the
11 * following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above
14 * copyright notice, this list of conditions and the
15 * following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the
18 * above copyright notice, this list of conditions and
19 * the following disclaimer in the documentation and/or
20 * other materials provided with the distribution.
21 *
22 * 3. All advertising materials mentioning features or use
23 * of this software must display the following
24 * acknowledgement:
25 *
26 * This product includes software developed by Easy
27 * Software Products.
28 *
29 * 4. The name of Easy Software Products may not be used to
30 * endorse or promote products derived from this software
31 * without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS
34 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
35 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
38 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
41 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
44 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
46 * DAMAGE.
47 *
48 * Contents:
49 *
50 * list_devices() - List the available SCSI printer devices.
51 * print_device() - Print a file to a SCSI device.
52 */
53
54/*
55 * Include necessary headers.
56 */
57
58#include <scsi/sg.h>
c0e1af83 59#include <cups/i18n.h>
ef416fc2 60
61
62/*
63 * We currently only support the Linux 2.4 generic SCSI interface.
64 */
65
66#ifndef SG_DXFER_TO_DEV
67/*
68 * Dummy functions that do nothing on unsupported platforms...
69 */
70void list_devices(void) {}
71int print_device(const char *resource, int fd, int copies) { return (1); }
72#else
73
74
75/*
76 * 'list_devices()' - List the available SCSI printer devices.
77 */
78
79void
80list_devices(void)
81{
82 puts("direct scsi \"Unknown\" \"SCSI Printer\"");
83}
84
85
86/*
87 * 'print_device()' - Print a file to a SCSI device.
88 */
89
90int /* O - Print status */
91print_device(const char *resource, /* I - SCSI device */
92 int fd, /* I - File to print */
93 int copies) /* I - Number of copies to print */
94{
95 int scsi_fd; /* SCSI file descriptor */
96 char buffer[8192]; /* Data buffer */
97 int bytes; /* Number of bytes */
98 int try; /* Current try */
99 sg_io_hdr_t scsi_req; /* SCSI request */
100 unsigned char scsi_cmd[6], /* SCSI command data */
101 scsi_sense[32]; /* SCSI sense data */
102# if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
103 struct sigaction action; /* Actions for POSIX signals */
104# endif /* HAVE_SIGACTION && !HAVE_SIGSET */
105
106
107 /*
108 * Make sure we have a valid resource name...
109 */
110
111 if (strncmp(resource, "/dev/sg", 7) != 0)
112 {
db1f069b
MS
113 _cupsLangPrintf(stderr, _("ERROR: Bad SCSI device file \"%s\"!\n"),
114 resource);
ef416fc2 115 return (CUPS_BACKEND_STOP);
116 }
117
118 /*
119 * Open the SCSI device file...
120 */
121
757d2cad 122 fputs("STATE: +connecting-to-device\n", stderr);
123
ef416fc2 124 do
125 {
126 if ((scsi_fd = open(resource, O_RDWR | O_EXCL)) == -1)
127 {
128 if (getenv("CLASS") != NULL)
129 {
130 /*
131 * If the CLASS environment variable is set, the job was submitted
132 * to a class and not to a specific queue. In this case, we want
133 * to abort immediately so that the job can be requeued on the next
134 * available printer in the class.
135 */
136
c0e1af83 137 _cupsLangPuts(stderr,
138 _("INFO: Unable to contact printer, queuing on next "
139 "printer in class...\n"));
ef416fc2 140
141 /*
142 * Sleep 5 seconds to keep the job from requeuing too rapidly...
143 */
144
145 sleep(5);
146
147 return (CUPS_BACKEND_FAILED);
148 }
149
150 if (errno != EAGAIN && errno != EBUSY)
151 {
db1f069b
MS
152 _cupsLangPrintf(stderr,
153 _("ERROR: Unable to open device file \"%s\": %s\n"),
154 resource, strerror(errno));
ef416fc2 155 return (CUPS_BACKEND_FAILED);
156 }
157 else
158 {
db1f069b
MS
159 _cupsLangPuts(stderr,
160 _("INFO: Printer busy; will retry in 30 seconds...\n"));
ef416fc2 161 sleep(30);
162 }
163 }
164 }
165 while (scsi_fd == -1);
166
757d2cad 167 fputs("STATE: -connecting-to-device\n", stderr);
168
ef416fc2 169 /*
170 * Now that we are "connected" to the port, ignore SIGTERM so that we
171 * can finish out any page data the driver sends (e.g. to eject the
172 * current page... Only ignore SIGTERM if we are printing data from
173 * stdin (otherwise you can't cancel raw jobs...)
174 */
175
176 if (fd != 0)
177 {
178# ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
179 sigset(SIGTERM, SIG_IGN);
180# elif defined(HAVE_SIGACTION)
181 memset(&action, 0, sizeof(action));
182
183 sigemptyset(&action.sa_mask);
184 action.sa_handler = SIG_IGN;
185 sigaction(SIGTERM, &action, NULL);
186# else
187 signal(SIGTERM, SIG_IGN);
188# endif /* HAVE_SIGSET */
189 }
190
191 /*
192 * Copy the print file to the device...
193 */
194
195 while (copies > 0)
196 {
197 if (fd != 0)
198 lseek(fd, 0, SEEK_SET);
199
200 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
201 {
202 memset(&scsi_req, 0, sizeof(scsi_req));
203
204 scsi_req.interface_id = 'S';
205 scsi_req.dxfer_direction = SG_DXFER_TO_DEV;
206 scsi_req.cmd_len = 6;
207 scsi_req.mx_sb_len = sizeof(scsi_sense);
208 scsi_req.iovec_count = 0;
209 scsi_req.dxfer_len = bytes;
210 scsi_req.dxferp = buffer;
211 scsi_req.cmdp = scsi_cmd;
212 scsi_req.sbp = scsi_sense;
213 scsi_req.timeout = 60 * 1000;
214
215 scsi_cmd[0] = 0x0a; /* Group 0 print command */
216 scsi_cmd[1] = 0x00;
217 scsi_cmd[2] = bytes / 65536;
218 scsi_cmd[3] = bytes / 256;
219 scsi_cmd[4] = bytes;
220 scsi_cmd[5] = 0x00;
221
222 for (try = 0; try < 10; try ++)
223 if (ioctl(scsi_fd, SG_IO, &scsi_req) < 0 ||
224 scsi_req.status != 0)
225 {
db1f069b
MS
226 _cupsLangPrintf(stderr,
227 _("WARNING: SCSI command timed out (%d); "
228 "retrying...\n"), scsi_req.status);
ef416fc2 229 sleep(try + 1);
230 }
231 else
232 break;
233
234 if (try >= 10)
235 {
db1f069b
MS
236 _cupsLangPrintf(stderr, _("ERROR: Unable to send print data (%d)\n"),
237 scsi_req.status);
ef416fc2 238 close(scsi_fd);
239 return (CUPS_BACKEND_FAILED);
240 }
241 }
242
243 copies --;
244 }
245
246 /*
247 * Close the device and return...
248 */
249
250 close(fd);
251
252 return (CUPS_BACKEND_OK);
253}
254#endif /* !SG_DXFER_TO_DEV */
255
256
257/*
2e4ff8af 258 * End of "$Id: scsi-linux.c 6834 2007-08-22 18:29:25Z mike $".
ef416fc2 259 */