]> git.ipfire.org Git - thirdparty/cups.git/blob - backend/usb.c
Report both unlpt and ulpt devices under *BSD.
[thirdparty/cups.git] / backend / usb.c
1 /*
2 * "$Id: usb.c,v 1.31 2002/08/09 00:08:29 mike Exp $"
3 *
4 * USB port backend for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2002 by Easy Software Products, all rights reserved.
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 * This file is subject to the Apple OS-Developed Software exception.
25 *
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>
39 #include <errno.h>
40 #include <cups/string.h>
41 #include <signal.h>
42
43 #ifdef WIN32
44 # include <io.h>
45 #else
46 # include <unistd.h>
47 # include <fcntl.h>
48 # include <termios.h>
49 #endif /* WIN32 */
50
51
52 /*
53 * Local functions...
54 */
55
56 void 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
67 int /* O - Exit status */
68 main(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) */
77 int fp; /* Print file */
78 int copies; /* Number of copies to print */
79 int fd; /* Parallel device */
80 int wbytes; /* Number of bytes written */
81 size_t nbytes, /* Number of bytes read */
82 tbytes; /* Total number of bytes written */
83 char buffer[8192], /* Output buffer */
84 *bufptr; /* Pointer into buffer */
85 struct termios opts; /* Parallel port options */
86 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
87 struct sigaction action; /* Actions for POSIX signals */
88 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
89
90
91 /*
92 * Make sure status messages are not buffered...
93 */
94
95 setbuf(stderr, NULL);
96
97 /*
98 * Check command-line...
99 */
100
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 {
119 fp = 0;
120 copies = 1;
121 }
122 else
123 {
124 /*
125 * Try to open the print file...
126 */
127
128 if ((fp = open(argv[6], O_RDONLY)) < 0)
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
161 do
162 {
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 }
170 else if (errno == ENXIO || errno == EIO || errno == ENOENT)
171 {
172 fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr);
173 sleep(30);
174 }
175 else
176 {
177 fprintf(stderr, "ERROR: Unable to open USB port device file \"%s\": %s\n",
178 resource, strerror(errno));
179 return (1);
180 }
181 }
182 }
183 while (fd < 0);
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
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... Only ignore SIGTERM if we are printing data from
201 * stdin (otherwise you can't cancel raw jobs...)
202 */
203
204 if (argc < 7)
205 {
206 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
207 sigset(SIGTERM, SIG_IGN);
208 #elif defined(HAVE_SIGACTION)
209 memset(&action, 0, sizeof(action));
210
211 sigemptyset(&action.sa_mask);
212 action.sa_handler = SIG_IGN;
213 sigaction(SIGTERM, &action, NULL);
214 #else
215 signal(SIGTERM, SIG_IGN);
216 #endif /* HAVE_SIGSET */
217 }
218
219 /*
220 * Finally, send the print file...
221 */
222
223 while (copies > 0)
224 {
225 copies --;
226
227 if (fp != 0)
228 {
229 fputs("PAGE: 1 1\n", stderr);
230 lseek(fp, 0, SEEK_SET);
231 }
232
233 tbytes = 0;
234 while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0)
235 {
236 /*
237 * Write the print data to the printer...
238 */
239
240 tbytes += nbytes;
241 bufptr = buffer;
242
243 while (nbytes > 0)
244 {
245 if ((wbytes = write(fd, bufptr, nbytes)) < 0)
246 if (errno == ENOTTY)
247 wbytes = write(fd, bufptr, nbytes);
248
249 if (wbytes < 0)
250 {
251 perror("ERROR: Unable to send print file to printer");
252 break;
253 }
254
255 nbytes -= wbytes;
256 bufptr += wbytes;
257 }
258
259 if (argc > 6)
260 fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
261 (unsigned long)tbytes);
262 }
263 }
264
265 /*
266 * Close the socket connection and input file and return...
267 */
268
269 close(fd);
270 if (fp != 0)
271 close(fp);
272
273 fputs("INFO: Ready to print.\n", stderr);
274
275 return (0);
276 }
277
278
279 /*
280 * 'list_devices()' - List all USB devices.
281 */
282
283 void
284 list_devices(void)
285 {
286 #ifdef __linux
287 int i; /* Looping var */
288 int fd; /* File descriptor */
289 char device[255]; /* Device filename */
290 FILE *probe; /* /proc/bus/usb/devices file */
291 char line[1024], /* Line from file */
292 *delim, /* Delimiter in file */
293 make[IPP_MAX_NAME], /* Make from file */
294 model[IPP_MAX_NAME]; /* Model from file */
295
296
297 /*
298 * First try opening one of the USB devices to load the driver
299 * module as needed...
300 */
301
302 if ((fd = open("/dev/usb/lp0", O_WRONLY)) >= 0)
303 close(fd); /* 2.3.x and 2.4.x */
304 else if ((fd = open("/dev/usb/usblp0", O_WRONLY)) >= 0)
305 close(fd); /* Mandrake 7.x */
306 else if ((fd = open("/dev/usblp0", O_WRONLY)) >= 0)
307 close(fd); /* 2.2.x */
308
309 /*
310 * Then look at the device list for the USB bus...
311 */
312
313 if ((probe = fopen("/proc/bus/usb/devices", "r")) != NULL)
314 {
315 /*
316 * Scan the device list...
317 */
318
319 i = 0;
320
321 memset(make, 0, sizeof(make));
322 memset(model, 0, sizeof(model));
323
324 while (fgets(line, sizeof(line), probe) != NULL)
325 {
326 /*
327 * Strip trailing newline.
328 */
329
330 if ((delim = strrchr(line, '\n')) != NULL)
331 *delim = '\0';
332
333 /*
334 * See if it is a printer device ("P: ...")
335 */
336
337 if (strncmp(line, "S:", 2) == 0)
338 {
339 /*
340 * String attribute...
341 */
342
343 if (strncmp(line, "S: Manufacturer=", 17) == 0)
344 {
345 strlcpy(make, line + 17, sizeof(make));
346 if (strcmp(make, "Hewlett-Packard") == 0)
347 strcpy(make, "HP");
348 }
349 else if (strncmp(line, "S: Product=", 12) == 0)
350 strlcpy(model, line + 12, sizeof(model));
351 }
352 else if (strncmp(line, "I:", 2) == 0 &&
353 (strstr(line, "Driver=printer") != NULL ||
354 strstr(line, "Driver=usblp") != NULL) &&
355 make[0] && model[0])
356 {
357 /*
358 * We were processing a printer device; send the info out...
359 */
360
361 sprintf(device, "/dev/usb/lp%d", i);
362 if (access(device, 0))
363 {
364 sprintf(device, "/dev/usb/usblp%d", i);
365
366 if (access(device, 0))
367 sprintf(device, "/dev/usblp%d", i);
368 }
369
370 printf("direct usb:%s \"%s %s\" \"USB Printer #%d\"\n",
371 device, make, model, i + 1);
372
373 i ++;
374
375 memset(make, 0, sizeof(make));
376 memset(model, 0, sizeof(model));
377 }
378 }
379
380 fclose(probe);
381
382 /*
383 * Write empty device listings for unused USB devices...
384 */
385
386 for (; i < 16; i ++)
387 {
388 sprintf(device, "/dev/usb/lp%d", i);
389
390 if (access(device, 0))
391 {
392 sprintf(device, "/dev/usb/usblp%d", i);
393
394 if (access(device, 0))
395 {
396 sprintf(device, "/dev/usblp%d", i);
397
398 if (access(device, 0))
399 continue;
400 }
401 }
402
403 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
404 }
405 }
406 else
407 {
408 /*
409 * Just check manually for USB devices...
410 */
411
412 for (i = 0; i < 16; i ++)
413 {
414 sprintf(device, "/dev/usb/lp%d", i);
415
416 if (access(device, 0))
417 {
418 sprintf(device, "/dev/usb/usblp%d", i);
419
420 if (access(device, 0))
421 {
422 sprintf(device, "/dev/usblp%d", i);
423
424 if (access(device, 0))
425 continue;
426 }
427 }
428
429 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1);
430 }
431 }
432 #elif defined(__sgi)
433 #elif defined(__sun)
434 #elif defined(__hpux)
435 #elif defined(__osf)
436 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
437 int i; /* Looping var */
438 char device[255]; /* Device filename */
439
440
441 for (i = 0; i < 8; i ++)
442 {
443 sprintf(device, "/dev/ulpt%d", i);
444 if (!access(device, 0))
445 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (ulpt)\"\n", device, i + 1);
446
447 sprintf(device, "/dev/unlpt%d", i);
448 if (!access(device, 0))
449 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\" (unlpt)\n", device, i + 1);
450 }
451 #endif
452 }
453
454
455 /*
456 * End of "$Id: usb.c,v 1.31 2002/08/09 00:08:29 mike Exp $".
457 */