]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/usb.c
Mirror 1.1.x changes.
[thirdparty/cups.git] / backend / usb.c
CommitLineData
a2c6b8b1 1/*
34f927d3 2 * "$Id: usb.c,v 1.18.2.12 2002/08/09 00:08:49 mike Exp $"
a2c6b8b1 3 *
4 * USB port backend for the Common UNIX Printing System (CUPS).
5 *
839c43aa 6 * Copyright 1997-2002 by Easy Software Products, all rights reserved.
a2c6b8b1 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
dab1a4d8 24 * This file is subject to the Apple OS-Developed Software exception.
25 *
a2c6b8b1 26 * Contents:
27 *
28 * main() - Send a file to the specified USB port.
29 * list_devices() - List all USB devices.
30 */
31
32/*
33 * Include necessary headers.
34 */
35
36#include <cups/cups.h>
37#include <stdio.h>
38#include <stdlib.h>
a3e17a89 39#include <errno.h>
a2c6b8b1 40#include <cups/string.h>
4ff40357 41#include <signal.h>
a2c6b8b1 42
c3026ddc 43#ifdef WIN32
a2c6b8b1 44# include <io.h>
45#else
46# include <unistd.h>
47# include <fcntl.h>
48# include <termios.h>
c3026ddc 49#endif /* WIN32 */
a2c6b8b1 50
51
52/*
53 * Local functions...
54 */
55
56void list_devices(void);
57
58
59/*
60 * 'main()' - Send a file to the specified USB port.
61 *
62 * Usage:
63 *
64 * printer-uri job-id user title copies options [file]
65 */
66
67int /* O - Exit status */
68main(int argc, /* I - Number of command-line arguments (6 or 7) */
69 char *argv[]) /* I - Command-line arguments */
70{
71 char method[255], /* Method in URI */
72 hostname[1024], /* Hostname */
73 username[255], /* Username info (not used) */
74 resource[1024], /* Resource info (device and options) */
75 *options; /* Pointer to options */
76 int port; /* Port number (not used) */
267cf96a 77 int fp; /* Print file */
a2c6b8b1 78 int copies; /* Number of copies to print */
79 int fd; /* Parallel device */
1c33ff6a 80 int wbytes; /* Number of bytes written */
81 size_t nbytes, /* Number of bytes read */
a2c6b8b1 82 tbytes; /* Total number of bytes written */
1c33ff6a 83 char buffer[8192], /* Output buffer */
84 *bufptr; /* Pointer into buffer */
a2c6b8b1 85 struct termios opts; /* Parallel port options */
4ff40357 86#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
87 struct sigaction action; /* Actions for POSIX signals */
88#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
a2c6b8b1 89
90
4b23f3b3 91 /*
92 * Make sure status messages are not buffered...
93 */
94
95 setbuf(stderr, NULL);
96
97 /*
98 * Check command-line...
99 */
100
a2c6b8b1 101 if (argc == 1)
102 {
103 list_devices();
104 return (0);
105 }
106 else if (argc < 6 || argc > 7)
107 {
108 fputs("Usage: USB job-id user title copies options [file]\n", stderr);
109 return (1);
110 }
111
112 /*
113 * If we have 7 arguments, print the file named on the command-line.
114 * Otherwise, send stdin instead...
115 */
116
117 if (argc == 6)
118 {
267cf96a 119 fp = 0;
a2c6b8b1 120 copies = 1;
121 }
122 else
123 {
124 /*
125 * Try to open the print file...
126 */
127
267cf96a 128 if ((fp = open(argv[6], O_RDONLY)) < 0)
a2c6b8b1 129 {
130 perror("ERROR: unable to open print file");
131 return (1);
132 }
133
134 copies = atoi(argv[4]);
135 }
136
137 /*
138 * Extract the device name and options from the URI...
139 */
140
141 httpSeparate(argv[0], method, username, hostname, &port, resource);
142
143 /*
144 * See if there are any options...
145 */
146
147 if ((options = strchr(resource, '?')) != NULL)
148 {
149 /*
150 * Yup, terminate the device name string and move to the first
151 * character of the options...
152 */
153
154 *options++ = '\0';
155 }
156
157 /*
158 * Open the USB port device...
159 */
160
a3e17a89 161 do
a2c6b8b1 162 {
a3e17a89 163 if ((fd = open(resource, O_WRONLY | O_EXCL)) == -1)
164 {
165 if (errno == EBUSY)
166 {
167 fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr);
168 sleep(30);
169 }
469e1f90 170 else if (errno == ENXIO || errno == EIO || errno == ENOENT)
4c2096b8 171 {
172 fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr);
173 sleep(30);
174 }
a3e17a89 175 else
176 {
7030b751 177 fprintf(stderr, "ERROR: Unable to open USB port device file \"%s\": %s\n",
178 resource, strerror(errno));
a3e17a89 179 return (1);
180 }
181 }
a2c6b8b1 182 }
a3e17a89 183 while (fd < 0);
a2c6b8b1 184
185 /*
186 * Set any options provided...
187 */
188
189 tcgetattr(fd, &opts);
190
191 opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
192
193 /**** No options supported yet ****/
194
195 tcsetattr(fd, TCSANOW, &opts);
196
4ff40357 197 /*
198 * Now that we are "connected" to the port, ignore SIGTERM so that we
199 * can finish out any page data the driver sends (e.g. to eject the
200 * current page...
201 */
202
203#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
204 sigset(SIGTERM, SIG_IGN);
205#elif defined(HAVE_SIGACTION)
206 memset(&action, 0, sizeof(action));
207
208 sigemptyset(&action.sa_mask);
209 action.sa_handler = SIG_IGN;
210 sigaction(SIGTERM, &action, NULL);
211#else
212 signal(SIGTERM, SIG_IGN);
213#endif /* HAVE_SIGSET */
214
a2c6b8b1 215 /*
216 * Finally, send the print file...
217 */
218
219 while (copies > 0)
220 {
221 copies --;
222
267cf96a 223 if (fp != 0)
a2c6b8b1 224 {
225 fputs("PAGE: 1 1\n", stderr);
267cf96a 226 lseek(fp, 0, SEEK_SET);
a2c6b8b1 227 }
228
229 tbytes = 0;
267cf96a 230 while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0)
a2c6b8b1 231 {
232 /*
233 * Write the print data to the printer...
234 */
235
1c33ff6a 236 tbytes += nbytes;
237 bufptr = buffer;
238
239 while (nbytes > 0)
a2c6b8b1 240 {
1c33ff6a 241 if ((wbytes = write(fd, bufptr, nbytes)) < 0)
242 if (errno == ENOTTY)
243 wbytes = write(fd, bufptr, nbytes);
244
245 if (wbytes < 0)
246 {
247 perror("ERROR: Unable to send print file to printer");
248 break;
249 }
250
251 nbytes -= wbytes;
252 bufptr += wbytes;
a2c6b8b1 253 }
a2c6b8b1 254
255 if (argc > 6)
ba31b514 256 fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
257 (unsigned long)tbytes);
a2c6b8b1 258 }
259 }
260
261 /*
262 * Close the socket connection and input file and return...
263 */
264
265 close(fd);
267cf96a 266 if (fp != 0)
267 close(fp);
a2c6b8b1 268
a540d367 269 fputs("INFO: Ready to print.\n", stderr);
270
a2c6b8b1 271 return (0);
272}
273
274
275/*
276 * 'list_devices()' - List all USB devices.
277 */
278
279void
280list_devices(void)
281{
282#ifdef __linux
283 int i; /* Looping var */
a2c6b8b1 284 int fd; /* File descriptor */
285 char device[255]; /* Device filename */
095ce1ee 286 FILE *probe; /* /proc/bus/usb/devices file */
a2c6b8b1 287 char line[1024], /* Line from file */
288 *delim, /* Delimiter in file */
289 make[IPP_MAX_NAME], /* Make from file */
290 model[IPP_MAX_NAME]; /* Model from file */
291
292
095ce1ee 293 /*
294 * First try opening one of the USB devices to load the driver
295 * module as needed...
296 */
297
298 if ((fd = open("/dev/usb/lp0", O_WRONLY)) >= 0)
299 close(fd); /* 2.3.x and 2.4.x */
e2ff7d86 300 else if ((fd = open("/dev/usb/usblp0", O_WRONLY)) >= 0)
301 close(fd); /* Mandrake 7.x */
095ce1ee 302 else if ((fd = open("/dev/usblp0", O_WRONLY)) >= 0)
303 close(fd); /* 2.2.x */
304
305 /*
306 * Then look at the device list for the USB bus...
307 */
308
a2c6b8b1 309 if ((probe = fopen("/proc/bus/usb/devices", "r")) != NULL)
310 {
095ce1ee 311 /*
312 * Scan the device list...
313 */
314
0abffe2c 315 i = 0;
a2c6b8b1 316
317 memset(make, 0, sizeof(make));
318 memset(model, 0, sizeof(model));
319
320 while (fgets(line, sizeof(line), probe) != NULL)
321 {
322 /*
323 * Strip trailing newline.
324 */
325
326 if ((delim = strrchr(line, '\n')) != NULL)
327 *delim = '\0';
328
329 /*
330 * See if it is a printer device ("P: ...")
331 */
332
0abffe2c 333 if (strncmp(line, "S:", 2) == 0)
a2c6b8b1 334 {
335 /*
336 * String attribute...
337 */
338
339 if (strncmp(line, "S: Manufacturer=", 17) == 0)
0abffe2c 340 {
def978d5 341 strlcpy(make, line + 17, sizeof(make));
0abffe2c 342 if (strcmp(make, "Hewlett-Packard") == 0)
343 strcpy(make, "HP");
344 }
a2c6b8b1 345 else if (strncmp(line, "S: Product=", 12) == 0)
def978d5 346 strlcpy(model, line + 12, sizeof(model));
a2c6b8b1 347 }
0abffe2c 348 else if (strncmp(line, "I:", 2) == 0 &&
25488c69 349 (strstr(line, "Driver=printer") != NULL ||
350 strstr(line, "Driver=usblp") != NULL) &&
0abffe2c 351 make[0] && model[0])
a2c6b8b1 352 {
353 /*
354 * We were processing a printer device; send the info out...
355 */
356
e2ff7d86 357 sprintf(device, "/dev/usb/lp%d", i);
358 if (access(device, 0))
359 {
360 sprintf(device, "/dev/usb/usblp%d", i);
361
362 if (access(device, 0))
363 sprintf(device, "/dev/usblp%d", i);
364 }
365
366 printf("direct usb:%s \"%s %s\" \"USB Printer #%d\"\n",
367 device, make, model, i + 1);
0abffe2c 368
a2c6b8b1 369 i ++;
370
371 memset(make, 0, sizeof(make));
372 memset(model, 0, sizeof(model));
373 }
a2c6b8b1 374 }
375
376 fclose(probe);
753453e4 377
378 /*
379 * Write empty device listings for unused USB devices...
380 */
381
382 for (; i < 16; i ++)
383 {
384 sprintf(device, "/dev/usb/lp%d", i);
385
386 if (access(device, 0))
387 {
388 sprintf(device, "/dev/usb/usblp%d", i);
389
390 if (access(device, 0))
391 {
392 sprintf(device, "/dev/usblp%d", i);
393
394 if (access(device, 0))
395 continue;
396 }
397 }
398
399 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
400 }
a2c6b8b1 401 }
402 else
403 {
095ce1ee 404 /*
753453e4 405 * Just check manually for USB devices...
095ce1ee 406 */
407
753453e4 408 for (i = 0; i < 16; i ++)
a2c6b8b1 409 {
c6a53438 410 sprintf(device, "/dev/usb/lp%d", i);
67436e05 411
753453e4 412 if (access(device, 0))
e2ff7d86 413 {
753453e4 414 sprintf(device, "/dev/usb/usblp%d", i);
e2ff7d86 415
753453e4 416 if (access(device, 0))
417 {
418 sprintf(device, "/dev/usblp%d", i);
419
420 if (access(device, 0))
421 continue;
422 }
67436e05 423 }
753453e4 424
425 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
a2c6b8b1 426 }
427 }
428#elif defined(__sgi)
429#elif defined(__sun)
430#elif defined(__hpux)
431#elif defined(__osf)
34f927d3 432#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
a3e17a89 433 int i; /* Looping var */
a3e17a89 434 char device[255]; /* Device filename */
435
b43fa007 436
34f927d3 437 for (i = 0; i < 8; i ++)
a3e17a89 438 {
34f927d3 439 sprintf(device, "/dev/ulpt%d", i);
753453e4 440 if (!access(device, 0))
34f927d3 441 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (ulpt)\"\n", device, i + 1);
bf18d74f 442
34f927d3 443 sprintf(device, "/dev/unlpt%d", i);
753453e4 444 if (!access(device, 0))
34f927d3 445 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\" (unlpt)\n", device, i + 1);
bf18d74f 446 }
447#endif
a2c6b8b1 448}
449
450
451/*
34f927d3 452 * End of "$Id: usb.c,v 1.18.2.12 2002/08/09 00:08:49 mike Exp $".
a2c6b8b1 453 */