]>
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 | { | |
1d5ef583 | 286 | /* |
287 | * Use description... | |
288 | */ | |
289 | ||
290 | if (!strncasecmp(attr, "Hewlett-Packard hp ", 19)) | |
291 | { | |
292 | /* | |
293 | * Check for a common HP bug... | |
294 | */ | |
295 | ||
296 | strlcpy(make_model, "HP ", mmsize); | |
297 | strlcpy(make_model + 3, attr + 19, mmsize - 3); | |
298 | } | |
299 | else if (!strncasecmp(attr, "Hewlett-Packard ", 16)) | |
8e3807e7 | 300 | { |
301 | strlcpy(make_model, "HP ", mmsize); | |
302 | strlcpy(make_model + 3, attr + 16, mmsize - 3); | |
303 | } | |
304 | else | |
305 | { | |
306 | strlcpy(make_model, attr, mmsize); | |
307 | } | |
8e3807e7 | 308 | } |
309 | else if (mfg && mdl) | |
310 | { | |
311 | /* | |
312 | * Build a make-model string from the manufacturer and model attributes... | |
313 | */ | |
314 | ||
1d5ef583 | 315 | if (!strncasecmp(mfg, "Hewlett-Packard", 15)) |
316 | strlcpy(make_model, "HP", mmsize); | |
317 | else | |
318 | strlcpy(make_model, mfg, mmsize); | |
8e3807e7 | 319 | |
320 | if ((delim = strchr(make_model, ';')) != NULL) | |
321 | *delim = '\0'; | |
322 | ||
1d5ef583 | 323 | if (!strncasecmp(make_model, mdl, strlen(make_model))) |
324 | { | |
325 | /* | |
326 | * Just copy model string, since it has the manufacturer... | |
327 | */ | |
8e3807e7 | 328 | |
1d5ef583 | 329 | strlcpy(make_model, mdl, mmsize); |
330 | } | |
331 | else | |
332 | { | |
333 | /* | |
334 | * Concatenate the make and model... | |
335 | */ | |
336 | ||
337 | strlcat(make_model, " ", mmsize); | |
338 | strlcat(make_model, mdl, mmsize); | |
339 | } | |
8e3807e7 | 340 | } |
341 | else | |
342 | { | |
343 | /* | |
344 | * Use "Unknown" as the printer make and model... | |
345 | */ | |
346 | ||
347 | strlcpy(make_model, "Unknown", mmsize); | |
348 | } | |
349 | ||
1d5ef583 | 350 | if ((delim = strchr(make_model, ';')) != NULL) |
351 | *delim = '\0'; | |
352 | ||
8e3807e7 | 353 | /* |
354 | * Look for the serial number field... | |
355 | */ | |
356 | ||
357 | if ((attr = strstr(device_id, "SERN:")) != NULL) | |
358 | attr += 5; | |
359 | else if ((attr = strstr(device_id, "SERIALNUMBER:")) != NULL) | |
360 | attr += 13; | |
361 | else if ((attr = strstr(device_id, ";SN:")) != NULL) | |
362 | attr += 4; | |
363 | ||
8e3807e7 | 364 | if (attr) |
365 | { | |
366 | strlcpy(serial_number, attr, sizeof(serial_number)); | |
367 | ||
368 | if ((delim = strchr(serial_number, ';')) != NULL) | |
369 | *delim = '\0'; | |
370 | } | |
371 | else | |
372 | serial_number[0] = '\0'; | |
373 | ||
374 | /* | |
375 | * Generate the device URI from the make_model and serial number strings. | |
376 | */ | |
377 | ||
378 | strlcpy(uri, "usb://", urisize); | |
379 | for (uriptr = uri + 6, delim = make_model; | |
380 | *delim && uriptr < (uri + urisize - 1); | |
381 | delim ++) | |
382 | if (*delim == ' ') | |
383 | { | |
384 | delim ++; | |
385 | *uriptr++ = '/'; | |
386 | break; | |
387 | } | |
388 | else | |
389 | *uriptr++ = *delim; | |
390 | ||
391 | for (; *delim && uriptr < (uri + urisize - 3); delim ++) | |
392 | if (*delim == ' ') | |
393 | { | |
394 | *uriptr++ = '%'; | |
395 | *uriptr++ = '2'; | |
396 | *uriptr++ = '0'; | |
397 | } | |
398 | else | |
399 | *uriptr++ = *delim; | |
400 | ||
401 | *uriptr = '\0'; | |
402 | ||
403 | if (serial_number[0]) | |
404 | { | |
405 | /* | |
406 | * Add the serial number to the URI... | |
407 | */ | |
408 | ||
409 | strlcat(uri, "?serial=", urisize); | |
410 | strlcat(uri, serial_number, urisize); | |
411 | } | |
412 | } | |
413 | ||
414 | ||
415 | /* | |
416 | * 'list_devices()' - List all USB devices. | |
417 | */ | |
418 | ||
419 | void | |
420 | list_devices(void) | |
421 | { | |
422 | #ifdef __linux | |
423 | int i; /* Looping var */ | |
424 | int length; /* Length of device ID info */ | |
425 | int fd; /* File descriptor */ | |
426 | char format[255], /* Format for device filename */ | |
427 | device[255], /* Device filename */ | |
428 | device_id[1024], /* Device ID string */ | |
429 | device_uri[1024], /* Device URI string */ | |
430 | make_model[1024]; /* Make and model */ | |
431 | ||
432 | ||
433 | /* | |
434 | * First figure out which USB printer filename to use... | |
435 | */ | |
436 | ||
6f96d00f | 437 | if (access("/dev/usblp0", 0) == 0) |
438 | strcpy(format, "/dev/usblp%d"); | |
8e3807e7 | 439 | else if (access("/dev/usb/usblp0", 0) == 0) |
440 | strcpy(format, "/dev/usb/usblp%d"); | |
441 | else | |
6f96d00f | 442 | strcpy(format, "/dev/usb/lp%d"); |
8e3807e7 | 443 | |
444 | /* | |
445 | * Then open each USB device... | |
446 | */ | |
447 | ||
448 | for (i = 0; i < 16; i ++) | |
449 | { | |
450 | sprintf(device, format, i); | |
451 | ||
452 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
453 | { | |
454 | if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0) | |
455 | { | |
456 | length = (((unsigned)device_id[0] & 255) << 8) + | |
457 | ((unsigned)device_id[1] & 255); | |
458 | ||
459 | /* | |
460 | * Check to see if the length is larger than our buffer; first | |
461 | * assume that the vendor incorrectly implemented the 1284 spec, | |
462 | * and then limit the length to the size of our buffer... | |
463 | */ | |
464 | ||
465 | if (length > (sizeof(device_id) - 2)) | |
466 | length = (((unsigned)device_id[1] & 255) << 8) + | |
467 | ((unsigned)device_id[0] & 255); | |
468 | ||
469 | if (length > (sizeof(device_id) - 2)) | |
470 | length = sizeof(device_id) - 2; | |
471 | ||
472 | memmove(device_id, device_id + 2, length); | |
473 | device_id[length] = '\0'; | |
474 | } | |
475 | else | |
476 | device_id[0] = '\0'; | |
477 | ||
478 | close(fd); | |
479 | } | |
480 | else | |
481 | device_id[0] = '\0'; | |
482 | ||
483 | if (device_id[0]) | |
484 | { | |
485 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
486 | device_uri, sizeof(device_uri)); | |
487 | ||
488 | printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri, | |
489 | make_model, i + 1); | |
490 | } | |
8e3807e7 | 491 | } |
492 | #elif defined(__sgi) | |
74ef1ffb | 493 | #elif defined(__sun) && defined(ECPPIOC_GETDEVID) |
8e3807e7 | 494 | int i; /* Looping var */ |
495 | int fd; /* File descriptor */ | |
496 | char device[255], /* Device filename */ | |
497 | device_id[1024], /* Device ID string */ | |
498 | device_uri[1024], /* Device URI string */ | |
499 | make_model[1024]; /* Make and model */ | |
8e3807e7 | 500 | struct ecpp_device_id did; /* Device ID buffer */ |
8e3807e7 | 501 | |
502 | ||
503 | /* | |
504 | * Open each USB device... | |
505 | */ | |
506 | ||
507 | for (i = 0; i < 8; i ++) | |
508 | { | |
509 | sprintf(device, "/dev/usb/printer%d", i); | |
510 | ||
8e3807e7 | 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 | } | |
8e3807e7 | 541 | } |
542 | #elif defined(__hpux) | |
543 | #elif defined(__osf) | |
544 | #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | |
545 | int i; /* Looping var */ | |
546 | char device[255]; /* Device filename */ | |
547 | ||
548 | ||
549 | for (i = 0; i < 8; i ++) | |
550 | { | |
551 | sprintf(device, "/dev/ulpt%d", i); | |
552 | if (!access(device, 0)) | |
553 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device, i + 1); | |
554 | ||
555 | sprintf(device, "/dev/unlpt%d", i); | |
556 | if (!access(device, 0)) | |
557 | printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device, i + 1); | |
558 | } | |
559 | #endif | |
560 | } | |
561 | ||
562 | ||
563 | /* | |
564 | * 'open_device()' - Open a USB device... | |
565 | */ | |
566 | ||
567 | int /* O - File descriptor or -1 on error */ | |
568 | open_device(const char *uri) /* I - Device URI */ | |
569 | { | |
570 | /* | |
571 | * The generic implementation just treats the URI as a device filename... | |
572 | * Specific operating systems may also support using the device serial | |
573 | * number and/or make/model. | |
574 | */ | |
575 | ||
576 | if (strncmp(uri, "usb:/dev/", 9) == 0) | |
8e3807e7 | 577 | #ifdef __linux |
74ef1ffb | 578 | return (-1); /* Do not allow direct devices anymore */ |
8e3807e7 | 579 | else if (strncmp(uri, "usb://", 6) == 0) |
580 | { | |
581 | /* | |
582 | * For Linux, try looking up the device serial number or model... | |
583 | */ | |
584 | ||
585 | int i; /* Looping var */ | |
586 | int busy; /* Are any ports busy? */ | |
587 | int length; /* Length of device ID info */ | |
588 | int fd; /* File descriptor */ | |
589 | char format[255], /* Format for device filename */ | |
590 | device[255], /* Device filename */ | |
591 | device_id[1024], /* Device ID string */ | |
592 | make_model[1024], /* Make and model */ | |
593 | device_uri[1024]; /* Device URI string */ | |
594 | ||
595 | ||
596 | /* | |
597 | * First figure out which USB printer filename to use... | |
598 | */ | |
599 | ||
6f96d00f | 600 | if (access("/dev/usblp0", 0) == 0) |
601 | strcpy(format, "/dev/usblp%d"); | |
8e3807e7 | 602 | else if (access("/dev/usb/usblp0", 0) == 0) |
603 | strcpy(format, "/dev/usb/usblp%d"); | |
604 | else | |
6f96d00f | 605 | strcpy(format, "/dev/usb/lp%d"); |
8e3807e7 | 606 | |
607 | /* | |
608 | * Then find the correct USB device... | |
609 | */ | |
610 | ||
611 | do | |
612 | { | |
613 | for (busy = 0, i = 0; i < 16; i ++) | |
614 | { | |
615 | sprintf(device, format, i); | |
616 | ||
617 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
618 | { | |
619 | if (ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof(device_id)), device_id) == 0) | |
620 | { | |
621 | length = (((unsigned)device_id[0] & 255) << 8) + | |
622 | ((unsigned)device_id[1] & 255); | |
623 | memmove(device_id, device_id + 2, length); | |
624 | device_id[length] = '\0'; | |
625 | } | |
626 | else | |
627 | device_id[0] = '\0'; | |
628 | } | |
629 | else | |
630 | { | |
631 | /* | |
632 | * If the open failed because it was busy, flag it so we retry | |
633 | * as needed... | |
634 | */ | |
635 | ||
636 | if (errno == EBUSY) | |
637 | busy = 1; | |
638 | ||
639 | device_id[0] = '\0'; | |
640 | } | |
641 | ||
642 | if (device_id[0]) | |
643 | { | |
644 | /* | |
645 | * Got the device ID - is this the one? | |
646 | */ | |
647 | ||
648 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
649 | device_uri, sizeof(device_uri)); | |
650 | ||
651 | if (strcmp(uri, device_uri) == 0) | |
652 | { | |
653 | /* | |
654 | * Yes, return this file descriptor... | |
655 | */ | |
656 | ||
657 | fprintf(stderr, "DEBUG: Printer using device file \"%s\"...\n", device); | |
658 | ||
659 | return (fd); | |
660 | } | |
661 | } | |
662 | ||
663 | /* | |
664 | * This wasn't the one... | |
665 | */ | |
666 | ||
667 | if (fd >= 0) | |
668 | close(fd); | |
669 | } | |
670 | ||
671 | /* | |
672 | * If we get here and at least one of the printer ports showed up | |
673 | * as "busy", then sleep for a bit and retry... | |
674 | */ | |
675 | ||
676 | if (busy) | |
677 | { | |
678 | fputs("INFO: USB printer is busy; will retry in 5 seconds...\n", | |
679 | stderr); | |
680 | sleep(5); | |
681 | } | |
682 | } | |
683 | while (busy); | |
684 | ||
685 | /* | |
686 | * Couldn't find the printer, return "no such device or address"... | |
687 | */ | |
688 | ||
689 | errno = ENODEV; | |
690 | ||
691 | return (-1); | |
692 | } | |
693 | #elif defined(__sun) && defined(ECPPIOC_GETDEVID) | |
74ef1ffb | 694 | return (-1); /* Do not allow direct devices anymore */ |
8e3807e7 | 695 | else if (strncmp(uri, "usb://", 6) == 0) |
696 | { | |
697 | /* | |
698 | * For Solaris, try looking up the device serial number or model... | |
699 | */ | |
700 | ||
701 | int i; /* Looping var */ | |
702 | int busy; /* Are any ports busy? */ | |
703 | int fd; /* File descriptor */ | |
704 | char device[255], /* Device filename */ | |
705 | device_id[1024], /* Device ID string */ | |
706 | make_model[1024], /* Make and model */ | |
707 | device_uri[1024]; /* Device URI string */ | |
708 | struct ecpp_device_id did; /* Device ID buffer */ | |
709 | ||
710 | ||
711 | /* | |
712 | * Find the correct USB device... | |
713 | */ | |
714 | ||
715 | do | |
716 | { | |
63412dfd | 717 | for (i = 0, busy = 0; i < 8; i ++) |
8e3807e7 | 718 | { |
719 | sprintf(device, "/dev/usb/printer%d", i); | |
720 | ||
721 | if ((fd = open(device, O_RDWR | O_EXCL)) >= 0) | |
722 | { | |
723 | did.mode = ECPP_CENTRONICS; | |
724 | did.len = sizeof(device_id); | |
725 | did.rlen = 0; | |
726 | did.addr = device_id; | |
727 | ||
728 | if (ioctl(fd, ECPPIOC_GETDEVID, &did) == 0) | |
729 | { | |
730 | if (did.rlen < (sizeof(device_id) - 1)) | |
731 | device_id[did.rlen] = '\0'; | |
732 | else | |
733 | device_id[sizeof(device_id) - 1] = '\0'; | |
734 | } | |
735 | else | |
736 | device_id[0] = '\0'; | |
737 | } | |
738 | else | |
739 | { | |
740 | /* | |
741 | * If the open failed because it was busy, flag it so we retry | |
742 | * as needed... | |
743 | */ | |
744 | ||
745 | if (errno == EBUSY) | |
746 | busy = 1; | |
747 | ||
748 | device_id[0] = '\0'; | |
749 | } | |
750 | ||
751 | if (device_id[0]) | |
752 | { | |
753 | /* | |
754 | * Got the device ID - is this the one? | |
755 | */ | |
756 | ||
757 | decode_device_id(i, device_id, make_model, sizeof(make_model), | |
758 | device_uri, sizeof(device_uri)); | |
759 | ||
760 | if (strcmp(uri, device_uri) == 0) | |
761 | return (fd); /* Yes, return this file descriptor... */ | |
762 | } | |
763 | ||
764 | /* | |
765 | * This wasn't the one... | |
766 | */ | |
767 | ||
768 | if (fd >= 0) | |
769 | close(fd); | |
770 | } | |
771 | ||
772 | /* | |
773 | * If we get here and at least one of the printer ports showed up | |
774 | * as "busy", then sleep for a bit and retry... | |
775 | */ | |
776 | ||
777 | if (busy) | |
778 | { | |
779 | fputs("INFO: USB printer is busy; will retry in 5 seconds...\n", | |
780 | stderr); | |
781 | sleep(5); | |
782 | } | |
783 | } | |
784 | while (busy); | |
785 | ||
786 | /* | |
787 | * Couldn't find the printer, return "no such device or address"... | |
788 | */ | |
789 | ||
790 | errno = ENODEV; | |
791 | ||
792 | return (-1); | |
793 | } | |
d4102150 | 794 | #else |
74ef1ffb | 795 | return (open(uri + 4, O_RDWR | O_EXCL)); |
d4102150 | 796 | #endif /* __linux */ |
8e3807e7 | 797 | else |
798 | { | |
799 | errno = ENODEV; | |
800 | return (-1); | |
801 | } | |
802 | } | |
803 | ||
804 | ||
805 | /* | |
c9d3f842 | 806 | * End of "$Id$". |
8e3807e7 | 807 | */ |