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