]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/usb.c
2 * "$Id: usb.c,v 1.18.2.19 2002/10/15 16:40:33 mike Exp $"
4 * USB port backend for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2002 by Easy Software Products, all rights reserved.
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
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
28 * main() - Send a file to the specified USB port.
29 * list_devices() - List all USB devices.
33 * Include necessary headers.
36 #include <cups/cups.h>
40 #include <cups/string.h>
52 # include <sys/ioctl.h>
53 # include <linux/lp.h>
54 # define IOCNR_GET_DEVICE_ID 1
57 * Get device_id string
59 # define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
67 void decode_device_id(int port
, const char *device_id
,
68 char *make_model
, int mmsize
,
69 char *uri
, int urisize
);
70 void list_devices(void);
71 int open_device(const char *uri
);
75 * 'main()' - Send a file to the specified USB port.
79 * printer-uri job-id user title copies options [file]
82 int /* O - Exit status */
83 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
84 char *argv
[]) /* I - Command-line arguments */
86 int fp
; /* Print file */
87 int copies
; /* Number of copies to print */
88 int fd
; /* Parallel device */
89 int wbytes
; /* Number of bytes written */
90 size_t nbytes
, /* Number of bytes read */
91 tbytes
; /* Total number of bytes written */
92 char buffer
[8192], /* Output buffer */
93 *bufptr
; /* Pointer into buffer */
94 struct termios opts
; /* Parallel port options */
95 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
96 struct sigaction action
; /* Actions for POSIX signals */
97 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
99 unsigned char status
; /* Port status (off-line, out-of-paper, etc.) */
104 * Make sure status messages are not buffered...
107 setbuf(stderr
, NULL
);
110 * Ignore SIGPIPE signals...
114 sigset(SIGPIPE
, SIG_IGN
);
115 #elif defined(HAVE_SIGACTION)
116 memset(&action
, 0, sizeof(action
));
117 action
.sa_handler
= SIG_IGN
;
118 sigaction(SIGPIPE
, &action
, NULL
);
120 signal(SIGPIPE
, SIG_IGN
);
121 #endif /* HAVE_SIGSET */
124 * Check command-line...
132 else if (argc
< 6 || argc
> 7)
134 fputs("Usage: USB job-id user title copies options [file]\n", stderr
);
139 * If we have 7 arguments, print the file named on the command-line.
140 * Otherwise, send stdin instead...
151 * Try to open the print file...
154 if ((fp
= open(argv
[6], O_RDONLY
)) < 0)
156 perror("ERROR: unable to open print file");
160 copies
= atoi(argv
[4]);
164 * Open the USB port device...
169 if ((fd
= open_device(argv
[0])) == -1)
173 fputs("INFO: USB port busy; will retry in 30 seconds...\n", stderr
);
176 else if (errno
== ENXIO
|| errno
== EIO
|| errno
== ENOENT
)
178 fputs("INFO: Printer not connected; will retry in 30 seconds...\n", stderr
);
183 fprintf(stderr
, "ERROR: Unable to open USB device \"%s\": %s\n",
184 argv
[0], strerror(errno
));
192 * Set any options provided...
195 tcgetattr(fd
, &opts
);
197 opts
.c_lflag
&= ~(ICANON
| ECHO
| ISIG
); /* Raw mode */
199 /**** No options supported yet ****/
201 tcsetattr(fd
, TCSANOW
, &opts
);
204 * Now that we are "connected" to the port, ignore SIGTERM so that we
205 * can finish out any page data the driver sends (e.g. to eject the
209 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
210 sigset(SIGTERM
, SIG_IGN
);
211 #elif defined(HAVE_SIGACTION)
212 memset(&action
, 0, sizeof(action
));
214 sigemptyset(&action
.sa_mask
);
215 action
.sa_handler
= SIG_IGN
;
216 sigaction(SIGTERM
, &action
, NULL
);
218 signal(SIGTERM
, SIG_IGN
);
219 #endif /* HAVE_SIGSET */
222 * Finally, send the print file...
231 fputs("PAGE: 1 1\n", stderr
);
232 lseek(fp
, 0, SEEK_SET
);
236 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
239 * Write the print data to the printer...
248 if (ioctl(fd
, LPGETSTATUS
, &status
) == 0)
250 fprintf(stderr
, "DEBUG: LPGETSTATUS returned %02X...\n", status
);
252 if (status
& LP_NOPA
)
253 fputs("INFO: Media tray empty!\n", stderr
);
254 else if (status
& LP_ERR
)
255 fputs("INFO: Printer fault!\n", stderr
);
256 else if (status
& LP_OFFL
)
257 fputs("INFO: Printer off-line.\n", stderr
);
261 if ((wbytes
= write(fd
, bufptr
, nbytes
)) < 0)
263 wbytes
= write(fd
, bufptr
, nbytes
);
267 perror("ERROR: Unable to send print file to printer");
276 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
277 (unsigned long)tbytes
);
282 * Close the socket connection and input file and return...
289 fputs("INFO: Ready to print.\n", stderr
);
296 * 'decode_device_id()' - Decode the IEEE-1284 device ID string.
300 decode_device_id(int port
, /* I - Port number */
301 const char *device_id
, /* I - 1284 device ID string */
302 char *make_model
, /* O - Make/model */
303 int mmsize
, /* I - Size of buffer */
304 char *uri
, /* O - Device URI */
305 int urisize
) /* I - Size of buffer */
307 char *attr
, /* 1284 attribute */
308 *delim
, /* 1284 delimiter */
309 *uriptr
, /* Pointer into URI */
310 line
[1024]; /* Line from devices file */
311 FILE *fp
; /* /proc/bus/usb/devices file */
312 int current
; /* Current printer port */
313 char serial_number
[1024], /* Serial number string */
314 temp
[1024]; /* Temporary string */
318 * Look for the description field...
321 if ((attr
= strstr(device_id
, "DES:")) != NULL
)
323 else if ((attr
= strstr(device_id
, "DESCRIPTION:")) != NULL
)
328 if (strncasecmp(attr
, "Hewlett-Packard ", 16) == 0)
330 strlcpy(make_model
, "HP ", mmsize
);
331 strlcpy(make_model
+ 3, attr
+ 16, mmsize
- 3);
335 strlcpy(make_model
, attr
, mmsize
);
338 if ((delim
= strchr(make_model
, ';')) != NULL
)
342 strlcpy(make_model
, "Unknown", mmsize
);
345 * Look for the serial number field...
348 if ((attr
= strstr(device_id
, "SERN:")) != NULL
)
350 else if ((attr
= strstr(device_id
, "SERIALNUMBER:")) != NULL
)
355 strlcpy(serial_number
, attr
, sizeof(serial_number
));
357 if ((delim
= strchr(serial_number
, ';')) != NULL
)
360 else if ((fp
= fopen("/proc/bus/usb/devices", "r")) != NULL
)
362 serial_number
[0] = '\0';
364 for (current
= 0; fgets(line
, sizeof(line
), fp
) != NULL
;)
366 if (line
[0] == 'S' && (attr
= strstr(line
, "SerialNumber=")) != NULL
)
369 * Copy serial number from line...
372 strlcpy(temp
, attr
+ 13, sizeof(temp
));
373 if ((delim
= strchr(temp
, '\n')) != NULL
)
376 else if (line
[0] == 'I' && strstr(line
, "Driver=usblp") != NULL
&&
377 strstr(line
, "Prot=02") != NULL
)
380 * Found printer device; if current == port, then use it!
385 strlcpy(serial_number
, temp
, sizeof(serial_number
));
397 * Generate the device URI from the make_model and serial number strings.
400 strlcpy(uri
, "usb://", urisize
);
401 for (uriptr
= uri
+ 6, delim
= make_model
;
402 *delim
&& uriptr
< (uri
+ urisize
- 1);
413 for (; *delim
&& uriptr
< (uri
+ urisize
- 3); delim
++)
425 if (serial_number
[0])
428 * Add the serial number to the URI...
431 strlcat(uri
, "?serial=", urisize
);
432 strlcat(uri
, serial_number
, urisize
);
438 * 'list_devices()' - List all USB devices.
445 int i
; /* Looping var */
446 int length
; /* Length of device ID info */
447 int fd
; /* File descriptor */
448 char format
[255], /* Format for device filename */
449 device
[255], /* Device filename */
450 device_id
[1024], /* Device ID string */
451 device_uri
[1024], /* Device URI string */
452 make_model
[1024]; /* Make and model */
456 * First figure out which USB printer filename to use...
459 if (access("/dev/usb/lp0", 0) == 0)
460 strcpy(format
, "/dev/usb/lp%d");
461 else if (access("/dev/usb/usblp0", 0) == 0)
462 strcpy(format
, "/dev/usb/usblp%d");
464 strcpy(format
, "/dev/usblp%d");
467 * Then open each USB device...
470 for (i
= 0; i
< 16; i
++)
472 sprintf(device
, format
, i
);
474 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
476 if (ioctl(fd
, LPIOC_GET_DEVICE_ID(sizeof(device_id
)), device_id
) == 0)
478 length
= (((unsigned)device_id
[0] & 255) << 8) +
479 ((unsigned)device_id
[1] & 255);
480 memcpy(device_id
, device_id
+ 2, length
);
481 device_id
[length
] = '\0';
493 decode_device_id(i
, device_id
, make_model
, sizeof(make_model
),
494 device_uri
, sizeof(device_uri
));
496 printf("direct %s \"%s\" \"USB Printer #%d\"\n", device_uri
,
500 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device
, i
+ 1);
504 int i
; /* Looping var */
505 char device
[255]; /* Device filename */
508 for (i
= 0; i
< 8; i
++)
510 sprintf(device
, "/dev/usb/printer%d", i
);
511 if (!access(device
, 0))
512 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device
, i
+ 1);
514 #elif defined(__hpux)
516 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
517 int i
; /* Looping var */
518 char device
[255]; /* Device filename */
521 for (i
= 0; i
< 8; i
++)
523 sprintf(device
, "/dev/ulpt%d", i
);
524 if (!access(device
, 0))
525 printf("direct usb:%s \"Unknown\" \"USB Printer #%d\"\n", device
, i
+ 1);
527 sprintf(device
, "/dev/unlpt%d", i
);
528 if (!access(device
, 0))
529 printf("direct usb:%s \"Unknown\" \"USB Printer #%d (no reset)\"\n", device
, i
+ 1);
536 * 'open_device()' - Open a USB device...
539 int /* O - File descriptor or -1 on error */
540 open_device(const char *uri
) /* I - Device URI */
543 * The generic implementation just treats the URI as a device filename...
544 * Specific operating systems may also support using the device serial
545 * number and/or make/model.
548 if (strncmp(uri
, "usb:/dev/", 9) == 0)
549 return (open(uri
+ 4, O_RDWR
| O_EXCL
));
551 else if (strncmp(uri
, "usb://", 6) == 0)
554 * For Linux, try looking up the device serial number or model...
557 int i
; /* Looping var */
558 int length
; /* Length of device ID info */
559 int fd
; /* File descriptor */
560 char format
[255], /* Format for device filename */
561 device
[255], /* Device filename */
562 device_id
[1024], /* Device ID string */
563 make_model
[1024], /* Make and model */
564 device_uri
[1024]; /* Device URI string */
568 * First figure out which USB printer filename to use...
571 if (access("/dev/usb/lp0", 0) == 0)
572 strcpy(format
, "/dev/usb/lp%d");
573 else if (access("/dev/usb/usblp0", 0) == 0)
574 strcpy(format
, "/dev/usb/usblp%d");
576 strcpy(format
, "/dev/usblp%d");
579 * Then find the correct USB device...
582 for (i
= 0; i
< 16; i
++)
584 sprintf(device
, format
, i
);
586 if ((fd
= open(device
, O_RDWR
| O_EXCL
)) >= 0)
588 if (ioctl(fd
, LPIOC_GET_DEVICE_ID(sizeof(device_id
)), device_id
) == 0)
590 length
= (((unsigned)device_id
[0] & 255) << 8) +
591 ((unsigned)device_id
[1] & 255);
592 memcpy(device_id
, device_id
+ 2, length
);
593 device_id
[length
] = '\0';
604 * Got the device ID - is this the one?
607 decode_device_id(i
, device_id
, make_model
, sizeof(make_model
),
608 device_uri
, sizeof(device_uri
));
610 if (strcmp(uri
, device_uri
) == 0)
611 return (fd
); /* Yes, return this file descriptor... */
615 * This wasn't the one...
622 * Couldn't find the printer, return "no such device or address"...
639 * End of "$Id: usb.c,v 1.18.2.19 2002/10/15 16:40:33 mike Exp $".