]>
Commit | Line | Data |
---|---|---|
8e3807e7 | 1 | /* |
c9d3f842 | 2 | * "$Id$" |
8e3807e7 | 3 | * |
4 | * USB port backend for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * This file is included from "usb.c" when compiled on UNIX/Linux. | |
7 | * | |
c9d3f842 | 8 | * Copyright 1997-2005 by Easy Software Products, all rights reserved. |
8e3807e7 | 9 | * |
10 | * These coded instructions, statements, and computer programs are the | |
11 | * property of Easy Software Products and are protected by Federal | |
12 | * copyright law. Distribution and use rights are outlined in the file | |
13 | * "LICENSE" which should have been included with this file. If this | |
14 | * file is missing or damaged please contact Easy Software Products | |
15 | * at: | |
16 | * | |
17 | * Attn: CUPS Licensing Information | |
18 | * Easy Software Products | |
19 | * 44141 Airport View Drive, Suite 204 | |
c9d3f842 | 20 | * Hollywood, Maryland 20636 USA |
8e3807e7 | 21 | * |
22 | * Voice: (301) 373-9600 | |
23 | * EMail: cups-info@cups.org | |
24 | * WWW: http://www.cups.org | |
25 | * | |
26 | * This file is subject to the Apple OS-Developed Software exception. | |
27 | * | |
28 | * Contents: | |
29 | * | |
30 | * main() - Send a file to the specified USB port. | |
31 | * list_devices() - List all USB devices. | |
32 | */ | |
33 | ||
34 | /* | |
35 | * Include necessary headers. | |
36 | */ | |
37 | ||
8e3807e7 | 38 | #ifdef __linux |
39 | # include <sys/ioctl.h> | |
40 | # include <linux/lp.h> | |
41 | # define IOCNR_GET_DEVICE_ID 1 | |
42 | ||
43 | /* | |
44 | * Get device_id string | |
45 | */ | |
46 | # define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) | |
47 | #endif /* __linux */ | |
48 | ||
49 | #ifdef __sun | |
50 | # ifdef __sparc | |
51 | # include <sys/ecppio.h> | |
52 | # else | |
53 | # include <sys/ioccom.h> | |
54 | # include <sys/ecppsys.h> | |
55 | # endif /* __sparc */ | |
56 | #endif /* __sun */ | |
57 | ||
58 | ||
59 | /* | |
60 | * Local functions... | |
61 | */ | |
62 | ||
63 | void decode_device_id(int port, const char *device_id, | |
64 | char *make_model, int mmsize, | |
65 | char *uri, int urisize); | |
66 | int open_device(const char *uri); | |
67 | ||
68 | ||
69 | /* | |
70 | * 'print_device()' - Print a file to a USB device. | |
71 | */ | |
72 | ||
73 | int /* O - Exit status */ | |
74 | print_device(const char *uri, /* I - Device URI */ | |
75 | const char *hostname, /* I - Hostname/manufacturer */ | |
76 | const char *resource, /* I - Resource/modelname */ | |
77 | const char *options, /* I - Device options/serial number */ | |
78 | int fp, /* I - File descriptor to print */ | |
79 | int copies) /* I - Copies to print */ | |
80 | { | |
81 | int fd; /* USB device */ | |
82 | int wbytes; /* Number of bytes written */ | |
83 | size_t nbytes, /* Number of bytes read */ | |
84 | tbytes; /* Total number of bytes written */ | |
85 | char buffer[8192], /* Output buffer */ | |
86 | *bufptr; /* Pointer into buffer */ | |
87 | struct termios opts; /* Parallel port options */ | |
88 | #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) | |
89 | struct sigaction action; /* Actions for POSIX signals */ | |
90 | #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ | |
91 | #ifdef __linux | |
e8f77a45 | 92 | unsigned int status; /* Port status (off-line, out-of-paper, etc.) */ |
8e3807e7 | 93 | #endif /* __linux */ |
94 | ||
95 | ||
96 | /* | |
97 | * Open the USB port device... | |
98 | */ | |
99 | ||
100 | do | |
101 | { | |
102 | if ((fd = open_device(uri)) == -1) | |
103 | { | |
104 | if (errno == EBUSY) | |
105 | { | |
106 | fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr); | |
107 | sleep(30); | |
108 | } | |
109 | else if (errno == ENXIO || errno == EIO || errno == ENOENT) | |
110 | { | |
111 | fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr); | |
112 | sleep(30); | |
113 | } | |
114 | else | |
115 | { | |
116 | fprintf(stderr, "ERROR: Unable to open USB device \"%s\": %s\n", | |
117 | uri, strerror(errno)); | |
118 | return (1); | |
119 | } | |
120 | } | |
121 | } | |
122 | while (fd < 0); | |
123 | ||
124 | /* | |
125 | * Set any options provided... | |
126 | */ | |
127 | ||
128 | tcgetattr(fd, &opts); | |
129 | ||
130 | opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */ | |
131 | ||
132 | /**** No options supported yet ****/ | |
133 | ||
134 | tcsetattr(fd, TCSANOW, &opts); | |
135 | ||
136 | /* | |
137 | * Now that we are "connected" to the port, ignore SIGTERM so that we | |
138 | * can finish out any page data the driver sends (e.g. to eject the | |
139 | * current page... Only ignore SIGTERM if we are printing data from | |
140 | * stdin (otherwise you can't cancel raw jobs...) | |
141 | */ | |
142 | ||
ab652145 | 143 | if (!fp) |
8e3807e7 | 144 | { |
145 | #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ | |
146 | sigset(SIGTERM, SIG_IGN); | |
147 | #elif defined(HAVE_SIGACTION) | |
148 | memset(&action, 0, sizeof(action)); | |
149 | ||
150 | sigemptyset(&action.sa_mask); | |
151 | action.sa_handler = SIG_IGN; | |
152 | sigaction(SIGTERM, &action, NULL); | |
153 | #else | |
154 | signal(SIGTERM, SIG_IGN); | |
155 | #endif /* HAVE_SIGSET */ | |
156 | } | |
157 | ||
158 | #if defined(__linux) && defined(LP_POUTPA) | |
159 | /* | |
160 | * Show the printer status before we send the file; normally, we'd | |
161 | * do this while we write data to the printer, however at least some | |
162 | * Linux kernels have buggy USB drivers which don't like to be | |
163 | * queried while sending data to the printer... | |
164 | * | |
165 | * Also, we're using the 8255 constants instead of the ones that are | |
166 | * supposed to be used, as it appears that the USB driver also doesn't | |
167 | * follow standards... | |
168 | */ | |
169 | ||
170 | if (ioctl(fd, LPGETSTATUS, &status) == 0) | |
171 | { | |
172 | fprintf(stderr, "DEBUG: LPGETSTATUS returned a port status of %02X...\n", status); | |
173 | ||
174 | if (status & LP_POUTPA) | |
175 | fputs("WARNING: Media tray empty!\n", stderr); | |
176 | else if (!(status & LP_PERRORP)) | |
177 | fputs("WARNING: Printer fault!\n", stderr); | |
178 | else if (!(status & LP_PSELECD)) | |
179 | fputs("WARNING: Printer off-line.\n", stderr); | |
180 | } | |
181 | #endif /* __linux && LP_POUTPA */ | |
182 | ||
183 | /* | |
184 | * Finally, send the print file... | |
185 | */ | |
186 | ||
897922a9 | 187 | wbytes = 0; |
188 | ||
8e3807e7 | 189 | while (copies > 0) |
190 | { | |
191 | copies --; | |
192 | ||
193 | if (fp != 0) | |
194 | { | |
195 | fputs("PAGE: 1 1\n", stderr); | |
196 | lseek(fp, 0, SEEK_SET); | |
197 | } | |
198 | ||
199 | tbytes = 0; | |
200 | while ((nbytes = read(fp, buffer, sizeof(buffer))) > 0) | |
201 | { | |
202 | /* | |
203 | * Write the print data to the printer... | |
204 | */ | |
205 | ||
206 | tbytes += nbytes; | |
207 | bufptr = buffer; | |
208 | ||
209 | while (nbytes > 0) | |
210 | { | |
211 | ||
212 | if ((wbytes = write(fd, bufptr, nbytes)) < 0) | |
213 | if (errno == ENOTTY) | |
214 | wbytes = write(fd, bufptr, nbytes); | |
215 | ||
216 | if (wbytes < 0) | |
217 | { | |
218 | perror("ERROR: Unable to send print file to printer"); | |
219 | break; | |
220 | } | |
221 | ||
222 | nbytes -= wbytes; | |
223 | bufptr += wbytes; | |
224 | } | |
225 | ||
226 | if (wbytes < 0) | |
227 | break; | |
228 | ||
229 | if (fp) | |
230 | fprintf(stderr, "INFO: Sending print file, %lu bytes...\n", | |
231 | (unsigned long)tbytes); | |
232 | } | |
233 | } | |
234 | ||
235 | /* | |
236 | * Close the USB port and return... | |
237 | */ | |
238 | ||
239 | close(fd); | |
240 | ||
897922a9 | 241 | return (wbytes < 0); |
8e3807e7 | 242 | } |
243 | ||
244 | ||
245 | /* | |
246 | * 'decode_device_id()' - Decode the IEEE-1284 device ID string. | |
247 | */ | |
248 | ||
249 | void | |
250 | decode_device_id(int port, /* I - Port number */ | |
251 | const char *device_id, /* I - 1284 device ID string */ | |
252 | char *make_model, /* O - Make/model */ | |
253 | int mmsize, /* I - Size of buffer */ | |
254 | char *uri, /* O - Device URI */ | |
255 | int urisize) /* I - Size of buffer */ | |
256 | { | |
257 | char *attr, /* 1284 attribute */ | |
258 | *delim, /* 1284 delimiter */ | |
259 | *uriptr, /* Pointer into URI */ | |
260 | *mfg, /* Manufacturer string */ | |
261 | *mdl, /* Model string */ | |
262 | serial_number[1024]; /* Serial number string */ | |
263 | ||
264 | ||
265 | /* | |
266 | * Look for the description field... | |
267 | */ | |
268 | ||
269 | if ((attr = strstr(device_id, "DES:")) != NULL) | |
270 | attr += 4; | |
271 | else if ((attr = strstr(device_id, "DESCRIPTION:")) != NULL) | |
272 | attr += 12; | |
273 | ||
274 | if ((mfg = strstr(device_id, "MANUFACTURER:")) != NULL) | |
275 | mfg += 13; | |
276 | else if ((mfg = strstr(device_id, "MFG:")) != NULL) | |
277 | mfg += 4; | |
278 | ||
279 | if ((mdl = strstr(device_id, "MODEL:")) != NULL) | |
280 | mdl += 6; | |
281 | else if ((mdl = strstr(device_id, "MDL:")) != NULL) | |
282 | mdl += 4; | |
283 | ||
284 | if (attr) | |
285 | { | |
286 | if (strncasecmp(attr, "Hewlett-Packard ", 16) == 0) | |
287 | { | |
288 | strlcpy(make_model, "HP ", mmsize); | |
289 | strlcpy(make_model + 3, attr + 16, mmsize - 3); | |
290 | } | |
291 | else | |
292 | { | |
293 | strlcpy(make_model, attr, mmsize); | |
294 | } | |
295 | ||
296 | if ((delim = strchr(make_model, ';')) != NULL) | |
297 | *delim = '\0'; | |
298 | } | |
299 | else if (mfg && mdl) | |
300 | { | |
301 | /* | |
302 | * Build a make-model string from the manufacturer and model attributes... | |
303 | */ | |
304 | ||
305 | strlcpy(make_model, mfg, mmsize); | |
306 | ||
307 | if ((delim = strchr(make_model, ';')) != NULL) | |
308 | *delim = '\0'; | |
309 | ||
310 | strlcat(make_model, " ", mmsize); | |
311 | strlcat(make_model, mdl, mmsize); | |
312 | ||
313 | if ((delim = strchr(make_model, ';')) != NULL) | |
314 | *delim = '\0'; | |
315 | } | |
316 | else | |
317 | { | |
318 | /* | |
319 | * Use "Unknown" as the printer make and model... | |
320 | */ | |
321 | ||
322 | strlcpy(make_model, "Unknown", mmsize); | |
323 | } | |
324 | ||
325 | /* | |
326 | * Look for the serial number field... | |
327 | */ | |
328 | ||
329 | if ((attr = strstr(device_id, "SERN:")) != NULL) | |
330 | attr += 5; | |
331 | else if ((attr = strstr(device_id, "SERIALNUMBER:")) != NULL) | |
332 | attr += 13; | |
333 | else if ((attr = strstr(device_id, ";SN:")) != NULL) | |
334 | attr += 4; | |
335 | ||
336 | if (mfg) | |
337 | { | |
338 | /* | |
339 | * Make sure manufacturer is truncated at delimiter... | |
340 | */ | |
341 | ||
342 | if ((delim = strchr(mfg, ';')) != NULL) | |
343 | *delim = '\0'; | |
344 | } | |
345 | ||
346 | if (mdl) | |
347 | { | |
348 | /* | |
349 | * Make sure model is truncated at delimiter... | |
350 | */ | |
351 | ||
352 | if ((delim = strchr(mdl, ';')) != NULL) | |
353 | *delim = '\0'; | |
354 | } | |
355 | ||
356 | if (attr) | |
357 | { | |
358 | strlcpy(serial_number, attr, sizeof(serial_number)); | |
359 | ||
360 | if ((delim = strchr(serial_number, ';')) != NULL) | |
361 | *delim = '\0'; | |
362 | } | |
363 | else | |
364 | serial_number[0] = '\0'; | |
365 | ||
366 | /* | |
367 | * Generate the device URI from the make_model and serial number strings. | |
368 | */ | |
369 | ||
370 | strlcpy(uri, "usb://", urisize); | |
371 | for (uriptr = uri + 6, delim = make_model; | |
372 | *delim && uriptr < (uri + urisize - 1); | |
373 | delim ++) | |
374 | if (*delim == ' ') | |
375 | { | |
376 | delim ++; | |
377 | *uriptr++ = '/'; | |
378 | break; | |
379 | } | |
380 | else | |
381 | *uriptr++ = *delim; | |
382 | ||
383 | for (; *delim && uriptr < (uri + urisize - 3); delim ++) | |
384 | if (*delim == ' ') | |
385 | { | |
386 | *uriptr++ = '%'; | |
387 | *uriptr++ = '2'; | |
388 | *uriptr++ = '0'; | |
389 | } | |
390 | else | |
391 | *uriptr++ = *delim; | |
392 | ||
393 | *uriptr = '\0'; | |
394 | ||
395 | if (serial_number[0]) | |
396 | { | |
397 | /* | |
398 | * Add the serial number to the URI... | |
399 | */ | |
400 | ||
401 | strlcat(uri, "?serial=", urisize); | |
402 | strlcat(uri, serial_number, urisize); | |
403 | } | |
404 | } | |
405 | ||
406 | ||
407 | /* | |
408 | * 'list_devices()' - List all USB devices. | |
409 | */ | |
410 | ||
411 | void | |
412 | list_devices(void) | |
413 | { | |
414 | #ifdef __linux | |
415 | int i; /* Looping var */ | |
416 | int length; /* Length of device ID info */ | |
417 | int fd; /* File descriptor */ | |
418 | char format[255], /* Format for device filename */ | |
419 | device[255], /* Device filename */ | |
420 | device_id[1024], /* Device ID string */ | |
421 | device_uri[1024], /* Device URI string */ | |
422 | make_model[1024]; /* Make and model */ | |
423 | ||
424 | ||
425 | /* | |
426 | * First figure out which USB printer filename to use... | |
427 | */ | |
428 | ||
6f96d00f | 429 | if (access("/dev/usblp0", 0) == 0) |
430 | strcpy(format, "/dev/usblp%d"); | |
8e3807e7 | 431 | else if (access("/dev/usb/usblp0", 0) == 0) |
432 | strcpy(format, "/dev/usb/usblp%d"); | |
433 | else | |
6f96d00f | 434 | strcpy(format, "/dev/usb/lp%d"); |
8e3807e7 | 435 | |
436 | /* | |
437 | * Then open each USB device... | |
438 | */ | |
439 | ||
440 | for (i = 0; i < 16; i ++) | |
441 | { | |
442 | sprintf(device, format, i); | |
443 | ||
444 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
445 | { | |
446 | if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0) | |
447 | { | |
448 | length = (((unsigned)device_id[0] & 255) << 8) + | |
449 | ((unsigned)device_id[1] & 255); | |
450 | ||
451 | /* | |
452 | * Check to see if the length is larger than our buffer; first | |
453 | * assume that the vendor incorrectly implemented the 1284 spec, | |
454 | * and then limit the length to the size of our buffer... | |
455 | */ | |
456 | ||
457 | if (length > (sizeof(device_id) - 2)) | |
458 | length = (((unsigned)device_id[1] & 255) << 8) + | |
459 | ((unsigned)device_id[0] & 255); | |
460 | ||
461 | if (length > (sizeof(device_id) - 2)) | |
462 | length = sizeof(device_id) - 2; | |
463 | ||
464 | memmove(device_id, device_id + 2, length); | |
465 | device_id[length] = '\0'; | |
466 | } | |
467 | else | |
468 | device_id[0] = '\0'; | |
469 | ||
470 | close(fd); | |
471 | } | |
472 | else | |
473 | device_id[0] = '\0'; | |
474 | ||
475 | if (device_id[0]) | |
476 | { | |
477 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
478 | device_uri, sizeof(device_uri)); | |
479 | ||
480 | printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri, | |
481 | make_model, i + 1); | |
482 | } | |
483 | else | |
484 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); | |
485 | } | |
486 | #elif defined(__sgi) | |
487 | #elif defined(__sun) | |
488 | int i; /* Looping var */ | |
489 | int fd; /* File descriptor */ | |
490 | char device[255], /* Device filename */ | |
491 | device_id[1024], /* Device ID string */ | |
492 | device_uri[1024], /* Device URI string */ | |
493 | make_model[1024]; /* Make and model */ | |
494 | # ifdef ECPPIOC_GETDEVID | |
495 | struct ecpp_device_id did; /* Device ID buffer */ | |
496 | # endif /* ECPPIOC_GETDEVID */ | |
497 | ||
498 | ||
499 | /* | |
500 | * Open each USB device... | |
501 | */ | |
502 | ||
503 | for (i = 0; i < 8; i ++) | |
504 | { | |
505 | sprintf(device, "/dev/usb/printer%d", i); | |
506 | ||
507 | # ifndef ECPPIOC_GETDEVID | |
508 | if (!access(device, 0)) | |
509 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); | |
510 | # else | |
511 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
512 | { | |
513 | did.mode = ECPP_CENTRONICS; | |
514 | did.len = sizeof(device_id); | |
515 | did.rlen = 0; | |
516 | did.addr = device_id; | |
517 | ||
518 | if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0) | |
519 | { | |
520 | if (did.rlen < (sizeof(device_id) - 1)) | |
521 | device_id[did.rlen] = '\0'; | |
522 | else | |
523 | device_id[sizeof(device_id) - 1] = '\0'; | |
524 | } | |
525 | else | |
526 | device_id[0] = '\0'; | |
527 | ||
528 | close(fd); | |
529 | } | |
530 | else | |
531 | device_id[0] = '\0'; | |
532 | ||
533 | if (device_id[0]) | |
534 | { | |
535 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
536 | device_uri, sizeof(device_uri)); | |
537 | ||
538 | printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri, | |
539 | make_model, i + 1); | |
540 | } | |
541 | else | |
542 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); | |
543 | # endif /* !ECPPIOC_GETDEVID */ | |
544 | } | |
545 | #elif defined(__hpux) | |
546 | #elif defined(__osf) | |
547 | #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | |
548 | int i; /* Looping var */ | |
549 | char device[255]; /* Device filename */ | |
550 | ||
551 | ||
552 | for (i = 0; i < 8; i ++) | |
553 | { | |
554 | sprintf(device, "/dev/ulpt%d", i); | |
555 | if (!access(device, 0)) | |
556 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); | |
557 | ||
558 | sprintf(device, "/dev/unlpt%d", i); | |
559 | if (!access(device, 0)) | |
560 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1); | |
561 | } | |
562 | #endif | |
563 | } | |
564 | ||
565 | ||
566 | /* | |
567 | * 'open_device()' - Open a USB device... | |
568 | */ | |
569 | ||
570 | int /* O - File descriptor or -1 on error */ | |
571 | open_device(const char *uri) /* I - Device URI */ | |
572 | { | |
573 | /* | |
574 | * The generic implementation just treats the URI as a device filename... | |
575 | * Specific operating systems may also support using the device serial | |
576 | * number and/or make/model. | |
577 | */ | |
578 | ||
579 | if (strncmp(uri, "usb:/dev/", 9) == 0) | |
580 | return (open(uri + 4, O_RDWR | O_EXCL)); | |
581 | #ifdef __linux | |
582 | else if (strncmp(uri, "usb://", 6) == 0) | |
583 | { | |
584 | /* | |
585 | * For Linux, try looking up the device serial number or model... | |
586 | */ | |
587 | ||
588 | int i; /* Looping var */ | |
589 | int busy; /* Are any ports busy? */ | |
590 | int length; /* Length of device ID info */ | |
591 | int fd; /* File descriptor */ | |
592 | char format[255], /* Format for device filename */ | |
593 | device[255], /* Device filename */ | |
594 | device_id[1024], /* Device ID string */ | |
595 | make_model[1024], /* Make and model */ | |
596 | device_uri[1024]; /* Device URI string */ | |
597 | ||
598 | ||
599 | /* | |
600 | * First figure out which USB printer filename to use... | |
601 | */ | |
602 | ||
6f96d00f | 603 | if (access("/dev/usblp0", 0) == 0) |
604 | strcpy(format, "/dev/usblp%d"); | |
8e3807e7 | 605 | else if (access("/dev/usb/usblp0", 0) == 0) |
606 | strcpy(format, "/dev/usb/usblp%d"); | |
607 | else | |
6f96d00f | 608 | strcpy(format, "/dev/usb/lp%d"); |
8e3807e7 | 609 | |
610 | /* | |
611 | * Then find the correct USB device... | |
612 | */ | |
613 | ||
614 | do | |
615 | { | |
616 | for (busy = 0, i = 0; i < 16; i ++) | |
617 | { | |
618 | sprintf(device, format, i); | |
619 | ||
620 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
621 | { | |
622 | if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0) | |
623 | { | |
624 | length = (((unsigned)device_id[0] & 255) << 8) + | |
625 | ((unsigned)device_id[1] & 255); | |
626 | memmove(device_id, device_id + 2, length); | |
627 | device_id[length] = '\0'; | |
628 | } | |
629 | else | |
630 | device_id[0] = '\0'; | |
631 | } | |
632 | else | |
633 | { | |
634 | /* | |
635 | * If the open failed because it was busy, flag it so we retry | |
636 | * as needed... | |
637 | */ | |
638 | ||
639 | if (errno == EBUSY) | |
640 | busy = 1; | |
641 | ||
642 | device_id[0] = '\0'; | |
643 | } | |
644 | ||
645 | if (device_id[0]) | |
646 | { | |
647 | /* | |
648 | * Got the device ID - is this the one? | |
649 | */ | |
650 | ||
651 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
652 | device_uri, sizeof(device_uri)); | |
653 | ||
654 | if (strcmp(uri, device_uri) == 0) | |
655 | { | |
656 | /* | |
657 | * Yes, return this file descriptor... | |
658 | */ | |
659 | ||
660 | fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device); | |
661 | ||
662 | return (fd); | |
663 | } | |
664 | } | |
665 | ||
666 | /* | |
667 | * This wasn't the one... | |
668 | */ | |
669 | ||
670 | if (fd >= 0) | |
671 | close(fd); | |
672 | } | |
673 | ||
674 | /* | |
675 | * If we get here and at least one of the printer ports showed up | |
676 | * as "busy", then sleep for a bit and retry... | |
677 | */ | |
678 | ||
679 | if (busy) | |
680 | { | |
681 | fputs("INFO: USB printer is busy; will retry in 5 seconds...\n", | |
682 | stderr); | |
683 | sleep(5); | |
684 | } | |
685 | } | |
686 | while (busy); | |
687 | ||
688 | /* | |
689 | * Couldn't find the printer, return "no such device or address"... | |
690 | */ | |
691 | ||
692 | errno = ENODEV; | |
693 | ||
694 | return (-1); | |
695 | } | |
696 | #elif defined(__sun) && defined(ECPPIOC_GETDEVID) | |
697 | else if (strncmp(uri, "usb://", 6) == 0) | |
698 | { | |
699 | /* | |
700 | * For Solaris, try looking up the device serial number or model... | |
701 | */ | |
702 | ||
703 | int i; /* Looping var */ | |
704 | int busy; /* Are any ports busy? */ | |
705 | int fd; /* File descriptor */ | |
706 | char device[255], /* Device filename */ | |
707 | device_id[1024], /* Device ID string */ | |
708 | make_model[1024], /* Make and model */ | |
709 | device_uri[1024]; /* Device URI string */ | |
710 | struct ecpp_device_id did; /* Device ID buffer */ | |
711 | ||
712 | ||
713 | /* | |
714 | * Find the correct USB device... | |
715 | */ | |
716 | ||
717 | do | |
718 | { | |
63412dfd | 719 | for (i = 0, busy = 0; i < 8; i ++) |
8e3807e7 | 720 | { |
721 | sprintf(device, "/dev/usb/printer%d", i); | |
722 | ||
723 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
724 | { | |
725 | did.mode = ECPP_CENTRONICS; | |
726 | did.len = sizeof(device_id); | |
727 | did.rlen = 0; | |
728 | did.addr = device_id; | |
729 | ||
730 | if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0) | |
731 | { | |
732 | if (did.rlen < (sizeof(device_id) - 1)) | |
733 | device_id[did.rlen] = '\0'; | |
734 | else | |
735 | device_id[sizeof(device_id) - 1] = '\0'; | |
736 | } | |
737 | else | |
738 | device_id[0] = '\0'; | |
739 | } | |
740 | else | |
741 | { | |
742 | /* | |
743 | * If the open failed because it was busy, flag it so we retry | |
744 | * as needed... | |
745 | */ | |
746 | ||
747 | if (errno == EBUSY) | |
748 | busy = 1; | |
749 | ||
750 | device_id[0] = '\0'; | |
751 | } | |
752 | ||
753 | if (device_id[0]) | |
754 | { | |
755 | /* | |
756 | * Got the device ID - is this the one? | |
757 | */ | |
758 | ||
759 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
760 | device_uri, sizeof(device_uri)); | |
761 | ||
762 | if (strcmp(uri, device_uri) == 0) | |
763 | return (fd); /* Yes, return this file descriptor... */ | |
764 | } | |
765 | ||
766 | /* | |
767 | * This wasn't the one... | |
768 | */ | |
769 | ||
770 | if (fd >= 0) | |
771 | close(fd); | |
772 | } | |
773 | ||
774 | /* | |
775 | * If we get here and at least one of the printer ports showed up | |
776 | * as "busy", then sleep for a bit and retry... | |
777 | */ | |
778 | ||
779 | if (busy) | |
780 | { | |
781 | fputs("INFO: USB printer is busy; will retry in 5 seconds...\n", | |
782 | stderr); | |
783 | sleep(5); | |
784 | } | |
785 | } | |
786 | while (busy); | |
787 | ||
788 | /* | |
789 | * Couldn't find the printer, return "no such device or address"... | |
790 | */ | |
791 | ||
792 | errno = ENODEV; | |
793 | ||
794 | return (-1); | |
795 | } | |
796 | #endif /* __linux */ | |
797 | else | |
798 | { | |
799 | errno = ENODEV; | |
800 | return (-1); | |
801 | } | |
802 | } | |
803 | ||
804 | ||
805 | /* | |
c9d3f842 | 806 | * End of "$Id$". |
8e3807e7 | 807 | */ |