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