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