]> git.ipfire.org Git - thirdparty/cups.git/blob - backend/serial.c
Load cups into easysw/current.
[thirdparty/cups.git] / backend / serial.c
1 /*
2 * "$Id: serial.c 5241 2006-03-07 22:07:44Z mike $"
3 *
4 * Serial port backend for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2006 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 USA
19 *
20 * Voice: (301) 373-9600
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 printer or server.
29 * list_devices() - List all serial devices.
30 */
31
32 /*
33 * Include necessary headers.
34 */
35
36 #include <cups/backend.h>
37 #include <cups/cups.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <errno.h>
41 #include <cups/string.h>
42 #include <signal.h>
43
44 #ifdef __hpux
45 # include <sys/modem.h>
46 #endif /* __hpux */
47
48 #ifdef WIN32
49 # include <io.h>
50 #else
51 # include <unistd.h>
52 # include <fcntl.h>
53 # include <termios.h>
54 # ifdef __hpux
55 # include <sys/time.h>
56 # else
57 # include <sys/select.h>
58 # endif /* __hpux */
59 # ifdef HAVE_SYS_IOCTL_H
60 # include <sys/ioctl.h>
61 # endif /* HAVE_SYS_IOCTL_H */
62 #endif /* WIN32 */
63
64 #ifdef __sgi
65 # include <invent.h>
66 # ifndef INV_EPP_ECP_PLP
67 # define INV_EPP_ECP_PLP 6 /* From 6.3/6.4/6.5 sys/invent.h */
68 # define INV_ASO_SERIAL 14 /* serial portion of SGI ASO board */
69 # define INV_IOC3_DMA 16 /* DMA mode IOC3 serial */
70 # define INV_IOC3_PIO 17 /* PIO mode IOC3 serial */
71 # define INV_ISA_DMA 19 /* DMA mode ISA serial -- O2 */
72 # endif /* !INV_EPP_ECP_PLP */
73 #endif /* __sgi */
74
75 #ifndef CRTSCTS
76 # ifdef CNEW_RTSCTS
77 # define CRTSCTS CNEW_RTSCTS
78 # else
79 # define CRTSCTS 0
80 # endif /* CNEW_RTSCTS */
81 #endif /* !CRTSCTS */
82
83 #if defined(__APPLE__)
84 # include <CoreFoundation/CoreFoundation.h>
85 # include <IOKit/IOKitLib.h>
86 # include <IOKit/serial/IOSerialKeys.h>
87 # include <IOKit/IOBSD.h>
88 #endif /* __APPLE__ */
89
90
91 /*
92 * Local functions...
93 */
94
95 void list_devices(void);
96
97
98 /*
99 * 'main()' - Send a file to the printer or server.
100 *
101 * Usage:
102 *
103 * printer-uri job-id user title copies options [file]
104 */
105
106 int /* O - Exit status */
107 main(int argc, /* I - Number of command-line arguments (6 or 7) */
108 char *argv[]) /* I - Command-line arguments */
109 {
110 char method[255], /* Method in URI */
111 hostname[1024], /* Hostname */
112 username[255], /* Username info (not used) */
113 resource[1024], /* Resource info (device and options) */
114 *options, /* Pointer to options */
115 name[255], /* Name of option */
116 value[255], /* Value of option */
117 *ptr; /* Pointer into name or value */
118 int port; /* Port number (not used) */
119 int fp; /* Print file */
120 int copies; /* Number of copies to print */
121 int fd; /* Parallel device */
122 int rbytes; /* Number of bytes read */
123 int wbytes; /* Number of bytes written */
124 size_t nbytes, /* Number of bytes read */
125 tbytes; /* Total number of bytes written */
126 int dtrdsr; /* Do dtr/dsr flow control? */
127 int bufsize; /* Size of output buffer for writes */
128 char buffer[8192], /* Output buffer */
129 *bufptr; /* Pointer into buffer */
130 struct termios opts; /* Serial port options */
131 struct termios origopts; /* Original port options */
132 fd_set input, /* Input set for select() */
133 output; /* Output set for select() */
134 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
135 struct sigaction action; /* Actions for POSIX signals */
136 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
137
138
139 /*
140 * Make sure status messages are not buffered...
141 */
142
143 setbuf(stderr, NULL);
144
145 /*
146 * Ignore SIGPIPE signals...
147 */
148
149 #ifdef HAVE_SIGSET
150 sigset(SIGPIPE, SIG_IGN);
151 #elif defined(HAVE_SIGACTION)
152 memset(&action, 0, sizeof(action));
153 action.sa_handler = SIG_IGN;
154 sigaction(SIGPIPE, &action, NULL);
155 #else
156 signal(SIGPIPE, SIG_IGN);
157 #endif /* HAVE_SIGSET */
158
159 /*
160 * Check command-line...
161 */
162
163 if (argc == 1)
164 {
165 list_devices();
166 return (CUPS_BACKEND_OK);
167 }
168 else if (argc < 6 || argc > 7)
169 {
170 fputs("Usage: serial job-id user title copies options [file]\n", stderr);
171 return (CUPS_BACKEND_FAILED);
172 }
173
174 /*
175 * If we have 7 arguments, print the file named on the command-line.
176 * Otherwise, send stdin instead...
177 */
178
179 if (argc == 6)
180 {
181 fp = 0;
182 copies = 1;
183 }
184 else
185 {
186 /*
187 * Try to open the print file...
188 */
189
190 if ((fp = open(argv[6], O_RDONLY)) < 0)
191 {
192 perror("ERROR: unable to open print file");
193 return (CUPS_BACKEND_FAILED);
194 }
195
196 copies = atoi(argv[4]);
197 }
198
199 /*
200 * Extract the device name and options from the URI...
201 */
202
203 httpSeparateURI(HTTP_URI_CODING_ALL, cupsBackendDeviceURI(argv),
204 method, sizeof(method), username, sizeof(username),
205 hostname, sizeof(hostname), &port,
206 resource, sizeof(resource));
207
208 /*
209 * See if there are any options...
210 */
211
212 if ((options = strchr(resource, '?')) != NULL)
213 {
214 /*
215 * Yup, terminate the device name string and move to the first
216 * character of the options...
217 */
218
219 *options++ = '\0';
220 }
221
222 /*
223 * Open the serial port device...
224 */
225
226 fputs("STATE: +connecting-to-device\n", stderr);
227
228 do
229 {
230 if ((fd = open(resource, O_WRONLY | O_NOCTTY | O_EXCL | O_NDELAY)) == -1)
231 {
232 if (getenv("CLASS") != NULL)
233 {
234 /*
235 * If the CLASS environment variable is set, the job was submitted
236 * to a class and not to a specific queue. In this case, we want
237 * to abort immediately so that the job can be requeued on the next
238 * available printer in the class.
239 */
240
241 fputs("INFO: Unable to open serial port, queuing on next printer in class...\n",
242 stderr);
243
244 /*
245 * Sleep 5 seconds to keep the job from requeuing too rapidly...
246 */
247
248 sleep(5);
249
250 return (CUPS_BACKEND_FAILED);
251 }
252
253 if (errno == EBUSY)
254 {
255 fputs("INFO: Serial port busy; will retry in 30 seconds...\n", stderr);
256 sleep(30);
257 }
258 else
259 {
260 fprintf(stderr, "ERROR: Unable to open serial port device file \"%s\": %s\n",
261 resource, strerror(errno));
262 return (CUPS_BACKEND_FAILED);
263 }
264 }
265 }
266 while (fd < 0);
267
268 fputs("STATE: -connecting-to-device\n", stderr);
269
270 /*
271 * Set any options provided...
272 */
273
274 tcgetattr(fd, &origopts);
275 tcgetattr(fd, &opts);
276
277 opts.c_lflag &= ~(ICANON | ECHO | ISIG); /* Raw mode */
278 opts.c_oflag &= ~OPOST; /* Don't post-process */
279
280 bufsize = 96; /* 9600 baud / 10 bits/char / 10Hz */
281 dtrdsr = 0; /* No dtr/dsr flow control */
282
283 if (options != NULL)
284 while (*options)
285 {
286 /*
287 * Get the name...
288 */
289
290 for (ptr = name; *options && *options != '=';)
291 if (ptr < (name + sizeof(name) - 1))
292 *ptr++ = *options++;
293 *ptr = '\0';
294
295 if (*options == '=')
296 {
297 /*
298 * Get the value...
299 */
300
301 options ++;
302
303 for (ptr = value; *options && *options != '+' && *options != '&';)
304 if (ptr < (value + sizeof(value) - 1))
305 *ptr++ = *options++;
306 *ptr = '\0';
307
308 if (*options == '+')
309 options ++;
310 }
311 else
312 value[0] = '\0';
313
314 /*
315 * Process the option...
316 */
317
318 if (!strcasecmp(name, "baud"))
319 {
320 /*
321 * Set the baud rate...
322 */
323
324 bufsize = atoi(value) / 100;
325
326 #if B19200 == 19200
327 cfsetispeed(&opts, atoi(value));
328 cfsetospeed(&opts, atoi(value));
329 #else
330 switch (atoi(value))
331 {
332 case 1200 :
333 cfsetispeed(&opts, B1200);
334 cfsetospeed(&opts, B1200);
335 break;
336 case 2400 :
337 cfsetispeed(&opts, B2400);
338 cfsetospeed(&opts, B2400);
339 break;
340 case 4800 :
341 cfsetispeed(&opts, B4800);
342 cfsetospeed(&opts, B4800);
343 break;
344 case 9600 :
345 cfsetispeed(&opts, B9600);
346 cfsetospeed(&opts, B9600);
347 break;
348 case 19200 :
349 cfsetispeed(&opts, B19200);
350 cfsetospeed(&opts, B19200);
351 break;
352 case 38400 :
353 cfsetispeed(&opts, B38400);
354 cfsetospeed(&opts, B38400);
355 break;
356 # ifdef B57600
357 case 57600 :
358 cfsetispeed(&opts, B57600);
359 cfsetospeed(&opts, B57600);
360 break;
361 # endif /* B57600 */
362 # ifdef B115200
363 case 115200 :
364 cfsetispeed(&opts, B115200);
365 cfsetospeed(&opts, B115200);
366 break;
367 # endif /* B115200 */
368 # ifdef B230400
369 case 230400 :
370 cfsetispeed(&opts, B230400);
371 cfsetospeed(&opts, B230400);
372 break;
373 # endif /* B230400 */
374 default :
375 fprintf(stderr, "WARNING: Unsupported baud rate %s!\n", value);
376 break;
377 }
378 #endif /* B19200 == 19200 */
379 }
380 else if (!strcasecmp(name, "bits"))
381 {
382 /*
383 * Set number of data bits...
384 */
385
386 switch (atoi(value))
387 {
388 case 7 :
389 opts.c_cflag &= ~CSIZE;
390 opts.c_cflag |= CS7;
391 opts.c_cflag |= PARENB;
392 opts.c_cflag &= ~PARODD;
393 break;
394 case 8 :
395 opts.c_cflag &= ~CSIZE;
396 opts.c_cflag |= CS8;
397 opts.c_cflag &= ~PARENB;
398 break;
399 }
400 }
401 else if (!strcasecmp(name, "parity"))
402 {
403 /*
404 * Set parity checking...
405 */
406
407 if (!strcasecmp(value, "even"))
408 {
409 opts.c_cflag |= PARENB;
410 opts.c_cflag &= ~PARODD;
411 }
412 else if (!strcasecmp(value, "odd"))
413 {
414 opts.c_cflag |= PARENB;
415 opts.c_cflag |= PARODD;
416 }
417 else if (!strcasecmp(value, "none"))
418 opts.c_cflag &= ~PARENB;
419 else if (!strcasecmp(value, "space"))
420 {
421 /*
422 * Note: we only support space parity with 7 bits per character...
423 */
424
425 opts.c_cflag &= ~CSIZE;
426 opts.c_cflag |= CS8;
427 opts.c_cflag &= ~PARENB;
428 }
429 else if (!strcasecmp(value, "mark"))
430 {
431 /*
432 * Note: we only support mark parity with 7 bits per character
433 * and 1 stop bit...
434 */
435
436 opts.c_cflag &= ~CSIZE;
437 opts.c_cflag |= CS7;
438 opts.c_cflag &= ~PARENB;
439 opts.c_cflag |= CSTOPB;
440 }
441 }
442 else if (!strcasecmp(name, "flow"))
443 {
444 /*
445 * Set flow control...
446 */
447
448 if (!strcasecmp(value, "none"))
449 {
450 opts.c_iflag &= ~(IXON | IXOFF);
451 opts.c_cflag &= ~CRTSCTS;
452 }
453 else if (!strcasecmp(value, "soft"))
454 {
455 opts.c_iflag |= IXON | IXOFF;
456 opts.c_cflag &= ~CRTSCTS;
457 }
458 else if (!strcasecmp(value, "hard") ||
459 !strcasecmp(value, "rtscts"))
460 {
461 opts.c_iflag &= ~(IXON | IXOFF);
462 opts.c_cflag |= CRTSCTS;
463 }
464 else if (!strcasecmp(value, "dtrdsr"))
465 {
466 opts.c_iflag &= ~(IXON | IXOFF);
467 opts.c_cflag &= ~CRTSCTS;
468
469 dtrdsr = 1;
470 }
471 }
472 else if (!strcasecmp(name, "stop"))
473 {
474 switch (atoi(value))
475 {
476 case 1 :
477 opts.c_cflag &= ~CSTOPB;
478 break;
479
480 case 2 :
481 opts.c_cflag |= CSTOPB;
482 break;
483 }
484 }
485 }
486
487 tcsetattr(fd, TCSANOW, &opts);
488 fcntl(fd, F_SETFL, 0);
489
490 /*
491 * Now that we are "connected" to the port, ignore SIGTERM so that we
492 * can finish out any page data the driver sends (e.g. to eject the
493 * current page... Only ignore SIGTERM if we are printing data from
494 * stdin (otherwise you can't cancel raw jobs...)
495 */
496
497 if (argc < 7)
498 {
499 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
500 sigset(SIGTERM, SIG_IGN);
501 #elif defined(HAVE_SIGACTION)
502 memset(&action, 0, sizeof(action));
503
504 sigemptyset(&action.sa_mask);
505 action.sa_handler = SIG_IGN;
506 sigaction(SIGTERM, &action, NULL);
507 #else
508 signal(SIGTERM, SIG_IGN);
509 #endif /* HAVE_SIGSET */
510 }
511
512 /*
513 * Finally, send the print file...
514 */
515
516 if (bufsize > sizeof(buffer))
517 bufsize = sizeof(buffer);
518
519 wbytes = 0;
520
521 while (copies > 0)
522 {
523 copies --;
524
525 if (fp != 0)
526 {
527 fputs("PAGE: 1 1\n", stderr);
528 lseek(fp, 0, SEEK_SET);
529 }
530
531 if (dtrdsr)
532 {
533 /*
534 * Check the port and sleep until DSR is set...
535 */
536
537 int status;
538
539
540 if (!ioctl(fd, TIOCMGET, &status))
541 if (!(status & TIOCM_DSR))
542 {
543 /*
544 * Wait for DSR to go high...
545 */
546
547 fputs("DEBUG: DSR is low; waiting for device...\n", stderr);
548
549 do
550 {
551 sleep(1);
552 if (ioctl(fd, TIOCMGET, &status))
553 break;
554 }
555 while (!(status & TIOCM_DSR));
556
557 fputs("DEBUG: DSR is high; writing to device...\n", stderr);
558 }
559 }
560
561 tbytes = 0;
562 while ((nbytes = read(fp, buffer, bufsize)) > 0)
563 {
564 /*
565 * Write the print data to the printer...
566 */
567
568 tbytes += nbytes;
569 bufptr = buffer;
570
571 while (nbytes > 0)
572 {
573 /*
574 * See if we are ready to read or write...
575 */
576
577 do
578 {
579 FD_ZERO(&input);
580 FD_SET(fd, &input);
581 FD_ZERO(&output);
582 FD_SET(fd, &output);
583 }
584 while (select(fd + 1, &input, &output, NULL, NULL) < 0);
585
586 if (FD_ISSET(fd, &input))
587 {
588 /*
589 * Read backchannel data...
590 */
591
592 if ((rbytes = read(fd, resource, sizeof(resource))) > 0)
593 {
594 fprintf(stderr, "DEBUG: Received %d bytes of back-channel data!\n",
595 rbytes);
596 cupsBackChannelWrite(resource, rbytes, 1.0);
597 }
598 }
599
600 if (FD_ISSET(fd, &output))
601 {
602 /*
603 * Write print data...
604 */
605
606 if ((wbytes = write(fd, bufptr, nbytes)) < 0)
607 if (errno == ENOTTY)
608 wbytes = write(fd, bufptr, nbytes);
609
610 if (wbytes < 0)
611 {
612 /*
613 * Check for retryable errors...
614 */
615
616 if (errno != EAGAIN && errno != EINTR)
617 {
618 perror("ERROR: Unable to send print file to printer");
619 break;
620 }
621 }
622 else
623 {
624 /*
625 * Update count and pointer...
626 */
627
628 nbytes -= wbytes;
629 bufptr += wbytes;
630 }
631 }
632 }
633
634 if (wbytes < 0)
635 break;
636
637 if (argc > 6)
638 fprintf(stderr, "INFO: Sending print file, %lu bytes...\n",
639 (unsigned long)tbytes);
640 }
641 }
642
643 /*
644 * Close the serial port and input file and return...
645 */
646
647 tcsetattr(fd, TCSADRAIN, &origopts);
648
649 close(fd);
650 if (fp != 0)
651 close(fp);
652
653 return (wbytes < 0 ? CUPS_BACKEND_FAILED : CUPS_BACKEND_OK);
654 }
655
656
657 /*
658 * 'list_devices()' - List all serial devices.
659 */
660
661 void
662 list_devices(void)
663 {
664 #if defined(__hpux) || defined(__sgi) || defined(__sun) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
665 static char *funky_hex = "0123456789abcdefghijklmnopqrstuvwxyz";
666 /* Funky hex numbering used for some devices */
667 #endif /* __hpux || __sgi || __sun || __FreeBSD__ || __OpenBSD__ */
668
669 #if defined(__linux) || defined(linux) || defined(__linux__)
670 int i, j; /* Looping vars */
671 int fd; /* File descriptor */
672 char device[255]; /* Device filename */
673
674
675 for (i = 0; i < 100; i ++)
676 {
677 sprintf(device, "/dev/ttyS%d", i);
678 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
679 {
680 close(fd);
681 # if defined(_ARCH_PPC) || defined(powerpc) || defined(__powerpc)
682 printf("serial serial:%s?baud=230400 \"Unknown\" \"Serial Port #%d\"\n",
683 device, i + 1);
684 # else
685 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
686 device, i + 1);
687 # endif /* _ARCH_PPC || powerpc || __powerpc */
688 }
689 }
690
691 for (i = 0; i < 16; i ++)
692 {
693 sprintf(device, "/dev/usb/ttyUSB%d", i);
694 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
695 {
696 close(fd);
697 printf("serial serial:%s?baud=230400 \"Unknown\" \"USB Serial Port #%d\"\n",
698 device, i + 1);
699 }
700 }
701
702 for (i = 0; i < 64; i ++)
703 {
704 for (j = 0; j < 8; j ++)
705 {
706 sprintf(device, "/dev/ttyQ%02de%d", i, j);
707 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
708 {
709 close(fd);
710 printf("serial serial:%s?baud=115200 \"Unknown\" "
711 "\"Equinox ESP %d Port #%d\"\n",
712 device, i, j + 1);
713 }
714 }
715 }
716 #elif defined(__sgi)
717 int i, j, n; /* Looping vars */
718 char device[255]; /* Device filename */
719 inventory_t *inv; /* Hardware inventory info */
720
721
722 /*
723 * IRIX maintains a hardware inventory of most devices...
724 */
725
726 setinvent();
727
728 while ((inv = getinvent()) != NULL)
729 {
730 if (inv->inv_class == INV_SERIAL)
731 {
732 /*
733 * Some sort of serial port...
734 */
735
736 if (inv->inv_type == INV_CDSIO || inv->inv_type == INV_CDSIO_E)
737 {
738 /*
739 * CDSIO port...
740 */
741
742 for (n = 0; n < 6; n ++)
743 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"CDSIO Board %d Serial Port #%d\"\n",
744 n + 5 + 8 * inv->inv_controller, inv->inv_controller, n + 1);
745 }
746 else if (inv->inv_type == INV_EPC_SERIAL)
747 {
748 /*
749 * Everest serial port...
750 */
751
752 if (inv->inv_unit == 0)
753 i = 1;
754 else
755 i = 41 + 4 * (int)inv->inv_controller;
756
757 for (n = 0; n < (int)inv->inv_state; n ++)
758 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"EPC Serial Port %d, Ebus slot %d\"\n",
759 n + i, n + 1, (int)inv->inv_controller);
760 }
761 else if (inv->inv_state > 1)
762 {
763 /*
764 * Standard serial port under IRIX 6.4 and earlier...
765 */
766
767 for (n = 0; n < (int)inv->inv_state; n ++)
768 printf("serial serial:/dev/ttyd%d?baud=38400 \"Unknown\" \"Onboard Serial Port %d\"\n",
769 n + (int)inv->inv_unit + 1, n + (int)inv->inv_unit + 1);
770 }
771 else
772 {
773 /*
774 * Standard serial port under IRIX 6.5 and beyond...
775 */
776
777 printf("serial serial:/dev/ttyd%d?baud=115200 \"Unknown\" \"Onboard Serial Port %d\"\n",
778 (int)inv->inv_controller, (int)inv->inv_controller);
779 }
780 }
781 }
782
783 endinvent();
784
785 /*
786 * Central Data makes serial and parallel "servers" that can be
787 * connected in a number of ways. Look for ports...
788 */
789
790 for (i = 0; i < 10; i ++)
791 for (j = 0; j < 8; j ++)
792 for (n = 0; n < 32; n ++)
793 {
794 if (i == 8) /* EtherLite */
795 sprintf(device, "/dev/ttydn%d%c", j, funky_hex[n]);
796 else if (i == 9) /* PCI */
797 sprintf(device, "/dev/ttydp%d%c", j, funky_hex[n]);
798 else /* SCSI */
799 sprintf(device, "/dev/ttyd%d%d%c", i, j, funky_hex[n]);
800
801 if (access(device, 0) == 0)
802 {
803 if (i == 8)
804 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
805 device, j, n);
806 else if (i == 9)
807 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data PCI Serial Port, ID %d, port %d\"\n",
808 device, j, n);
809 else
810 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
811 device, i, j, n);
812 }
813 }
814 #elif defined(__sun)
815 int i, j, n; /* Looping vars */
816 char device[255]; /* Device filename */
817
818
819 /*
820 * Standard serial ports...
821 */
822
823 for (i = 0; i < 26; i ++)
824 {
825 sprintf(device, "/dev/cua/%c", 'a' + i);
826 if (access(device, 0) == 0)
827 #ifdef B115200
828 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
829 device, i + 1);
830 #else
831 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
832 device, i + 1);
833 #endif /* B115200 */
834 }
835
836 /*
837 * MAGMA serial ports...
838 */
839
840 for (i = 0; i < 40; i ++)
841 {
842 sprintf(device, "/dev/term/%02d", i);
843 if (access(device, 0) == 0)
844 printf("serial serial:%s?baud=38400 \"Unknown\" \"MAGMA Serial Board #%d Port #%d\"\n",
845 device, (i / 10) + 1, (i % 10) + 1);
846 }
847
848 /*
849 * Central Data serial ports...
850 */
851
852 for (i = 0; i < 9; i ++)
853 for (j = 0; j < 8; j ++)
854 for (n = 0; n < 32; n ++)
855 {
856 if (i == 8) /* EtherLite */
857 sprintf(device, "/dev/sts/ttyN%d%c", j, funky_hex[n]);
858 else
859 sprintf(device, "/dev/sts/tty%c%d%c", i + 'C', j,
860 funky_hex[n]);
861
862 if (access(device, 0) == 0)
863 {
864 if (i == 8)
865 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
866 device, j, n);
867 else
868 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
869 device, i, j, n);
870 }
871 }
872 #elif defined(__hpux)
873 int i, j, n; /* Looping vars */
874 char device[255]; /* Device filename */
875
876
877 /*
878 * Standard serial ports...
879 */
880
881 for (i = 0; i < 10; i ++)
882 {
883 sprintf(device, "/dev/tty%dp0", i);
884 if (access(device, 0) == 0)
885 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
886 device, i + 1);
887 }
888
889 /*
890 * Central Data serial ports...
891 */
892
893 for (i = 0; i < 9; i ++)
894 for (j = 0; j < 8; j ++)
895 for (n = 0; n < 32; n ++)
896 {
897 if (i == 8) /* EtherLite */
898 sprintf(device, "/dev/ttyN%d%c", j, funky_hex[n]);
899 else
900 sprintf(device, "/dev/tty%c%d%c", i + 'C', j,
901 funky_hex[n]);
902
903 if (access(device, 0) == 0)
904 {
905 if (i == 8)
906 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data EtherLite Serial Port, ID %d, port %d\"\n",
907 device, j, n);
908 else
909 printf("serial serial:%s?baud=38400 \"Unknown\" \"Central Data SCSI Serial Port, logical bus %d, ID %d, port %d\"\n",
910 device, i, j, n);
911 }
912 }
913 #elif defined(__osf__)
914 int i; /* Looping var */
915 char device[255]; /* Device filename */
916
917
918 /*
919 * Standard serial ports...
920 */
921
922 for (i = 0; i < 100; i ++)
923 {
924 sprintf(device, "/dev/tty%02d", i);
925 if (access(device, 0) == 0)
926 printf("serial serial:%s?baud=38400 \"Unknown\" \"Serial Port #%d\"\n",
927 device, i + 1);
928 }
929 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
930 int i, j; /* Looping vars */
931 int fd; /* File descriptor */
932 char device[255]; /* Device filename */
933
934
935 /*
936 * SIO ports...
937 */
938
939 for (i = 0; i < 32; i ++)
940 {
941 sprintf(device, "/dev/ttyd%c", funky_hex[i]);
942 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
943 {
944 close(fd);
945 printf("serial serial:%s?baud=115200 \"Unknown\" \"Standard Serial Port #%d\"\n",
946 device, i + 1);
947 }
948 }
949
950 /*
951 * Cyclades ports...
952 */
953
954 for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */
955 for (j = 0; j < 32; j ++)
956 {
957 sprintf(device, "/dev/ttyc%d%c", i, funky_hex[j]);
958 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
959 {
960 close(fd);
961 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
962 device, i, j + 1);
963 }
964
965 sprintf(device, "/dev/ttyC%d%c", i, funky_hex[j]);
966 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
967 {
968 close(fd);
969 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Port #%d\"\n",
970 device, i, j + 1);
971 }
972 }
973
974 /*
975 * Digiboard ports...
976 */
977
978 for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */
979 for (j = 0; j < 32; j ++)
980 {
981 sprintf(device, "/dev/ttyD%d%c", i, funky_hex[j]);
982 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
983 {
984 close(fd);
985 printf("serial serial:%s?baud=115200 \"Unknown\" \"Digiboard #%d Serial Port #%d\"\n",
986 device, i, j + 1);
987 }
988 }
989
990 /*
991 * Stallion ports...
992 */
993
994 for (i = 0; i < 32; i ++)
995 {
996 sprintf(device, "/dev/ttyE%c", funky_hex[i]);
997 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
998 {
999 close(fd);
1000 printf("serial serial:%s?baud=115200 \"Unknown\" \"Stallion Serial Port #%d\"\n",
1001 device, i + 1);
1002 }
1003 }
1004
1005 /*
1006 * SX ports...
1007 */
1008
1009 for (i = 0; i < 128; i ++)
1010 {
1011 sprintf(device, "/dev/ttyA%d", i + 1);
1012 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
1013 {
1014 close(fd);
1015 printf("serial serial:%s?baud=115200 \"Unknown\" \"SX Serial Port #%d\"\n",
1016 device, i + 1);
1017 }
1018 }
1019 #elif defined(__NetBSD__)
1020 int i, j; /* Looping vars */
1021 int fd; /* File descriptor */
1022 char device[255]; /* Device filename */
1023
1024
1025 /*
1026 * Standard serial ports...
1027 */
1028
1029 for (i = 0; i < 4; i ++)
1030 {
1031 sprintf(device, "/dev/tty%02d", i);
1032 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
1033 {
1034 close(fd);
1035 printf("serial serial:%s?baud=115200 \"Unknown\" \"Serial Port #%d\"\n",
1036 device, i + 1);
1037 }
1038 }
1039
1040 /*
1041 * Cyclades-Z ports...
1042 */
1043
1044 for (i = 0; i < 16; i ++) /* Should be up to 65536 boards... */
1045 for (j = 0; j < 64; j ++)
1046 {
1047 sprintf(device, "/dev/ttyCZ%02d%02d", i, j);
1048 if ((fd = open(device, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0)
1049 {
1050 close(fd);
1051 printf("serial serial:%s?baud=115200 \"Unknown\" \"Cyclades #%d Serial Prt #%d\"\n",
1052 device, i, j + 1);
1053 }
1054 }
1055 #elif defined(__APPLE__)
1056 /*
1057 * Standard serial ports on MacOS X...
1058 */
1059
1060 kern_return_t kernResult;
1061 mach_port_t masterPort;
1062 io_iterator_t serialPortIterator;
1063 CFMutableDictionaryRef classesToMatch;
1064 io_object_t serialService;
1065
1066 printf("serial serial \"Unknown\" \"Serial Printer (serial)\"\n");
1067
1068 kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
1069 if (KERN_SUCCESS != kernResult)
1070 return;
1071
1072 /*
1073 * Serial devices are instances of class IOSerialBSDClient.
1074 */
1075
1076 classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
1077 if (classesToMatch != NULL)
1078 {
1079 CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey),
1080 CFSTR(kIOSerialBSDRS232Type));
1081
1082 kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch,
1083 &serialPortIterator);
1084 if (kernResult == KERN_SUCCESS)
1085 {
1086 while ((serialService = IOIteratorNext(serialPortIterator)))
1087 {
1088 CFTypeRef serialNameAsCFString;
1089 CFTypeRef bsdPathAsCFString;
1090 char serialName[128];
1091 char bsdPath[1024];
1092 Boolean result;
1093
1094
1095 serialNameAsCFString =
1096 IORegistryEntryCreateCFProperty(serialService,
1097 CFSTR(kIOTTYDeviceKey),
1098 kCFAllocatorDefault, 0);
1099 if (serialNameAsCFString)
1100 {
1101 result = CFStringGetCString(serialNameAsCFString, serialName,
1102 sizeof(serialName),
1103 kCFStringEncodingASCII);
1104 CFRelease(serialNameAsCFString);
1105
1106 if (result)
1107 {
1108 bsdPathAsCFString =
1109 IORegistryEntryCreateCFProperty(serialService,
1110 CFSTR(kIOCalloutDeviceKey),
1111 kCFAllocatorDefault, 0);
1112 if (bsdPathAsCFString)
1113 {
1114 result = CFStringGetCString(bsdPathAsCFString, bsdPath,
1115 sizeof(bsdPath),
1116 kCFStringEncodingASCII);
1117 CFRelease(bsdPathAsCFString);
1118
1119 if (result)
1120 printf("serial serial:%s?baud=115200 \"Unknown\" \"%s\"\n", bsdPath,
1121 serialName);
1122 }
1123 }
1124 }
1125
1126 IOObjectRelease(serialService);
1127 }
1128
1129 IOObjectRelease(serialPortIterator); /* Release the iterator. */
1130 }
1131 }
1132 #endif
1133 }
1134
1135
1136 /*
1137 * End of "$Id: serial.c 5241 2006-03-07 22:07:44Z mike $".
1138 */