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