sconfig.c revision 123123
1123123Simp/*
2123123Simp * Channel configuration utility for Cronyx serial adapters.
3123123Simp *
4123123Simp * Copyright (C) 1997-2002 Cronyx Engineering.
5123123Simp * Author: Serge Vakulenko, <vak@cronyx.ru>
6123123Simp *
7123123Simp * Copyright (C) 1999-2003 Cronyx Engineering.
8123123Simp * Author: Roman Kurakin, <rik@cronyx.ru>
9123123Simp *
10123123Simp * This software is distributed with NO WARRANTIES, not even the implied
11123123Simp * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12123123Simp *
13123123Simp * Authors grant any other persons or organisations permission to use
14123123Simp * or modify this software as long as this message is kept with the software,
15123123Simp * all derivative works or modified versions.
16123123Simp *
17123123Simp * Cronyx Id: sconfig.c,v 1.2.2.4 2003/06/20 16:20:48 rik Exp $
18123123Simp * $FreeBSD: head/sbin/sconfig/sconfig.c 123123 2003-12-03 07:59:49Z imp $
19123123Simp */
20123123Simp#include <stdio.h>
21123123Simp#include <stdlib.h>
22123123Simp#include <string.h>
23123123Simp#include <unistd.h>
24123123Simp#include <fcntl.h>
25123123Simp#include <errno.h>
26123123Simp#include <ctype.h>
27123123Simp#include <sys/ioctl.h>
28123123Simp#include <sys/types.h>
29123123Simp#include <sys/stat.h>
30123123Simp#include <sys/socket.h>
31123123Simp#include <net/if.h>
32123123Simp#include <machine/cserial.h>
33123123Simp
34123123Simp#define MAXCHAN 128
35123123Simp
36123123Simpint vflag, eflag, sflag, mflag, cflag, fflag, iflag, aflag, xflag;
37123123Simpint tflag, uflag;
38123123Simpchar mask[48];
39123123Simpint adapter_type;		/* 0-sigma, 1-tau, 2-tau */
40123123Simpchar chan_name[16];
41123123Simp
42123123Simpextern char *optarg;
43123123Simpextern int optind;
44123123Simp
45123123Simpstatic void
46123123Simpusage (void)
47123123Simp{
48123123Simp	printf(
49123123Simp"Serial Adapter Configuration Utility\n"
50123123Simp"Copyright (C) 1998-1999 Cronyx Engineering Ltd.\n"
51123123Simp"See also man sconfig (8)\n"
52123123Simp"Usage:\n"
53123123Simp"\tsconfig [-aimsxeftuc] [device [parameters ...]]\n"
54123123Simp"\n"
55123123Simp"Options:\n"
56123123Simp"\t<no options>\t\t -- print channel options\n"
57123123Simp"\t-a\t\t\t -- print all settings of the channel\n"
58123123Simp"\t-i\t\t\t -- print network interface status\n"
59123123Simp"\t-m\t\t\t -- print modem signal status\n"
60123123Simp"\t-s\t\t\t -- print channel statistics\n"
61123123Simp"\t-x\t\t\t -- print extended channel statistics\n"
62123123Simp"\t-e\t\t\t -- print short E1/G703 statistics\n"
63123123Simp"\t-f\t\t\t -- print full E1/G703 statistics\n"
64123123Simp"\t-t\t\t\t -- print short E3/T3/STS-1 statistics\n"
65123123Simp"\t-u\t\t\t -- print full E3/T3/STS-1 statistics\n"
66123123Simp"\t-c\t\t\t -- clear statistics\n"
67123123Simp"\nParameters:\n"
68123123Simp"\t<number>\t\t -- baud rate, internal clock\n"
69123123Simp"\textclock\t\t -- external clock (default)\n"
70123123Simp"\nProtocol options:\n"
71123123Simp"\tasync\t\t\t -- asynchronous protocol\n"
72123123Simp#ifdef __linux__
73123123Simp"\tsync\t\t\t -- synchronous protocol\n"
74123123Simp#endif
75123123Simp"\tcisco\t\t\t -- Cisco/HDLC protocol\n"
76123123Simp"\tfr\t\t\t -- Frame Relay protocol\n"
77123123Simp#ifdef __linux__
78123123Simp"\t    dlci<number>\t -- Add new DLCI\n"
79123123Simp#endif
80123123Simp"\tppp\t\t\t -- PPP protocol\n"
81123123Simp#ifdef __linux__
82123123Simp"\trbrg\t\t\t -- Remote bridge\n"
83123123Simp"\traw\t\t\t -- raw HDLC protocol\n"
84123123Simp"\tpacket\t\t\t -- packetized HDLC protocol\n"
85123123Simp"\tidle\t\t\t -- no protocol\n"
86123123Simp#else
87123123Simp"\t    keepalive={on,of}\t -- Enable/disable keepalive\n"
88123123Simp#endif
89123123Simp"\nInterface options:\n"
90123123Simp"\tport={rs232,v35,rs449}\t -- port type (for old models of Sigma)\n"
91123123Simp"\tcfg={A,B,C}\t\t -- adapter configuration\n"
92123123Simp"\tloop={on,off}\t\t -- internal loopback\n"
93123123Simp"\trloop={on,off}\t\t -- remote loopback\n"
94123123Simp"\tdpll={on,off}\t\t -- DPLL mode\n"
95123123Simp"\tnrzi={on,off}\t\t -- NRZI encoding\n"
96123123Simp"\tinvclk={on,off}\t\t -- invert receive and transmit clock\n"
97123123Simp"\tinvrclk={on,off}\t -- invert receive clock\n"
98123123Simp"\tinvtclk={on,off}\t -- invert transmit clock\n"
99123123Simp"\thigain={on,off}\t\t -- E1 high non linear input sensitivity \n\t\t\t\t    (long line)\n"
100123123Simp"\tmonitor={on,off}\t -- E1 high linear input sensitivity \n\t\t\t\t    (interception mode)\n"
101123123Simp"\tphony={on,off}\t\t -- E1 telepnony mode\n"
102123123Simp"\tunfram={on,off}\t\t -- E1 unframed mode\n"
103123123Simp"\tscrambler={on,off}\t -- G.703 scrambling mode\n"
104123123Simp"\tuse16={on,off}\t\t -- E1 timeslot 16 usage\n"
105123123Simp"\tcrc4={on,off}\t\t -- E1 CRC4 mode\n"
106123123Simp"\tsyn={int,rcv,rcvX}\t -- G.703 transmit clock\n"
107123123Simp"\tts=...\t\t\t -- E1 timeslots\n"
108123123Simp"\tpass=...\t\t -- E1 subchannel timeslots\n"
109123123Simp"\tdir=<num>\t\t -- connect channel to link<num>\n"
110123123Simp/*"\tcablen={on,off}\t\t -- T3/STS-1 high transmitter output for long cable\n"*/
111123123Simp"\tdebug={0,1,2}\t\t -- enable/disable debug messages\n"
112123123Simp	);
113123123Simp	exit (0);
114123123Simp}
115123123Simp
116123123Simpstatic unsigned long
117123123Simpscan_timeslots (char *s)
118123123Simp{
119123123Simp	char *e;
120123123Simp	long v;
121123123Simp	int i;
122123123Simp	unsigned long ts, lastv;
123123123Simp
124123123Simp	ts = lastv = 0;
125123123Simp	for (;;) {
126123123Simp		v = strtol (s, &e, 10);
127123123Simp		if (e == s)
128123123Simp			break;
129123123Simp		if (*e == '-') {
130123123Simp			lastv = v;
131123123Simp			s = e+1;
132123123Simp			continue;
133123123Simp		}
134123123Simp		if (*e == ',')
135123123Simp			++e;
136123123Simp
137123123Simp		if (lastv)
138123123Simp			for (i=lastv; i<v; ++i)
139123123Simp				ts |= 1L << i;
140123123Simp		ts |= 1L << v;
141123123Simp
142123123Simp		lastv = 0;
143123123Simp		s = e;
144123123Simp	}
145123123Simp	return ts;
146123123Simp}
147123123Simp
148123123Simpstatic int
149123123Simpppp_ok (void)
150123123Simp{
151123123Simp#ifdef __linux__
152123123Simp	int s, p;
153123123Simp	struct ifreq ifr;
154123123Simp	char pttyname[32];
155123123Simp	char *p1, *p2;
156123123Simp	int i, j;
157123123Simp	int ppp_disc = N_PPP;
158123123Simp
159123123Simp	/*
160123123Simp	 * Open a socket for doing the ioctl operations.
161123123Simp	 */
162123123Simp	s = socket (AF_INET, SOCK_DGRAM, 0);
163123123Simp	if (s < 0) {
164123123Simp		fprintf (stderr, "Error opening socket.\n");
165123123Simp		return 0;
166123123Simp	}
167123123Simp	strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
168123123Simp	if (ioctl (s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0) {
169123123Simp		/* Ok. */
170123123Simp		close (s);
171123123Simp		return 1;
172123123Simp	}
173123123Simp	close (s);
174123123Simp
175123123Simp	/* open pseudo-tty and try to set PPP discipline */
176123123Simp	sprintf (pttyname, "/dev/ptyXX");
177123123Simp	p1 = &pttyname[8];
178123123Simp	p2 = &pttyname[9];
179123123Simp	for (i=0; i<16; i++) {
180123123Simp		struct stat stb;
181123123Simp
182123123Simp		*p1 = "pqrstuvwxyzabcde"[i];
183123123Simp		*p2 = '0';
184123123Simp		if (stat (pttyname, &stb) < 0)
185123123Simp			continue;
186123123Simp		for (j=0; j<16; j++) {
187123123Simp			*p2 = "0123456789abcdef"[j];
188123123Simp			p = open (pttyname, 2);
189123123Simp			if (p > 0) {
190123123Simp				if (ioctl (p, TIOCSETD, &ppp_disc) < 0) {
191123123Simp					fprintf (stderr, "No PPP discipline in kernel.\n");
192123123Simp					close (p);
193123123Simp					return 0;
194123123Simp				}
195123123Simp				close (p);
196123123Simp				return 1;
197123123Simp			}
198123123Simp		}
199123123Simp	}
200123123Simp	fprintf (stderr, "Cannot get pseudo-tty.\n");
201123123Simp	return 0;
202123123Simp#else
203123123Simp	return 1;
204123123Simp#endif
205123123Simp}
206123123Simp
207123123Simpstatic char *
208123123Simpformat_timeslots (unsigned long s)
209123123Simp{
210123123Simp	static char buf [100];
211123123Simp	char *p = buf;
212123123Simp	int i;
213123123Simp
214123123Simp	for (i=1; i<32; ++i)
215123123Simp		if ((s >> i) & 1) {
216123123Simp			int prev = (i > 1)  & (s >> (i-1));
217123123Simp			int next = (i < 31) & (s >> (i+1));
218123123Simp
219123123Simp			if (prev) {
220123123Simp				if (next)
221123123Simp					continue;
222123123Simp				*p++ = '-';
223123123Simp			} else if (p > buf)
224123123Simp				*p++ = ',';
225123123Simp
226123123Simp			if (i >= 10)
227123123Simp				*p++ = '0' + i / 10;
228123123Simp			*p++ = '0' + i % 10;
229123123Simp		}
230123123Simp	*p = 0;
231123123Simp	return buf;
232123123Simp}
233123123Simp
234123123Simpstatic void
235123123Simpprint_modems (int fd, int need_header)
236123123Simp{
237123123Simp	int status;
238123123Simp
239123123Simp	if (ioctl (fd, TIOCMGET, &status) < 0) {
240123123Simp		perror ("getting modem status");
241123123Simp		return;
242123123Simp	}
243123123Simp	if (need_header)
244123123Simp		printf ("Channel\tLE\tDTR\tDSR\tRTS\tCTS\tCD\n");
245123123Simp	printf ("%s\t%s\t%s\t%s\t%s\t%s\t%s\n", chan_name,
246123123Simp		status & TIOCM_LE  ? "On" : "-",
247123123Simp		status & TIOCM_DTR ? "On" : "-",
248123123Simp		status & TIOCM_DSR ? "On" : "-",
249123123Simp		status & TIOCM_RTS ? "On" : "-",
250123123Simp		status & TIOCM_CTS ? "On" : "-",
251123123Simp		status & TIOCM_CD  ? "On" : "-");
252123123Simp}
253123123Simp
254123123Simpstatic void
255123123Simpprint_ifconfig (int fd)
256123123Simp{
257123123Simp	char buf [64];
258123123Simp#ifdef __linux__
259123123Simp	char protocol [8];
260123123Simp
261123123Simp	if (ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0 &&
262123123Simp	    strcmp (protocol, "fr") == 0)
263123123Simp		sprintf (buf, "ifconfig %sd16 2>/dev/null", chan_name);
264123123Simp	else
265123123Simp#endif
266123123Simp	sprintf (buf, "ifconfig %s 2>/dev/null", chan_name);
267123123Simp	system (buf);
268123123Simp}
269123123Simp
270123123Simpstatic char *
271123123Simpformat_long (unsigned long val)
272123123Simp{
273123123Simp	static char s[32];
274123123Simp	int l;
275123123Simp	l = sprintf (s, "%lu", val);
276123123Simp	if (l>7 && !sflag) {
277123123Simp		s[3] = s[2];
278123123Simp		s[2] = s[1];
279123123Simp		s[1] = '.';
280123123Simp		s[4] = 'e';
281123123Simp		sprintf (s + 5, "%02d", l-1);
282123123Simp	}
283123123Simp	return s;
284123123Simp}
285123123Simp
286123123Simpstatic void
287123123Simpprint_stats (int fd, int need_header)
288123123Simp{
289123123Simp	struct serial_statistics st;
290123123Simp	unsigned long sarr [9];
291123123Simp	int i;
292123123Simp
293123123Simp	if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) {
294123123Simp		perror ("getting statistics");
295123123Simp		return;
296123123Simp	}
297123123Simp	if (need_header) {
298123123Simp		if (sflag) {
299123123Simp			printf ("        ------------Receive-----------      "
300123123Simp				"------------Transmit----------\n");
301123123Simp			printf ("Channel Interrupts  Packets     Errors      "
302123123Simp				"Interrupts  Packets     Errors\n");
303123123Simp		}
304123123Simp		else    {
305123123Simp			printf ("        --------Receive---------------  "
306123123Simp				"--------Transmit--------------  Modem\n");
307123123Simp			printf ("Channel Intrs   Bytes   Packets Errors  "
308123123Simp				"Intrs   Bytes   Packets Errors  Intrs\n");
309123123Simp		}
310123123Simp	}
311123123Simp
312123123Simp	sarr [0] = st.rintr;
313123123Simp	sarr [1] = st.ibytes;
314123123Simp	sarr [2] = st.ipkts;
315123123Simp	sarr [3] = st.ierrs;
316123123Simp	sarr [4] = st.tintr;
317123123Simp	sarr [5] = st.obytes;
318123123Simp	sarr [6] = st.opkts;
319123123Simp	sarr [7] = st.oerrs;
320123123Simp	sarr [8] = st.mintr;
321123123Simp	printf ("%s", chan_name);
322123123Simp	if (sflag) {
323123123Simp		printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0],
324123123Simp			sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]);
325123123Simp	} else {
326123123Simp		for (i = 0; i < 9; i++)
327123123Simp			printf ("\t%s", format_long (sarr [i]));
328123123Simp		printf ("\n");
329123123Simp	}
330123123Simp}
331123123Simp
332123123Simpstatic void
333123123Simpclear_stats (int fd)
334123123Simp{
335123123Simp	if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) {
336123123Simp		perror ("clearing statistics");
337123123Simp		exit (-1);
338123123Simp	}
339123123Simp}
340123123Simp
341123123Simpstatic char *
342123123Simpformat_e1_status (unsigned long status)
343123123Simp{
344123123Simp	static char buf [80];
345123123Simp
346123123Simp	if (status & E1_NOALARM)
347123123Simp		return "Ok";
348123123Simp	buf[0] = 0;
349123123Simp	if (status & E1_LOS)     strcat (buf, ",LOS");
350123123Simp	if (status & E1_AIS)     strcat (buf, ",AIS");
351123123Simp	if (status & E1_LOF)     strcat (buf, ",LOF");
352123123Simp	if (status & E1_LOMF)    strcat (buf, ",LOMF");
353123123Simp	if (status & E1_FARLOF)  strcat (buf, ",FARLOF");
354123123Simp	if (status & E1_AIS16)   strcat (buf, ",AIS16");
355123123Simp	if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
356123123Simp/*	if (status & E1_TSTREQ)  strcat (buf, ",TSTREQ");*/
357123123Simp/*	if (status & E1_TSTERR)  strcat (buf, ",TSTERR");*/
358123123Simp	if (buf[0] == ',')
359123123Simp		return buf+1;
360123123Simp	return "Unknown";
361123123Simp}
362123123Simp
363123123Simpstatic void
364123123Simpprint_frac (int leftalign, unsigned long numerator, unsigned long divider)
365123123Simp{
366123123Simp	int n;
367123123Simp
368123123Simp	if (numerator < 1 || divider < 1) {
369123123Simp		printf (leftalign ? "/-   " : "    -");
370123123Simp		return;
371123123Simp	}
372123123Simp	n = (int) (0.5 + 1000.0 * numerator / divider);
373123123Simp	if (n < 1000) {
374123123Simp		printf (leftalign ? "/.%-3d" : " .%03d", n);
375123123Simp		return;
376123123Simp	}
377123123Simp	putchar (leftalign ? '/' : ' ');
378123123Simp
379123123Simp	if      (n >= 1000000) n = (n+500) / 1000 * 1000;
380123123Simp	else if (n >= 100000)  n = (n+50)  / 100 * 100;
381123123Simp	else if (n >= 10000)   n = (n+5)   / 10 * 10;
382123123Simp
383123123Simp	switch (n) {
384123123Simp	case 1000:    printf (".999"); return;
385123123Simp	case 10000:   n = 9990;   break;
386123123Simp	case 100000:  n = 99900;  break;
387123123Simp	case 1000000: n = 999000; break;
388123123Simp	}
389123123Simp	if (n < 10000)        printf ("%d.%d", n/1000, n/10%100);
390123123Simp	else if (n < 100000)  printf ("%d.%d", n/1000, n/100%10);
391123123Simp	else if (n < 1000000) printf ("%d.", n/1000);
392123123Simp	else                  printf ("%d", n/1000);
393123123Simp}
394123123Simp
395123123Simpstatic void
396123123Simpprint_e1_stats (int fd, int need_header)
397123123Simp{
398123123Simp	struct e1_statistics st;
399123123Simp	int i, maxi;
400123123Simp
401123123Simp	if (need_header)
402123123Simp		printf ("Chan\t Unav/Degr  Bpv/Fsyn  CRC/RCRC  Err/Lerr  Sev/Bur   Oof/Slp  Status\n");
403123123Simp
404123123Simp	if (ioctl (fd, SERIAL_GETESTAT, &st) < 0)
405123123Simp		return;
406123123Simp	printf ("%s\t", chan_name);
407123123Simp
408123123Simp	/* Unavailable seconds, degraded minutes */
409123123Simp	print_frac (0, st.currnt.uas, st.cursec);
410123123Simp	print_frac (1, 60 * st.currnt.dm, st.cursec);
411123123Simp
412123123Simp	/* Bipolar violations, frame sync errors */
413123123Simp	print_frac (0, st.currnt.bpv, st.cursec);
414123123Simp	print_frac (1, st.currnt.fse, st.cursec);
415123123Simp
416123123Simp	/* CRC errors, remote CRC errors (E-bit) */
417123123Simp	print_frac (0, st.currnt.crce, st.cursec);
418123123Simp	print_frac (1, st.currnt.rcrce, st.cursec);
419123123Simp
420123123Simp	/* Errored seconds, line errored seconds */
421123123Simp	print_frac (0, st.currnt.es, st.cursec);
422123123Simp	print_frac (1, st.currnt.les, st.cursec);
423123123Simp
424123123Simp	/* Severely errored seconds, bursty errored seconds */
425123123Simp	print_frac (0, st.currnt.ses, st.cursec);
426123123Simp	print_frac (1, st.currnt.bes, st.cursec);
427123123Simp
428123123Simp	/* Out of frame seconds, controlled slip seconds */
429123123Simp	print_frac (0, st.currnt.oofs, st.cursec);
430123123Simp	print_frac (1, st.currnt.css, st.cursec);
431123123Simp
432123123Simp	printf (" %s\n", format_e1_status (st.status));
433123123Simp
434123123Simp	if (fflag) {
435123123Simp		/* Print total statistics. */
436123123Simp		printf ("\t");
437123123Simp		print_frac (0, st.total.uas, st.totsec);
438123123Simp		print_frac (1, 60 * st.total.dm, st.totsec);
439123123Simp
440123123Simp		print_frac (0, st.total.bpv, st.totsec);
441123123Simp		print_frac (1, st.total.fse, st.totsec);
442123123Simp
443123123Simp		print_frac (0, st.total.crce, st.totsec);
444123123Simp		print_frac (1, st.total.rcrce, st.totsec);
445123123Simp
446123123Simp		print_frac (0, st.total.es, st.totsec);
447123123Simp		print_frac (1, st.total.les, st.totsec);
448123123Simp
449123123Simp		print_frac (0, st.total.ses, st.totsec);
450123123Simp		print_frac (1, st.total.bes, st.totsec);
451123123Simp
452123123Simp		print_frac (0, st.total.oofs, st.totsec);
453123123Simp		print_frac (1, st.total.css, st.totsec);
454123123Simp
455123123Simp		printf (" -- Total\n");
456123123Simp
457123123Simp		/* Print 24-hour history. */
458123123Simp		maxi = (st.totsec - st.cursec) / 900;
459123123Simp		if (maxi > 48)
460123123Simp			maxi = 48;
461123123Simp		for (i=0; i<maxi; ++i) {
462123123Simp			printf ("       ");
463123123Simp			print_frac (0, st.interval[i].uas, 15*60);
464123123Simp			print_frac (1, 60 * st.interval[i].dm, 15*60);
465123123Simp
466123123Simp			print_frac (0, st.interval[i].bpv, 15*60);
467123123Simp			print_frac (1, st.interval[i].fse, 15*60);
468123123Simp
469123123Simp			print_frac (0, st.interval[i].crce, 15*60);
470123123Simp			print_frac (1, st.interval[i].rcrce, 15*60);
471123123Simp
472123123Simp			print_frac (0, st.interval[i].es, 15*60);
473123123Simp			print_frac (1, st.interval[i].les, 15*60);
474123123Simp
475123123Simp			print_frac (0, st.interval[i].ses, 15*60);
476123123Simp			print_frac (1, st.interval[i].bes, 15*60);
477123123Simp
478123123Simp			print_frac (0, st.interval[i].oofs, 15*60);
479123123Simp			print_frac (1, st.interval[i].css, 15*60);
480123123Simp
481123123Simp			if (i < 3)
482123123Simp				printf (" -- %dm\n", (i+1)*15);
483123123Simp			else
484123123Simp				printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15);
485123123Simp		}
486123123Simp	}
487123123Simp}
488123123Simp
489123123Simpstatic char *
490123123Simpformat_e3_status (unsigned long status)
491123123Simp{
492123123Simp	static char buf [80];
493123123Simp
494123123Simp	buf[0] = 0;
495123123Simp	if (status & E3_LOS)     strcat (buf, ",LOS");
496123123Simp	if (status & E3_TXE)     strcat (buf, ",XMIT");
497123123Simp	if (buf[0] == ',')
498123123Simp		return buf+1;
499123123Simp	return "Ok";
500123123Simp}
501123123Simp
502123123Simpstatic char *
503123123Simpformat_e3_cv (unsigned long cv, unsigned long baud, unsigned long time)
504123123Simp{
505123123Simp	static char buf[80];
506123123Simp
507123123Simp	if (!cv || !baud || !time)
508123123Simp		sprintf (buf, "         -         ");
509123123Simp	else
510123123Simp		sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/time);
511123123Simp	return buf;
512123123Simp}
513123123Simp
514123123Simpstatic void
515123123Simpprint_e3_stats (int fd, int need_header)
516123123Simp{
517123123Simp	struct e3_statistics st;
518123123Simp	int i, maxi;
519123123Simp	long baud;
520123123Simp
521123123Simp	if (need_header)
522123123Simp		printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n");
523123123Simp
524123123Simp	if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 ||
525123123Simp	    ioctl (fd, SERIAL_GETBAUD, &baud) < 0)
526123123Simp		return;
527123123Simp
528123123Simp	if (!st.cursec)
529123123Simp		st.cursec = 1;
530123123Simp
531123123Simp	printf ("%s\t%s\t\t\t\t\t", chan_name,
532123123Simp		format_e3_cv (st.ccv, baud, st.cursec));
533123123Simp
534123123Simp	printf (" %s\n", format_e3_status (st.status));
535123123Simp
536123123Simp
537123123Simp	if (uflag) {
538123123Simp		/* Print total statistics. */
539123123Simp		printf ("\t%s\t\t\t\t\t",
540123123Simp			format_e3_cv (st.tcv, baud, st.totsec));
541123123Simp		printf (" -- Total\n");
542123123Simp
543123123Simp		/* Print 24-hour history. */
544123123Simp		maxi = (st.totsec - st.cursec) / 900;
545123123Simp		if (maxi > 48)
546123123Simp			maxi = 48;
547123123Simp		for (i=0; i<maxi; ++i) {
548123123Simp			printf ("\t%s\t\t\t\t\t",
549123123Simp				format_e3_cv (st.icv[i], baud, 15*60));
550123123Simp			if (i < 3)
551123123Simp				printf (" -- %2dm\n", (i+1)*15);
552123123Simp			else
553123123Simp				printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15);
554123123Simp		}
555123123Simp	}
556123123Simp}
557123123Simp
558123123Simpstatic void
559123123Simpprint_chan (int fd)
560123123Simp{
561123123Simp	char protocol [8];
562123123Simp	char cfg;
563123123Simp	int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4;
564123123Simp	int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor;
565123123Simp	int cable, dir, scrambler;
566123123Simp	int cablen, rloop;
567123123Simp	long baud, timeslots, subchan;
568123123Simp	int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid;
569123123Simp	int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid;
570123123Simp	int timeslots_valid, subchan_valid, higain_valid, level_valid;
571123123Simp	int keepalive_valid, debug_valid, cfg_valid, port_valid;
572123123Simp	int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid;
573123123Simp	int cable_valid, dir_valid, scrambler_valid;
574123123Simp	int cablen_valid, rloop_valid;
575123123Simp
576123123Simp	protocol_valid  = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0;
577123123Simp	cfg_valid       = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0;
578123123Simp	baud_valid      = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0;
579123123Simp	loop_valid      = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0;
580123123Simp	dpll_valid      = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0;
581123123Simp	nrzi_valid      = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0;
582123123Simp	invclk_valid    = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0;
583123123Simp	invrclk_valid	= ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0;
584123123Simp	invtclk_valid	= ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0;
585123123Simp	clk_valid       = ioctl (fd, SERIAL_GETCLK, &clk) >= 0;
586123123Simp	timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, &timeslots) >= 0;
587123123Simp	subchan_valid   = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0;
588123123Simp	higain_valid    = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0;
589123123Simp	phony_valid     = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0;
590123123Simp	unfram_valid    = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0;
591123123Simp	monitor_valid   = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0;
592123123Simp	use16_valid     = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0;
593123123Simp	crc4_valid      = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0;
594123123Simp	level_valid     = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0;
595123123Simp	keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0;
596123123Simp	debug_valid     = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0;
597123123Simp	port_valid	= ioctl (fd, SERIAL_GETPORT, &port) >= 0;
598123123Simp	cable_valid	= ioctl (fd, SERIAL_GETCABLE, &cable) >= 0;
599123123Simp	dir_valid	= ioctl (fd, SERIAL_GETDIR, &dir) >= 0;
600123123Simp	scrambler_valid	= ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0;
601123123Simp	cablen_valid	= ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0;
602123123Simp	rloop_valid	= ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0;
603123123Simp
604123123Simp	printf ("%s", chan_name);
605123123Simp	if (port_valid)
606123123Simp		switch (port) {
607123123Simp		case 0:	printf (" (rs232)"); break;
608123123Simp		case 1:	printf (" (v35)"); break;
609123123Simp		case 2:	printf (" (rs530)"); break;
610123123Simp		}
611123123Simp	else if (cable_valid)
612123123Simp		switch (cable) {
613123123Simp		case 0:	printf (" (rs232)"); break;
614123123Simp		case 1:	printf (" (v35)"); break;
615123123Simp		case 2:	printf (" (rs530)"); break;
616123123Simp		case 3:	printf (" (x21)"); break;
617123123Simp		case 4:	printf (" (rs485)"); break;
618123123Simp		case 9:	printf (" (no cable)"); break;
619123123Simp		}
620123123Simp	if (debug_valid && debug)
621123123Simp		printf (" debug=%d", debug);
622123123Simp	if (protocol_valid && *protocol)
623123123Simp		printf (" %.8s", protocol);
624123123Simp	else
625123123Simp		printf (" idle");
626123123Simp	if (cablen_valid)
627123123Simp		printf (" cablen=%s", cablen ? "on" : "off");
628123123Simp	if (keepalive_valid)
629123123Simp		printf (" keepalive=%s", keepalive ? "on" : "off");
630123123Simp
631123123Simp	if (cfg_valid)
632123123Simp		switch (cfg) {
633123123Simp		case 'a' :	printf (" cfg=A");	break;
634123123Simp		case 'b' :	printf (" cfg=B");	break;
635123123Simp		case 'c' :	printf (" cfg=C");	break;
636123123Simp		case 'd' :	printf (" cfg=D");	break;
637123123Simp		default  :	printf (" cfg=unknown");
638123123Simp		}
639123123Simp	if (dir_valid)
640123123Simp		printf (" dir=%d", dir);
641123123Simp
642123123Simp	if (baud_valid) {
643123123Simp		if (baud)
644123123Simp			printf (" %ld", baud);
645123123Simp		else
646123123Simp			printf (" extclock");
647123123Simp	}
648123123Simp	if (clk_valid)
649123123Simp		switch (clk) {
650123123Simp		case E1CLK_INTERNAL:	  printf (" syn=int");     break;
651123123Simp		case E1CLK_RECEIVE:	  printf (" syn=rcv");     break;
652123123Simp		case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0");    break;
653123123Simp		case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1");    break;
654123123Simp		case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2");    break;
655123123Simp		case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3");    break;
656123123Simp		default:                  printf (" syn=%d", clk); break;
657123123Simp		}
658123123Simp
659123123Simp	if (dpll_valid)
660123123Simp		printf (" dpll=%s", dpll ? "on" : "off");
661123123Simp	if (nrzi_valid)
662123123Simp		printf (" nrzi=%s", nrzi ? "on" : "off");
663123123Simp	if (invclk_valid)
664123123Simp		printf (" invclk=%s", invclk ? "on" : "off");
665123123Simp	if (invrclk_valid)
666123123Simp		printf (" invrclk=%s", invrclk ? "on" : "off");
667123123Simp	if (invtclk_valid)
668123123Simp		printf (" invtclk=%s", invtclk ? "on" : "off");
669123123Simp	if (unfram_valid)
670123123Simp		printf (" unfram=%s", unfram ? "on" : "off");
671123123Simp	if (use16_valid)
672123123Simp		printf (" use16=%s", use16 ? "on" : "off");
673123123Simp	if (aflag) {
674123123Simp		if (crc4_valid)
675123123Simp			printf (" crc4=%s", crc4 ? "on" : "off");
676123123Simp		if (higain_valid)
677123123Simp			printf (" higain=%s", higain ? "on" : "off");
678123123Simp		if (monitor_valid)
679123123Simp			printf (" monitor=%s", monitor ? "on" : "off");
680123123Simp		if (phony_valid)
681123123Simp			printf (" phony=%s", phony ? "on" : "off");
682123123Simp		if (scrambler_valid)
683123123Simp			printf (" scrambler=%s", scrambler ? "on" : "off");
684123123Simp		if (loop_valid)
685123123Simp			printf (" loop=%s", loop ? "on" : "off");
686123123Simp		if (rloop_valid)
687123123Simp			printf (" rloop=%s", rloop ? "on" : "off");
688123123Simp	}
689123123Simp	if (timeslots_valid)
690123123Simp		printf (" ts=%s", format_timeslots (timeslots));
691123123Simp	if (subchan_valid)
692123123Simp		printf (" pass=%s", format_timeslots (subchan));
693123123Simp	if (level_valid)
694123123Simp		printf (" (level=-%.1fdB)", level / 10.0);
695123123Simp	printf ("\n");
696123123Simp}
697123123Simp
698123123Simpstatic void
699123123Simpsetup_chan (int fd, int argc, char **argv)
700123123Simp{
701123123Simp	int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram;
702123123Simp	int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk;
703123123Simp	int monitor, dir, scrambler, rloop, cablen;
704123123Simp	long baud, timeslots;
705123123Simp
706123123Simp	for (i=0; i<argc; ++i) {
707123123Simp		if (argv[i][0] >= '0' && argv[i][0] <= '9') {
708123123Simp			baud = strtol (argv[i], 0, 10);
709123123Simp			ioctl (fd, SERIAL_SETBAUD, &baud);
710123123Simp		} else if (strcasecmp ("extclock", argv[i]) == 0) {
711123123Simp			baud = 0;
712123123Simp			ioctl (fd, SERIAL_SETBAUD, &baud);
713123123Simp		} else if (strncasecmp ("cfg=", argv[i], 4) == 0) {
714123123Simp			if (strncasecmp ("a", argv[i]+4, 1) == 0)
715123123Simp				ioctl (fd, SERIAL_SETCFG, "a");
716123123Simp			else if (strncasecmp ("b", argv[i]+4, 1) == 0)
717123123Simp				ioctl (fd, SERIAL_SETCFG, "b");
718123123Simp			else if (strncasecmp ("c", argv[i]+4, 1) == 0)
719123123Simp				ioctl (fd, SERIAL_SETCFG, "c");
720123123Simp			else if (strncasecmp ("d", argv[i]+4, 1) == 0)
721123123Simp				ioctl (fd, SERIAL_SETCFG, "d");
722123123Simp			else {
723123123Simp				fprintf (stderr, "invalid cfg\n");
724123123Simp				exit (-1);
725123123Simp			}
726123123Simp		} else if (strcasecmp ("idle", argv[i]) == 0)
727123123Simp			ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0");
728123123Simp		else if (strcasecmp ("async", argv[i]) == 0) {
729123123Simp			mode = SERIAL_ASYNC;
730123123Simp			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
731123123Simp				ioctl (fd, SERIAL_SETPROTO, "async\0\0");
732123123Simp		} else if (strcasecmp ("sync", argv[i]) == 0) {
733123123Simp			mode = SERIAL_HDLC;
734123123Simp			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
735123123Simp				ioctl (fd, SERIAL_SETPROTO, "sync\0\0");
736123123Simp		} else if (strcasecmp ("cisco", argv[i]) == 0) {
737123123Simp			mode = SERIAL_HDLC;
738123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
739123123Simp			ioctl (fd, SERIAL_SETPROTO, "cisco\0\0");
740123123Simp		} else if (strcasecmp ("rbrg", argv[i]) == 0) {
741123123Simp			mode = SERIAL_HDLC;
742123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
743123123Simp			ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0");
744123123Simp		} else if (strcasecmp ("raw", argv[i]) == 0) {
745123123Simp			mode = SERIAL_HDLC;
746123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
747123123Simp			ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0");
748123123Simp		} else if (strcasecmp ("packet", argv[i]) == 0) {
749123123Simp			mode = SERIAL_HDLC;
750123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
751123123Simp			ioctl (fd, SERIAL_SETPROTO, "packet\0\0\0\0");
752123123Simp		} else if (strcasecmp ("ppp", argv[i]) == 0) {
753123123Simp			/* check that ppp line discipline is present */
754123123Simp			if (ppp_ok ()) {
755123123Simp				mode = SERIAL_HDLC;
756123123Simp				ioctl (fd, SERIAL_SETMODE, &mode);
757123123Simp				ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0");
758123123Simp			}
759123123Simp		} else if (strncasecmp ("keepalive=", argv[i], 10) == 0) {
760123123Simp			keepalive = (strcasecmp ("on", argv[i] + 10) == 0);
761123123Simp			ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive);
762123123Simp		} else if (strcasecmp ("fr", argv[i]) == 0) {
763123123Simp			mode = SERIAL_HDLC;
764123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
765123123Simp			ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0");
766123123Simp		} else if (strncasecmp ("debug=", argv[i], 6) == 0) {
767123123Simp			debug = strtol (argv[i]+6, 0, 10);
768123123Simp			ioctl (fd, SERIAL_SETDEBUG, &debug);
769123123Simp		} else if (strncasecmp ("loop=", argv[i], 5) == 0) {
770123123Simp			loop = (strcasecmp ("on", argv[i] + 5) == 0);
771123123Simp			ioctl (fd, SERIAL_SETLOOP, &loop);
772123123Simp		} else if (strncasecmp ("rloop=", argv[i], 6) == 0) {
773123123Simp			rloop = (strcasecmp ("on", argv[i] + 6) == 0);
774123123Simp			ioctl (fd, SERIAL_SETRLOOP, &rloop);
775123123Simp		} else if (strncasecmp ("dpll=", argv[i], 5) == 0) {
776123123Simp			dpll = (strcasecmp ("on", argv[i] + 5) == 0);
777123123Simp			ioctl (fd, SERIAL_SETDPLL, &dpll);
778123123Simp		} else if (strncasecmp ("nrzi=", argv[i], 5) == 0) {
779123123Simp			nrzi = (strcasecmp ("on", argv[i] + 5) == 0);
780123123Simp			ioctl (fd, SERIAL_SETNRZI, &nrzi);
781123123Simp		} else if (strncasecmp ("invclk=", argv[i], 7) == 0) {
782123123Simp			invclk = (strcasecmp ("on", argv[i] + 7) == 0);
783123123Simp			ioctl (fd, SERIAL_SETINVCLK, &invclk);
784123123Simp		} else if (strncasecmp ("invrclk=", argv[i], 8) == 0) {
785123123Simp			invrclk = (strcasecmp ("on", argv[i] + 8) == 0);
786123123Simp			ioctl (fd, SERIAL_SETINVRCLK, &invrclk);
787123123Simp		} else if (strncasecmp ("invtclk=", argv[i], 8) == 0) {
788123123Simp			invtclk = (strcasecmp ("on", argv[i] + 8) == 0);
789123123Simp			ioctl (fd, SERIAL_SETINVTCLK, &invtclk);
790123123Simp		} else if (strncasecmp ("higain=", argv[i], 7) == 0) {
791123123Simp			higain = (strcasecmp ("on", argv[i] + 7) == 0);
792123123Simp			ioctl (fd, SERIAL_SETHIGAIN, &higain);
793123123Simp		} else if (strncasecmp ("phony=", argv[i], 6) == 0) {
794123123Simp			phony = (strcasecmp ("on", argv[i] + 6) == 0);
795123123Simp			ioctl (fd, SERIAL_SETPHONY, &phony);
796123123Simp		} else if (strncasecmp ("unfram=", argv[i], 7) == 0) {
797123123Simp			unfram = (strcasecmp ("on", argv[i] + 7) == 0);
798123123Simp			ioctl (fd, SERIAL_SETUNFRAM, &unfram);
799123123Simp		} else if (strncasecmp ("scrambler=", argv[i], 10) == 0) {
800123123Simp			scrambler = (strcasecmp ("on", argv[i] + 10) == 0);
801123123Simp			ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler);
802123123Simp		} else if (strncasecmp ("monitor=", argv[i], 8) == 0) {
803123123Simp			monitor = (strcasecmp ("on", argv[i] + 8) == 0);
804123123Simp			ioctl (fd, SERIAL_SETMONITOR, &monitor);
805123123Simp		} else if (strncasecmp ("use16=", argv[i], 6) == 0) {
806123123Simp			use16 = (strcasecmp ("on", argv[i] + 6) == 0);
807123123Simp			ioctl (fd, SERIAL_SETUSE16, &use16);
808123123Simp		} else if (strncasecmp ("crc4=", argv[i], 5) == 0) {
809123123Simp			crc4 = (strcasecmp ("on", argv[i] + 5) == 0);
810123123Simp			ioctl (fd, SERIAL_SETCRC4, &crc4);
811123123Simp		} else if (strcasecmp ("syn=int", argv[i]) == 0) {
812123123Simp			clk = E1CLK_INTERNAL;
813123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
814123123Simp		} else if (strcasecmp ("syn=rcv", argv[i]) == 0) {
815123123Simp			clk = E1CLK_RECEIVE;
816123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
817123123Simp		} else if (strcasecmp ("syn=rcv0", argv[i]) == 0) {
818123123Simp			clk = E1CLK_RECEIVE_CHAN0;
819123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
820123123Simp		} else if (strcasecmp ("syn=rcv1", argv[i]) == 0) {
821123123Simp			clk = E1CLK_RECEIVE_CHAN1;
822123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
823123123Simp		} else if (strcasecmp ("syn=rcv2", argv[i]) == 0) {
824123123Simp			clk = E1CLK_RECEIVE_CHAN2;
825123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
826123123Simp		} else if (strcasecmp ("syn=rcv3", argv[i]) == 0) {
827123123Simp			clk = E1CLK_RECEIVE_CHAN3;
828123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
829123123Simp		} else if (strncasecmp ("ts=", argv[i], 3) == 0) {
830123123Simp			timeslots = scan_timeslots (argv[i] + 3);
831123123Simp			ioctl (fd, SERIAL_SETTIMESLOTS, &timeslots);
832123123Simp		} else if (strncasecmp ("pass=", argv[i], 5) == 0) {
833123123Simp			timeslots = scan_timeslots (argv[i] + 5);
834123123Simp			ioctl (fd, SERIAL_SETSUBCHAN, &timeslots);
835123123Simp		} else if (strncasecmp ("dlci", argv[i], 4) == 0) {
836123123Simp			dlci = strtol (argv[i]+4, 0, 10);
837123123Simp			ioctl (fd, SERIAL_ADDDLCI, &dlci);
838123123Simp		} else if (strncasecmp ("dir=", argv[i], 4) == 0) {
839123123Simp			dir = strtol (argv[i]+4, 0, 10);
840123123Simp			ioctl (fd, SERIAL_SETDIR, &dir);
841123123Simp		} else if (strncasecmp ("port=", argv[i], 5) == 0) {
842123123Simp			if (strncasecmp ("rs232", argv[i]+5, 5) == 0) {
843123123Simp				port = 0;
844123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
845123123Simp			} else if (strncasecmp ("v35", argv[i]+5, 3) == 0) {
846123123Simp				port = 1;
847123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
848123123Simp			} else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) {
849123123Simp				port = 2;
850123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
851123123Simp			} else
852123123Simp				fprintf (stderr, "invalid port type\n");
853123123Simp				exit (-1);
854123123Simp#if 1
855123123Simp		} else if (strcasecmp ("reset", argv[i]) == 0) {
856123123Simp			ioctl (fd, SERIAL_RESET, 0);
857123123Simp		} else if (strcasecmp ("hwreset", argv[i]) == 0) {
858123123Simp			ioctl (fd, SERIAL_HARDRESET, 0);
859123123Simp#endif
860123123Simp		} else if (strncasecmp ("cablen=", argv[i], 7) == 0) {
861123123Simp			loop = (strcasecmp ("on", argv[i] + 7) == 0);
862123123Simp			ioctl (fd, SERIAL_SETCABLEN, &cablen);
863123123Simp		}
864123123Simp	}
865123123Simp}
866123123Simp
867123123Simpstatic void
868123123Simpget_mask (void)
869123123Simp{
870123123Simp#ifdef __linux__
871123123Simp	int fd;
872123123Simp
873123123Simp	fd = open ("/dev/serial/ctl0", 0);
874123123Simp	if (fd < 0) {
875123123Simp		perror ("/dev/serial/ctl0");
876123123Simp		exit (-1);
877123123Simp	}
878123123Simp	if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
879123123Simp		perror ("getting list of channels");
880123123Simp		exit (-1);
881123123Simp	}
882123123Simp	close (fd);
883123123Simp#else
884123123Simp	int fd, fd1, fd2, i;
885123123Simp	char buf [80];
886123123Simp
887123123Simp	for (i=0, fd=-1; i<12 && fd<0; i++) {
888123123Simp		sprintf (buf, "/dev/cx%d", i*4);
889123123Simp		fd = open (buf, 0);
890123123Simp	}
891123123Simp
892123123Simp	for (i=0, fd1=-1; i<3 && fd1<0; i++) {
893123123Simp		sprintf (buf, "/dev/ct%d", i*2);
894123123Simp		fd1 = open (buf, 0);
895123123Simp	}
896123123Simp
897123123Simp	for (i=0, fd2=-1; i<3 && fd2<0; i++) {
898123123Simp		sprintf (buf, "/dev/cp%d", i*4);
899123123Simp		fd2 = open (buf, 0);
900123123Simp	}
901123123Simp
902123123Simp	if ((fd < 0) && (fd1 < 0) && (fd2 < 0)) {
903123123Simp		fprintf (stderr, "No Cronyx adapters installed\n");
904123123Simp		exit (-1);
905123123Simp	}
906123123Simp
907123123Simp	if (fd >= 0) {
908123123Simp		if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
909123123Simp			perror ("getting list of channels");
910123123Simp			exit (-1);
911123123Simp		}
912123123Simp		close (fd);
913123123Simp	}
914123123Simp
915123123Simp	if (fd1 >= 0) {
916123123Simp		if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) {
917123123Simp			perror ("getting list of channels");
918123123Simp			exit (-1);
919123123Simp		}
920123123Simp		close (fd1);
921123123Simp	}
922123123Simp
923123123Simp	if (fd2 >= 0) {
924123123Simp		if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) {
925123123Simp			perror ("getting list of channels");
926123123Simp			exit (-1);
927123123Simp		}
928123123Simp		close (fd2);
929123123Simp	}
930123123Simp#endif
931123123Simp}
932123123Simp
933123123Simpstatic int
934123123Simpopen_chan_ctl (int num)
935123123Simp{
936123123Simp	char device [80];
937123123Simp	int fd;
938123123Simp
939123123Simp#ifdef __linux__
940123123Simp	sprintf (device, "/dev/serial/ctl%d", num);
941123123Simp#else
942123123Simp	switch (adapter_type) {
943123123Simp	case 0:
944123123Simp		sprintf (device, "/dev/cx%d", num);
945123123Simp		break;
946123123Simp	case 1:
947123123Simp		sprintf (device, "/dev/ct%d", num);
948123123Simp		break;
949123123Simp	case 2:
950123123Simp		sprintf (device, "/dev/cp%d", num);
951123123Simp		break;
952123123Simp	}
953123123Simp#endif
954123123Simp	fd = open (device, 0);
955123123Simp	if (fd < 0) {
956123123Simp		if (errno == ENODEV)
957123123Simp			fprintf (stderr, "chan%d: not configured\n", num);
958123123Simp		else
959123123Simp			perror (device);
960123123Simp		exit (-1);
961123123Simp	}
962123123Simp#ifdef __linux__
963123123Simp	if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0)
964123123Simp		sprintf (chan_name, "chan%d", num);
965123123Simp#else
966123123Simp	switch (adapter_type) {
967123123Simp	case 0: sprintf (chan_name, "cx%d", num); break;
968123123Simp	case 1: sprintf (chan_name, "ct%d", num); break;
969123123Simp	case 2: sprintf (chan_name, "cp%d", num); break;
970123123Simp	}
971123123Simp#endif
972123123Simp	return fd;
973123123Simp}
974123123Simp
975123123Simpint
976123123Simpmain (int argc, char **argv)
977123123Simp{
978123123Simp	char *p;
979123123Simp	int fd, need_header, chan_num;
980123123Simp
981123123Simp	if (argc > 1 && strcmp(argv[1], "help") == 0)
982123123Simp		usage();
983123123Simp
984123123Simp	for (;;) {
985123123Simp		switch (getopt (argc, argv, "mseftucviax")) {
986123123Simp		case EOF:
987123123Simp			break;
988123123Simp		case 'a':
989123123Simp			++aflag;
990123123Simp			continue;
991123123Simp		case 'm':
992123123Simp			++mflag;
993123123Simp			continue;
994123123Simp		case 's':
995123123Simp			++sflag;
996123123Simp			continue;
997123123Simp		case 'e':
998123123Simp			++eflag;
999123123Simp			continue;
1000123123Simp		case 'f':
1001123123Simp			++eflag;
1002123123Simp			++fflag;
1003123123Simp			continue;
1004123123Simp		case 't':
1005123123Simp			++tflag;
1006123123Simp			continue;
1007123123Simp		case 'u':
1008123123Simp			++tflag;
1009123123Simp			++uflag;
1010123123Simp			continue;
1011123123Simp		case 'c':
1012123123Simp			++cflag;
1013123123Simp			continue;
1014123123Simp		case 'v':
1015123123Simp			++vflag;
1016123123Simp			continue;
1017123123Simp		case 'i':
1018123123Simp			++iflag;
1019123123Simp			continue;
1020123123Simp		case 'x':
1021123123Simp			++xflag;
1022123123Simp			continue;
1023123123Simp		default:
1024123123Simp			usage();
1025123123Simp		}
1026123123Simp		break;
1027123123Simp	}
1028123123Simp	argc -= optind;
1029123123Simp	argv += optind;
1030123123Simp
1031123123Simp	if (argc <= 0) {
1032123123Simp		get_mask ();
1033123123Simp		need_header = 1;
1034123123Simp		adapter_type = 0;
1035123123Simp#ifndef __linux__
1036123123Simp		for (; adapter_type < 3; ++adapter_type)
1037123123Simp#endif
1038123123Simp		{
1039123123Simp		for (chan_num=0; chan_num<MAXCHAN; ++chan_num)
1040123123Simp			if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) {
1041123123Simp				fd = open_chan_ctl (chan_num);
1042123123Simp				if (vflag) {
1043123123Simp#ifdef __linux__
1044123123Simp				char buf[256];
1045123123Simp				if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) {
1046123123Simp					printf ("Version: %s\n", buf);
1047123123Simp					close (fd);
1048123123Simp					return (0);
1049123123Simp				}
1050123123Simp#endif
1051123123Simp				}
1052123123Simp				if (iflag) {
1053123123Simp					print_chan (fd);
1054123123Simp					print_ifconfig (fd);
1055123123Simp				} else if (sflag||xflag)
1056123123Simp					print_stats (fd, need_header);
1057123123Simp				else if (mflag)
1058123123Simp					print_modems (fd, need_header);
1059123123Simp				else if (eflag)
1060123123Simp					print_e1_stats (fd, need_header);
1061123123Simp				else if (tflag)
1062123123Simp					print_e3_stats (fd, need_header);
1063123123Simp				else if (cflag)
1064123123Simp					clear_stats (fd);
1065123123Simp				else
1066123123Simp					print_chan (fd);
1067123123Simp				close (fd);
1068123123Simp				need_header = 0;
1069123123Simp			}
1070123123Simp		}
1071123123Simp		return (0);
1072123123Simp	}
1073123123Simp
1074123123Simp	p = argv[0] + strlen (argv[0]);
1075123123Simp	while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9')
1076123123Simp		--p;
1077123123Simp	chan_num = strtol (p, 0, 10);
1078123123Simp#ifndef __linux__
1079123123Simp	if (strncasecmp ("cx", argv[0], 2)==0)
1080123123Simp		adapter_type = 0;
1081123123Simp	else if (strncasecmp ("ct", argv[0], 2)==0)
1082123123Simp		adapter_type = 1;
1083123123Simp	else if (strncasecmp ("cp", argv[0], 2)==0)
1084123123Simp		adapter_type = 2;
1085123123Simp	else {
1086123123Simp		fprintf (stderr, "Wrong channel name\n");
1087123123Simp		exit (-1);
1088123123Simp	}
1089123123Simp#endif
1090123123Simp	argc--;
1091123123Simp	argv++;
1092123123Simp
1093123123Simp	fd = open_chan_ctl (chan_num);
1094123123Simp	if (vflag) {
1095123123Simp#ifdef __linux__
1096123123Simp		char buf[256];
1097123123Simp		if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0)
1098123123Simp			printf ("Version: %s\n", buf);
1099123123Simp#endif
1100123123Simp	}
1101123123Simp	if (iflag) {
1102123123Simp		print_chan (fd);
1103123123Simp		print_ifconfig (fd);
1104123123Simp		close (fd);
1105123123Simp		return (0);
1106123123Simp	}
1107123123Simp	if (sflag||xflag) {
1108123123Simp		print_stats (fd, 1);
1109123123Simp		close (fd);
1110123123Simp		return (0);
1111123123Simp	}
1112123123Simp	if (mflag) {
1113123123Simp		print_modems (fd, 1);
1114123123Simp		close (fd);
1115123123Simp		return (0);
1116123123Simp	}
1117123123Simp	if (eflag) {
1118123123Simp		print_e1_stats (fd, 1);
1119123123Simp		close (fd);
1120123123Simp		return (0);
1121123123Simp	}
1122123123Simp	if (tflag) {
1123123123Simp		print_e3_stats (fd, 1);
1124123123Simp		close (fd);
1125123123Simp		return (0);
1126123123Simp	}
1127123123Simp	if (cflag) {
1128123123Simp		clear_stats (fd);
1129123123Simp		close (fd);
1130123123Simp		return (0);
1131123123Simp	}
1132123123Simp	if (argc > 0)
1133123123Simp		setup_chan (fd, argc, argv);
1134123123Simp	else
1135123123Simp		print_chan (fd);
1136123123Simp	close (fd);
1137123123Simp	return (0);
1138123123Simp}
1139123123Simp/*
1140123123Simp * Channel configuration utility for Cronyx serial adapters.
1141123123Simp *
1142123123Simp * Copyright (C) 1997-2002 Cronyx Engineering.
1143123123Simp * Author: Serge Vakulenko, <vak@cronyx.ru>
1144123123Simp *
1145123123Simp * Copyright (C) 1999-2003 Cronyx Engineering.
1146123123Simp * Author: Roman Kurakin, <rik@cronyx.ru>
1147123123Simp *
1148123123Simp * This software is distributed with NO WARRANTIES, not even the implied
1149123123Simp * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1150123123Simp *
1151123123Simp * Authors grant any other persons or organisations permission to use
1152123123Simp * or modify this software as long as this message is kept with the software,
1153123123Simp * all derivative works or modified versions.
1154123123Simp *
1155123123Simp * $Id: sconfig.c,v 1.2.2.4 2003/06/20 16:20:48 rik Exp $
1156123123Simp */
1157123123Simp#include <stdio.h>
1158123123Simp#include <stdlib.h>
1159123123Simp#include <string.h>
1160123123Simp#include <unistd.h>
1161123123Simp#include <fcntl.h>
1162123123Simp#include <errno.h>
1163123123Simp#include <ctype.h>
1164123123Simp#include <sys/ioctl.h>
1165123123Simp#include <sys/types.h>
1166123123Simp#include <sys/stat.h>
1167123123Simp#include <sys/socket.h>
1168123123Simp#include <net/if.h>
1169123123Simp#include <machine/cserial.h>
1170123123Simp
1171123123Simp#define MAXCHAN 128
1172123123Simp
1173123123Simpint vflag, eflag, sflag, mflag, cflag, fflag, iflag, aflag, xflag;
1174123123Simpint tflag, uflag;
1175123123Simpchar mask[48];
1176123123Simpint adapter_type;		/* 0-sigma, 1-tau, 2-tau */
1177123123Simpchar chan_name[16];
1178123123Simp
1179123123Simpextern char *optarg;
1180123123Simpextern int optind;
1181123123Simp
1182123123Simpstatic void
1183123123Simpusage (void)
1184123123Simp{
1185123123Simp	printf(
1186123123Simp"Serial Adapter Configuration Utility\n"
1187123123Simp"Copyright (C) 1998-1999 Cronyx Engineering Ltd.\n"
1188123123Simp"See also man sconfig (8)\n"
1189123123Simp"Usage:\n"
1190123123Simp"\tsconfig [-aimsxeftuc] [device [parameters ...]]\n"
1191123123Simp"\n"
1192123123Simp"Options:\n"
1193123123Simp"\t<no options>\t\t -- print channel options\n"
1194123123Simp"\t-a\t\t\t -- print all settings of the channel\n"
1195123123Simp"\t-i\t\t\t -- print network interface status\n"
1196123123Simp"\t-m\t\t\t -- print modem signal status\n"
1197123123Simp"\t-s\t\t\t -- print channel statistics\n"
1198123123Simp"\t-x\t\t\t -- print extended channel statistics\n"
1199123123Simp"\t-e\t\t\t -- print short E1/G703 statistics\n"
1200123123Simp"\t-f\t\t\t -- print full E1/G703 statistics\n"
1201123123Simp"\t-t\t\t\t -- print short E3/T3/STS-1 statistics\n"
1202123123Simp"\t-u\t\t\t -- print full E3/T3/STS-1 statistics\n"
1203123123Simp"\t-c\t\t\t -- clear statistics\n"
1204123123Simp"\nParameters:\n"
1205123123Simp"\t<number>\t\t -- baud rate, internal clock\n"
1206123123Simp"\textclock\t\t -- external clock (default)\n"
1207123123Simp"\nProtocol options:\n"
1208123123Simp"\tasync\t\t\t -- asynchronous protocol\n"
1209123123Simp#ifdef __linux__
1210123123Simp"\tsync\t\t\t -- synchronous protocol\n"
1211123123Simp#endif
1212123123Simp"\tcisco\t\t\t -- Cisco/HDLC protocol\n"
1213123123Simp"\tfr\t\t\t -- Frame Relay protocol\n"
1214123123Simp#ifdef __linux__
1215123123Simp"\t    dlci<number>\t -- Add new DLCI\n"
1216123123Simp#endif
1217123123Simp"\tppp\t\t\t -- PPP protocol\n"
1218123123Simp#ifdef __linux__
1219123123Simp"\trbrg\t\t\t -- Remote bridge\n"
1220123123Simp"\traw\t\t\t -- raw HDLC protocol\n"
1221123123Simp"\tpacket\t\t\t -- packetized HDLC protocol\n"
1222123123Simp"\tidle\t\t\t -- no protocol\n"
1223123123Simp#else
1224123123Simp"\t    keepalive={on,of}\t -- Enable/disable keepalive\n"
1225123123Simp#endif
1226123123Simp"\nInterface options:\n"
1227123123Simp"\tport={rs232,v35,rs449}\t -- port type (for old models of Sigma)\n"
1228123123Simp"\tcfg={A,B,C}\t\t -- adapter configuration\n"
1229123123Simp"\tloop={on,off}\t\t -- internal loopback\n"
1230123123Simp"\trloop={on,off}\t\t -- remote loopback\n"
1231123123Simp"\tdpll={on,off}\t\t -- DPLL mode\n"
1232123123Simp"\tnrzi={on,off}\t\t -- NRZI encoding\n"
1233123123Simp"\tinvclk={on,off}\t\t -- invert receive and transmit clock\n"
1234123123Simp"\tinvrclk={on,off}\t -- invert receive clock\n"
1235123123Simp"\tinvtclk={on,off}\t -- invert transmit clock\n"
1236123123Simp"\thigain={on,off}\t\t -- E1 high non linear input sensitivity \n\t\t\t\t    (long line)\n"
1237123123Simp"\tmonitor={on,off}\t -- E1 high linear input sensitivity \n\t\t\t\t    (interception mode)\n"
1238123123Simp"\tphony={on,off}\t\t -- E1 telepnony mode\n"
1239123123Simp"\tunfram={on,off}\t\t -- E1 unframed mode\n"
1240123123Simp"\tscrambler={on,off}\t -- G.703 scrambling mode\n"
1241123123Simp"\tuse16={on,off}\t\t -- E1 timeslot 16 usage\n"
1242123123Simp"\tcrc4={on,off}\t\t -- E1 CRC4 mode\n"
1243123123Simp"\tsyn={int,rcv,rcvX}\t -- G.703 transmit clock\n"
1244123123Simp"\tts=...\t\t\t -- E1 timeslots\n"
1245123123Simp"\tpass=...\t\t -- E1 subchannel timeslots\n"
1246123123Simp"\tdir=<num>\t\t -- connect channel to link<num>\n"
1247123123Simp/*"\tcablen={on,off}\t\t -- T3/STS-1 high transmitter output for long cable\n"*/
1248123123Simp"\tdebug={0,1,2}\t\t -- enable/disable debug messages\n"
1249123123Simp	);
1250123123Simp	exit (0);
1251123123Simp}
1252123123Simp
1253123123Simpstatic unsigned long
1254123123Simpscan_timeslots (char *s)
1255123123Simp{
1256123123Simp	char *e;
1257123123Simp	long v;
1258123123Simp	int i;
1259123123Simp	unsigned long ts, lastv;
1260123123Simp
1261123123Simp	ts = lastv = 0;
1262123123Simp	for (;;) {
1263123123Simp		v = strtol (s, &e, 10);
1264123123Simp		if (e == s)
1265123123Simp			break;
1266123123Simp		if (*e == '-') {
1267123123Simp			lastv = v;
1268123123Simp			s = e+1;
1269123123Simp			continue;
1270123123Simp		}
1271123123Simp		if (*e == ',')
1272123123Simp			++e;
1273123123Simp
1274123123Simp		if (lastv)
1275123123Simp			for (i=lastv; i<v; ++i)
1276123123Simp				ts |= 1L << i;
1277123123Simp		ts |= 1L << v;
1278123123Simp
1279123123Simp		lastv = 0;
1280123123Simp		s = e;
1281123123Simp	}
1282123123Simp	return ts;
1283123123Simp}
1284123123Simp
1285123123Simpstatic int
1286123123Simpppp_ok (void)
1287123123Simp{
1288123123Simp#ifdef __linux__
1289123123Simp	int s, p;
1290123123Simp	struct ifreq ifr;
1291123123Simp	char pttyname[32];
1292123123Simp	char *p1, *p2;
1293123123Simp	int i, j;
1294123123Simp	int ppp_disc = N_PPP;
1295123123Simp
1296123123Simp	/*
1297123123Simp	 * Open a socket for doing the ioctl operations.
1298123123Simp	 */
1299123123Simp	s = socket (AF_INET, SOCK_DGRAM, 0);
1300123123Simp	if (s < 0) {
1301123123Simp		fprintf (stderr, "Error opening socket.\n");
1302123123Simp		return 0;
1303123123Simp	}
1304123123Simp	strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
1305123123Simp	if (ioctl (s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0) {
1306123123Simp		/* Ok. */
1307123123Simp		close (s);
1308123123Simp		return 1;
1309123123Simp	}
1310123123Simp	close (s);
1311123123Simp
1312123123Simp	/* open pseudo-tty and try to set PPP discipline */
1313123123Simp	sprintf (pttyname, "/dev/ptyXX");
1314123123Simp	p1 = &pttyname[8];
1315123123Simp	p2 = &pttyname[9];
1316123123Simp	for (i=0; i<16; i++) {
1317123123Simp		struct stat stb;
1318123123Simp
1319123123Simp		*p1 = "pqrstuvwxyzabcde"[i];
1320123123Simp		*p2 = '0';
1321123123Simp		if (stat (pttyname, &stb) < 0)
1322123123Simp			continue;
1323123123Simp		for (j=0; j<16; j++) {
1324123123Simp			*p2 = "0123456789abcdef"[j];
1325123123Simp			p = open (pttyname, 2);
1326123123Simp			if (p > 0) {
1327123123Simp				if (ioctl (p, TIOCSETD, &ppp_disc) < 0) {
1328123123Simp					fprintf (stderr, "No PPP discipline in kernel.\n");
1329123123Simp					close (p);
1330123123Simp					return 0;
1331123123Simp				}
1332123123Simp				close (p);
1333123123Simp				return 1;
1334123123Simp			}
1335123123Simp		}
1336123123Simp	}
1337123123Simp	fprintf (stderr, "Cannot get pseudo-tty.\n");
1338123123Simp	return 0;
1339123123Simp#else
1340123123Simp	return 1;
1341123123Simp#endif
1342123123Simp}
1343123123Simp
1344123123Simpstatic char *
1345123123Simpformat_timeslots (unsigned long s)
1346123123Simp{
1347123123Simp	static char buf [100];
1348123123Simp	char *p = buf;
1349123123Simp	int i;
1350123123Simp
1351123123Simp	for (i=1; i<32; ++i)
1352123123Simp		if ((s >> i) & 1) {
1353123123Simp			int prev = (i > 1)  & (s >> (i-1));
1354123123Simp			int next = (i < 31) & (s >> (i+1));
1355123123Simp
1356123123Simp			if (prev) {
1357123123Simp				if (next)
1358123123Simp					continue;
1359123123Simp				*p++ = '-';
1360123123Simp			} else if (p > buf)
1361123123Simp				*p++ = ',';
1362123123Simp
1363123123Simp			if (i >= 10)
1364123123Simp				*p++ = '0' + i / 10;
1365123123Simp			*p++ = '0' + i % 10;
1366123123Simp		}
1367123123Simp	*p = 0;
1368123123Simp	return buf;
1369123123Simp}
1370123123Simp
1371123123Simpstatic void
1372123123Simpprint_modems (int fd, int need_header)
1373123123Simp{
1374123123Simp	int status;
1375123123Simp
1376123123Simp	if (ioctl (fd, TIOCMGET, &status) < 0) {
1377123123Simp		perror ("getting modem status");
1378123123Simp		return;
1379123123Simp	}
1380123123Simp	if (need_header)
1381123123Simp		printf ("Channel\tLE\tDTR\tDSR\tRTS\tCTS\tCD\n");
1382123123Simp	printf ("%s\t%s\t%s\t%s\t%s\t%s\t%s\n", chan_name,
1383123123Simp		status & TIOCM_LE  ? "On" : "-",
1384123123Simp		status & TIOCM_DTR ? "On" : "-",
1385123123Simp		status & TIOCM_DSR ? "On" : "-",
1386123123Simp		status & TIOCM_RTS ? "On" : "-",
1387123123Simp		status & TIOCM_CTS ? "On" : "-",
1388123123Simp		status & TIOCM_CD  ? "On" : "-");
1389123123Simp}
1390123123Simp
1391123123Simpstatic void
1392123123Simpprint_ifconfig (int fd)
1393123123Simp{
1394123123Simp	char buf [64];
1395123123Simp#ifdef __linux__
1396123123Simp	char protocol [8];
1397123123Simp
1398123123Simp	if (ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0 &&
1399123123Simp	    strcmp (protocol, "fr") == 0)
1400123123Simp		sprintf (buf, "ifconfig %sd16 2>/dev/null", chan_name);
1401123123Simp	else
1402123123Simp#endif
1403123123Simp	sprintf (buf, "ifconfig %s 2>/dev/null", chan_name);
1404123123Simp	system (buf);
1405123123Simp}
1406123123Simp
1407123123Simpstatic char *
1408123123Simpformat_long (unsigned long val)
1409123123Simp{
1410123123Simp	static char s[32];
1411123123Simp	int l;
1412123123Simp	l = sprintf (s, "%lu", val);
1413123123Simp	if (l>7 && !sflag) {
1414123123Simp		s[3] = s[2];
1415123123Simp		s[2] = s[1];
1416123123Simp		s[1] = '.';
1417123123Simp		s[4] = 'e';
1418123123Simp		sprintf (s + 5, "%02d", l-1);
1419123123Simp	}
1420123123Simp	return s;
1421123123Simp}
1422123123Simp
1423123123Simpstatic void
1424123123Simpprint_stats (int fd, int need_header)
1425123123Simp{
1426123123Simp	struct serial_statistics st;
1427123123Simp	unsigned long sarr [9];
1428123123Simp	int i;
1429123123Simp
1430123123Simp	if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) {
1431123123Simp		perror ("getting statistics");
1432123123Simp		return;
1433123123Simp	}
1434123123Simp	if (need_header) {
1435123123Simp		if (sflag) {
1436123123Simp			printf ("        ------------Receive-----------      "
1437123123Simp				"------------Transmit----------\n");
1438123123Simp			printf ("Channel Interrupts  Packets     Errors      "
1439123123Simp				"Interrupts  Packets     Errors\n");
1440123123Simp		}
1441123123Simp		else    {
1442123123Simp			printf ("        --------Receive---------------  "
1443123123Simp				"--------Transmit--------------  Modem\n");
1444123123Simp			printf ("Channel Intrs   Bytes   Packets Errors  "
1445123123Simp				"Intrs   Bytes   Packets Errors  Intrs\n");
1446123123Simp		}
1447123123Simp	}
1448123123Simp
1449123123Simp	sarr [0] = st.rintr;
1450123123Simp	sarr [1] = st.ibytes;
1451123123Simp	sarr [2] = st.ipkts;
1452123123Simp	sarr [3] = st.ierrs;
1453123123Simp	sarr [4] = st.tintr;
1454123123Simp	sarr [5] = st.obytes;
1455123123Simp	sarr [6] = st.opkts;
1456123123Simp	sarr [7] = st.oerrs;
1457123123Simp	sarr [8] = st.mintr;
1458123123Simp	printf ("%s", chan_name);
1459123123Simp	if (sflag) {
1460123123Simp		printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0],
1461123123Simp			sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]);
1462123123Simp	} else {
1463123123Simp		for (i = 0; i < 9; i++)
1464123123Simp			printf ("\t%s", format_long (sarr [i]));
1465123123Simp		printf ("\n");
1466123123Simp	}
1467123123Simp}
1468123123Simp
1469123123Simpstatic void
1470123123Simpclear_stats (int fd)
1471123123Simp{
1472123123Simp	if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) {
1473123123Simp		perror ("clearing statistics");
1474123123Simp		exit (-1);
1475123123Simp	}
1476123123Simp}
1477123123Simp
1478123123Simpstatic char *
1479123123Simpformat_e1_status (unsigned long status)
1480123123Simp{
1481123123Simp	static char buf [80];
1482123123Simp
1483123123Simp	if (status & E1_NOALARM)
1484123123Simp		return "Ok";
1485123123Simp	buf[0] = 0;
1486123123Simp	if (status & E1_LOS)     strcat (buf, ",LOS");
1487123123Simp	if (status & E1_AIS)     strcat (buf, ",AIS");
1488123123Simp	if (status & E1_LOF)     strcat (buf, ",LOF");
1489123123Simp	if (status & E1_LOMF)    strcat (buf, ",LOMF");
1490123123Simp	if (status & E1_FARLOF)  strcat (buf, ",FARLOF");
1491123123Simp	if (status & E1_AIS16)   strcat (buf, ",AIS16");
1492123123Simp	if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
1493123123Simp/*	if (status & E1_TSTREQ)  strcat (buf, ",TSTREQ");*/
1494123123Simp/*	if (status & E1_TSTERR)  strcat (buf, ",TSTERR");*/
1495123123Simp	if (buf[0] == ',')
1496123123Simp		return buf+1;
1497123123Simp	return "Unknown";
1498123123Simp}
1499123123Simp
1500123123Simpstatic void
1501123123Simpprint_frac (int leftalign, unsigned long numerator, unsigned long divider)
1502123123Simp{
1503123123Simp	int n;
1504123123Simp
1505123123Simp	if (numerator < 1 || divider < 1) {
1506123123Simp		printf (leftalign ? "/-   " : "    -");
1507123123Simp		return;
1508123123Simp	}
1509123123Simp	n = (int) (0.5 + 1000.0 * numerator / divider);
1510123123Simp	if (n < 1000) {
1511123123Simp		printf (leftalign ? "/.%-3d" : " .%03d", n);
1512123123Simp		return;
1513123123Simp	}
1514123123Simp	putchar (leftalign ? '/' : ' ');
1515123123Simp
1516123123Simp	if      (n >= 1000000) n = (n+500) / 1000 * 1000;
1517123123Simp	else if (n >= 100000)  n = (n+50)  / 100 * 100;
1518123123Simp	else if (n >= 10000)   n = (n+5)   / 10 * 10;
1519123123Simp
1520123123Simp	switch (n) {
1521123123Simp	case 1000:    printf (".999"); return;
1522123123Simp	case 10000:   n = 9990;   break;
1523123123Simp	case 100000:  n = 99900;  break;
1524123123Simp	case 1000000: n = 999000; break;
1525123123Simp	}
1526123123Simp	if (n < 10000)        printf ("%d.%d", n/1000, n/10%100);
1527123123Simp	else if (n < 100000)  printf ("%d.%d", n/1000, n/100%10);
1528123123Simp	else if (n < 1000000) printf ("%d.", n/1000);
1529123123Simp	else                  printf ("%d", n/1000);
1530123123Simp}
1531123123Simp
1532123123Simpstatic void
1533123123Simpprint_e1_stats (int fd, int need_header)
1534123123Simp{
1535123123Simp	struct e1_statistics st;
1536123123Simp	int i, maxi;
1537123123Simp
1538123123Simp	if (need_header)
1539123123Simp		printf ("Chan\t Unav/Degr  Bpv/Fsyn  CRC/RCRC  Err/Lerr  Sev/Bur   Oof/Slp  Status\n");
1540123123Simp
1541123123Simp	if (ioctl (fd, SERIAL_GETESTAT, &st) < 0)
1542123123Simp		return;
1543123123Simp	printf ("%s\t", chan_name);
1544123123Simp
1545123123Simp	/* Unavailable seconds, degraded minutes */
1546123123Simp	print_frac (0, st.currnt.uas, st.cursec);
1547123123Simp	print_frac (1, 60 * st.currnt.dm, st.cursec);
1548123123Simp
1549123123Simp	/* Bipolar violations, frame sync errors */
1550123123Simp	print_frac (0, st.currnt.bpv, st.cursec);
1551123123Simp	print_frac (1, st.currnt.fse, st.cursec);
1552123123Simp
1553123123Simp	/* CRC errors, remote CRC errors (E-bit) */
1554123123Simp	print_frac (0, st.currnt.crce, st.cursec);
1555123123Simp	print_frac (1, st.currnt.rcrce, st.cursec);
1556123123Simp
1557123123Simp	/* Errored seconds, line errored seconds */
1558123123Simp	print_frac (0, st.currnt.es, st.cursec);
1559123123Simp	print_frac (1, st.currnt.les, st.cursec);
1560123123Simp
1561123123Simp	/* Severely errored seconds, bursty errored seconds */
1562123123Simp	print_frac (0, st.currnt.ses, st.cursec);
1563123123Simp	print_frac (1, st.currnt.bes, st.cursec);
1564123123Simp
1565123123Simp	/* Out of frame seconds, controlled slip seconds */
1566123123Simp	print_frac (0, st.currnt.oofs, st.cursec);
1567123123Simp	print_frac (1, st.currnt.css, st.cursec);
1568123123Simp
1569123123Simp	printf (" %s\n", format_e1_status (st.status));
1570123123Simp
1571123123Simp	if (fflag) {
1572123123Simp		/* Print total statistics. */
1573123123Simp		printf ("\t");
1574123123Simp		print_frac (0, st.total.uas, st.totsec);
1575123123Simp		print_frac (1, 60 * st.total.dm, st.totsec);
1576123123Simp
1577123123Simp		print_frac (0, st.total.bpv, st.totsec);
1578123123Simp		print_frac (1, st.total.fse, st.totsec);
1579123123Simp
1580123123Simp		print_frac (0, st.total.crce, st.totsec);
1581123123Simp		print_frac (1, st.total.rcrce, st.totsec);
1582123123Simp
1583123123Simp		print_frac (0, st.total.es, st.totsec);
1584123123Simp		print_frac (1, st.total.les, st.totsec);
1585123123Simp
1586123123Simp		print_frac (0, st.total.ses, st.totsec);
1587123123Simp		print_frac (1, st.total.bes, st.totsec);
1588123123Simp
1589123123Simp		print_frac (0, st.total.oofs, st.totsec);
1590123123Simp		print_frac (1, st.total.css, st.totsec);
1591123123Simp
1592123123Simp		printf (" -- Total\n");
1593123123Simp
1594123123Simp		/* Print 24-hour history. */
1595123123Simp		maxi = (st.totsec - st.cursec) / 900;
1596123123Simp		if (maxi > 48)
1597123123Simp			maxi = 48;
1598123123Simp		for (i=0; i<maxi; ++i) {
1599123123Simp			printf ("       ");
1600123123Simp			print_frac (0, st.interval[i].uas, 15*60);
1601123123Simp			print_frac (1, 60 * st.interval[i].dm, 15*60);
1602123123Simp
1603123123Simp			print_frac (0, st.interval[i].bpv, 15*60);
1604123123Simp			print_frac (1, st.interval[i].fse, 15*60);
1605123123Simp
1606123123Simp			print_frac (0, st.interval[i].crce, 15*60);
1607123123Simp			print_frac (1, st.interval[i].rcrce, 15*60);
1608123123Simp
1609123123Simp			print_frac (0, st.interval[i].es, 15*60);
1610123123Simp			print_frac (1, st.interval[i].les, 15*60);
1611123123Simp
1612123123Simp			print_frac (0, st.interval[i].ses, 15*60);
1613123123Simp			print_frac (1, st.interval[i].bes, 15*60);
1614123123Simp
1615123123Simp			print_frac (0, st.interval[i].oofs, 15*60);
1616123123Simp			print_frac (1, st.interval[i].css, 15*60);
1617123123Simp
1618123123Simp			if (i < 3)
1619123123Simp				printf (" -- %dm\n", (i+1)*15);
1620123123Simp			else
1621123123Simp				printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15);
1622123123Simp		}
1623123123Simp	}
1624123123Simp}
1625123123Simp
1626123123Simpstatic char *
1627123123Simpformat_e3_status (unsigned long status)
1628123123Simp{
1629123123Simp	static char buf [80];
1630123123Simp
1631123123Simp	buf[0] = 0;
1632123123Simp	if (status & E3_LOS)     strcat (buf, ",LOS");
1633123123Simp	if (status & E3_TXE)     strcat (buf, ",XMIT");
1634123123Simp	if (buf[0] == ',')
1635123123Simp		return buf+1;
1636123123Simp	return "Ok";
1637123123Simp}
1638123123Simp
1639123123Simpstatic char *
1640123123Simpformat_e3_cv (unsigned long cv, unsigned long baud, unsigned long time)
1641123123Simp{
1642123123Simp	static char buf[80];
1643123123Simp
1644123123Simp	if (!cv || !baud || !time)
1645123123Simp		sprintf (buf, "         -         ");
1646123123Simp	else
1647123123Simp		sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/time);
1648123123Simp	return buf;
1649123123Simp}
1650123123Simp
1651123123Simpstatic void
1652123123Simpprint_e3_stats (int fd, int need_header)
1653123123Simp{
1654123123Simp	struct e3_statistics st;
1655123123Simp	int i, maxi;
1656123123Simp	long baud;
1657123123Simp
1658123123Simp	if (need_header)
1659123123Simp		printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n");
1660123123Simp
1661123123Simp	if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 ||
1662123123Simp	    ioctl (fd, SERIAL_GETBAUD, &baud) < 0)
1663123123Simp		return;
1664123123Simp
1665123123Simp	if (!st.cursec)
1666123123Simp		st.cursec = 1;
1667123123Simp
1668123123Simp	printf ("%s\t%s\t\t\t\t\t", chan_name,
1669123123Simp		format_e3_cv (st.ccv, baud, st.cursec));
1670123123Simp
1671123123Simp	printf (" %s\n", format_e3_status (st.status));
1672123123Simp
1673123123Simp
1674123123Simp	if (uflag) {
1675123123Simp		/* Print total statistics. */
1676123123Simp		printf ("\t%s\t\t\t\t\t",
1677123123Simp			format_e3_cv (st.tcv, baud, st.totsec));
1678123123Simp		printf (" -- Total\n");
1679123123Simp
1680123123Simp		/* Print 24-hour history. */
1681123123Simp		maxi = (st.totsec - st.cursec) / 900;
1682123123Simp		if (maxi > 48)
1683123123Simp			maxi = 48;
1684123123Simp		for (i=0; i<maxi; ++i) {
1685123123Simp			printf ("\t%s\t\t\t\t\t",
1686123123Simp				format_e3_cv (st.icv[i], baud, 15*60));
1687123123Simp			if (i < 3)
1688123123Simp				printf (" -- %2dm\n", (i+1)*15);
1689123123Simp			else
1690123123Simp				printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15);
1691123123Simp		}
1692123123Simp	}
1693123123Simp}
1694123123Simp
1695123123Simpstatic void
1696123123Simpprint_chan (int fd)
1697123123Simp{
1698123123Simp	char protocol [8];
1699123123Simp	char cfg;
1700123123Simp	int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4;
1701123123Simp	int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor;
1702123123Simp	int cable, dir, scrambler;
1703123123Simp	int cablen, rloop;
1704123123Simp	long baud, timeslots, subchan;
1705123123Simp	int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid;
1706123123Simp	int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid;
1707123123Simp	int timeslots_valid, subchan_valid, higain_valid, level_valid;
1708123123Simp	int keepalive_valid, debug_valid, cfg_valid, port_valid;
1709123123Simp	int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid;
1710123123Simp	int cable_valid, dir_valid, scrambler_valid;
1711123123Simp	int cablen_valid, rloop_valid;
1712123123Simp
1713123123Simp	protocol_valid  = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0;
1714123123Simp	cfg_valid       = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0;
1715123123Simp	baud_valid      = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0;
1716123123Simp	loop_valid      = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0;
1717123123Simp	dpll_valid      = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0;
1718123123Simp	nrzi_valid      = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0;
1719123123Simp	invclk_valid    = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0;
1720123123Simp	invrclk_valid	= ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0;
1721123123Simp	invtclk_valid	= ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0;
1722123123Simp	clk_valid       = ioctl (fd, SERIAL_GETCLK, &clk) >= 0;
1723123123Simp	timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, &timeslots) >= 0;
1724123123Simp	subchan_valid   = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0;
1725123123Simp	higain_valid    = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0;
1726123123Simp	phony_valid     = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0;
1727123123Simp	unfram_valid    = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0;
1728123123Simp	monitor_valid   = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0;
1729123123Simp	use16_valid     = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0;
1730123123Simp	crc4_valid      = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0;
1731123123Simp	level_valid     = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0;
1732123123Simp	keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0;
1733123123Simp	debug_valid     = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0;
1734123123Simp	port_valid	= ioctl (fd, SERIAL_GETPORT, &port) >= 0;
1735123123Simp	cable_valid	= ioctl (fd, SERIAL_GETCABLE, &cable) >= 0;
1736123123Simp	dir_valid	= ioctl (fd, SERIAL_GETDIR, &dir) >= 0;
1737123123Simp	scrambler_valid	= ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0;
1738123123Simp	cablen_valid	= ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0;
1739123123Simp	rloop_valid	= ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0;
1740123123Simp
1741123123Simp	printf ("%s", chan_name);
1742123123Simp	if (port_valid)
1743123123Simp		switch (port) {
1744123123Simp		case 0:	printf (" (rs232)"); break;
1745123123Simp		case 1:	printf (" (v35)"); break;
1746123123Simp		case 2:	printf (" (rs530)"); break;
1747123123Simp		}
1748123123Simp	else if (cable_valid)
1749123123Simp		switch (cable) {
1750123123Simp		case 0:	printf (" (rs232)"); break;
1751123123Simp		case 1:	printf (" (v35)"); break;
1752123123Simp		case 2:	printf (" (rs530)"); break;
1753123123Simp		case 3:	printf (" (x21)"); break;
1754123123Simp		case 4:	printf (" (rs485)"); break;
1755123123Simp		case 9:	printf (" (no cable)"); break;
1756123123Simp		}
1757123123Simp	if (debug_valid && debug)
1758123123Simp		printf (" debug=%d", debug);
1759123123Simp	if (protocol_valid && *protocol)
1760123123Simp		printf (" %.8s", protocol);
1761123123Simp	else
1762123123Simp		printf (" idle");
1763123123Simp	if (cablen_valid)
1764123123Simp		printf (" cablen=%s", cablen ? "on" : "off");
1765123123Simp	if (keepalive_valid)
1766123123Simp		printf (" keepalive=%s", keepalive ? "on" : "off");
1767123123Simp
1768123123Simp	if (cfg_valid)
1769123123Simp		switch (cfg) {
1770123123Simp		case 'a' :	printf (" cfg=A");	break;
1771123123Simp		case 'b' :	printf (" cfg=B");	break;
1772123123Simp		case 'c' :	printf (" cfg=C");	break;
1773123123Simp		case 'd' :	printf (" cfg=D");	break;
1774123123Simp		default  :	printf (" cfg=unknown");
1775123123Simp		}
1776123123Simp	if (dir_valid)
1777123123Simp		printf (" dir=%d", dir);
1778123123Simp
1779123123Simp	if (baud_valid) {
1780123123Simp		if (baud)
1781123123Simp			printf (" %ld", baud);
1782123123Simp		else
1783123123Simp			printf (" extclock");
1784123123Simp	}
1785123123Simp	if (clk_valid)
1786123123Simp		switch (clk) {
1787123123Simp		case E1CLK_INTERNAL:	  printf (" syn=int");     break;
1788123123Simp		case E1CLK_RECEIVE:	  printf (" syn=rcv");     break;
1789123123Simp		case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0");    break;
1790123123Simp		case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1");    break;
1791123123Simp		case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2");    break;
1792123123Simp		case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3");    break;
1793123123Simp		default:                  printf (" syn=%d", clk); break;
1794123123Simp		}
1795123123Simp
1796123123Simp	if (dpll_valid)
1797123123Simp		printf (" dpll=%s", dpll ? "on" : "off");
1798123123Simp	if (nrzi_valid)
1799123123Simp		printf (" nrzi=%s", nrzi ? "on" : "off");
1800123123Simp	if (invclk_valid)
1801123123Simp		printf (" invclk=%s", invclk ? "on" : "off");
1802123123Simp	if (invrclk_valid)
1803123123Simp		printf (" invrclk=%s", invrclk ? "on" : "off");
1804123123Simp	if (invtclk_valid)
1805123123Simp		printf (" invtclk=%s", invtclk ? "on" : "off");
1806123123Simp	if (unfram_valid)
1807123123Simp		printf (" unfram=%s", unfram ? "on" : "off");
1808123123Simp	if (use16_valid)
1809123123Simp		printf (" use16=%s", use16 ? "on" : "off");
1810123123Simp	if (aflag) {
1811123123Simp		if (crc4_valid)
1812123123Simp			printf (" crc4=%s", crc4 ? "on" : "off");
1813123123Simp		if (higain_valid)
1814123123Simp			printf (" higain=%s", higain ? "on" : "off");
1815123123Simp		if (monitor_valid)
1816123123Simp			printf (" monitor=%s", monitor ? "on" : "off");
1817123123Simp		if (phony_valid)
1818123123Simp			printf (" phony=%s", phony ? "on" : "off");
1819123123Simp		if (scrambler_valid)
1820123123Simp			printf (" scrambler=%s", scrambler ? "on" : "off");
1821123123Simp		if (loop_valid)
1822123123Simp			printf (" loop=%s", loop ? "on" : "off");
1823123123Simp		if (rloop_valid)
1824123123Simp			printf (" rloop=%s", rloop ? "on" : "off");
1825123123Simp	}
1826123123Simp	if (timeslots_valid)
1827123123Simp		printf (" ts=%s", format_timeslots (timeslots));
1828123123Simp	if (subchan_valid)
1829123123Simp		printf (" pass=%s", format_timeslots (subchan));
1830123123Simp	if (level_valid)
1831123123Simp		printf (" (level=-%.1fdB)", level / 10.0);
1832123123Simp	printf ("\n");
1833123123Simp}
1834123123Simp
1835123123Simpstatic void
1836123123Simpsetup_chan (int fd, int argc, char **argv)
1837123123Simp{
1838123123Simp	int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram;
1839123123Simp	int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk;
1840123123Simp	int monitor, dir, scrambler, rloop, cablen;
1841123123Simp	long baud, timeslots;
1842123123Simp
1843123123Simp	for (i=0; i<argc; ++i) {
1844123123Simp		if (argv[i][0] >= '0' && argv[i][0] <= '9') {
1845123123Simp			baud = strtol (argv[i], 0, 10);
1846123123Simp			ioctl (fd, SERIAL_SETBAUD, &baud);
1847123123Simp		} else if (strcasecmp ("extclock", argv[i]) == 0) {
1848123123Simp			baud = 0;
1849123123Simp			ioctl (fd, SERIAL_SETBAUD, &baud);
1850123123Simp		} else if (strncasecmp ("cfg=", argv[i], 4) == 0) {
1851123123Simp			if (strncasecmp ("a", argv[i]+4, 1) == 0)
1852123123Simp				ioctl (fd, SERIAL_SETCFG, "a");
1853123123Simp			else if (strncasecmp ("b", argv[i]+4, 1) == 0)
1854123123Simp				ioctl (fd, SERIAL_SETCFG, "b");
1855123123Simp			else if (strncasecmp ("c", argv[i]+4, 1) == 0)
1856123123Simp				ioctl (fd, SERIAL_SETCFG, "c");
1857123123Simp			else if (strncasecmp ("d", argv[i]+4, 1) == 0)
1858123123Simp				ioctl (fd, SERIAL_SETCFG, "d");
1859123123Simp			else {
1860123123Simp				fprintf (stderr, "invalid cfg\n");
1861123123Simp				exit (-1);
1862123123Simp			}
1863123123Simp		} else if (strcasecmp ("idle", argv[i]) == 0)
1864123123Simp			ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0");
1865123123Simp		else if (strcasecmp ("async", argv[i]) == 0) {
1866123123Simp			mode = SERIAL_ASYNC;
1867123123Simp			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
1868123123Simp				ioctl (fd, SERIAL_SETPROTO, "async\0\0");
1869123123Simp		} else if (strcasecmp ("sync", argv[i]) == 0) {
1870123123Simp			mode = SERIAL_HDLC;
1871123123Simp			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
1872123123Simp				ioctl (fd, SERIAL_SETPROTO, "sync\0\0");
1873123123Simp		} else if (strcasecmp ("cisco", argv[i]) == 0) {
1874123123Simp			mode = SERIAL_HDLC;
1875123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
1876123123Simp			ioctl (fd, SERIAL_SETPROTO, "cisco\0\0");
1877123123Simp		} else if (strcasecmp ("rbrg", argv[i]) == 0) {
1878123123Simp			mode = SERIAL_HDLC;
1879123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
1880123123Simp			ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0");
1881123123Simp		} else if (strcasecmp ("raw", argv[i]) == 0) {
1882123123Simp			mode = SERIAL_HDLC;
1883123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
1884123123Simp			ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0");
1885123123Simp		} else if (strcasecmp ("packet", argv[i]) == 0) {
1886123123Simp			mode = SERIAL_HDLC;
1887123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
1888123123Simp			ioctl (fd, SERIAL_SETPROTO, "packet\0\0\0\0");
1889123123Simp		} else if (strcasecmp ("ppp", argv[i]) == 0) {
1890123123Simp			/* check that ppp line discipline is present */
1891123123Simp			if (ppp_ok ()) {
1892123123Simp				mode = SERIAL_HDLC;
1893123123Simp				ioctl (fd, SERIAL_SETMODE, &mode);
1894123123Simp				ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0");
1895123123Simp			}
1896123123Simp		} else if (strncasecmp ("keepalive=", argv[i], 10) == 0) {
1897123123Simp			keepalive = (strcasecmp ("on", argv[i] + 10) == 0);
1898123123Simp			ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive);
1899123123Simp		} else if (strcasecmp ("fr", argv[i]) == 0) {
1900123123Simp			mode = SERIAL_HDLC;
1901123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
1902123123Simp			ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0");
1903123123Simp		} else if (strncasecmp ("debug=", argv[i], 6) == 0) {
1904123123Simp			debug = strtol (argv[i]+6, 0, 10);
1905123123Simp			ioctl (fd, SERIAL_SETDEBUG, &debug);
1906123123Simp		} else if (strncasecmp ("loop=", argv[i], 5) == 0) {
1907123123Simp			loop = (strcasecmp ("on", argv[i] + 5) == 0);
1908123123Simp			ioctl (fd, SERIAL_SETLOOP, &loop);
1909123123Simp		} else if (strncasecmp ("rloop=", argv[i], 6) == 0) {
1910123123Simp			rloop = (strcasecmp ("on", argv[i] + 6) == 0);
1911123123Simp			ioctl (fd, SERIAL_SETRLOOP, &rloop);
1912123123Simp		} else if (strncasecmp ("dpll=", argv[i], 5) == 0) {
1913123123Simp			dpll = (strcasecmp ("on", argv[i] + 5) == 0);
1914123123Simp			ioctl (fd, SERIAL_SETDPLL, &dpll);
1915123123Simp		} else if (strncasecmp ("nrzi=", argv[i], 5) == 0) {
1916123123Simp			nrzi = (strcasecmp ("on", argv[i] + 5) == 0);
1917123123Simp			ioctl (fd, SERIAL_SETNRZI, &nrzi);
1918123123Simp		} else if (strncasecmp ("invclk=", argv[i], 7) == 0) {
1919123123Simp			invclk = (strcasecmp ("on", argv[i] + 7) == 0);
1920123123Simp			ioctl (fd, SERIAL_SETINVCLK, &invclk);
1921123123Simp		} else if (strncasecmp ("invrclk=", argv[i], 8) == 0) {
1922123123Simp			invrclk = (strcasecmp ("on", argv[i] + 8) == 0);
1923123123Simp			ioctl (fd, SERIAL_SETINVRCLK, &invrclk);
1924123123Simp		} else if (strncasecmp ("invtclk=", argv[i], 8) == 0) {
1925123123Simp			invtclk = (strcasecmp ("on", argv[i] + 8) == 0);
1926123123Simp			ioctl (fd, SERIAL_SETINVTCLK, &invtclk);
1927123123Simp		} else if (strncasecmp ("higain=", argv[i], 7) == 0) {
1928123123Simp			higain = (strcasecmp ("on", argv[i] + 7) == 0);
1929123123Simp			ioctl (fd, SERIAL_SETHIGAIN, &higain);
1930123123Simp		} else if (strncasecmp ("phony=", argv[i], 6) == 0) {
1931123123Simp			phony = (strcasecmp ("on", argv[i] + 6) == 0);
1932123123Simp			ioctl (fd, SERIAL_SETPHONY, &phony);
1933123123Simp		} else if (strncasecmp ("unfram=", argv[i], 7) == 0) {
1934123123Simp			unfram = (strcasecmp ("on", argv[i] + 7) == 0);
1935123123Simp			ioctl (fd, SERIAL_SETUNFRAM, &unfram);
1936123123Simp		} else if (strncasecmp ("scrambler=", argv[i], 10) == 0) {
1937123123Simp			scrambler = (strcasecmp ("on", argv[i] + 10) == 0);
1938123123Simp			ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler);
1939123123Simp		} else if (strncasecmp ("monitor=", argv[i], 8) == 0) {
1940123123Simp			monitor = (strcasecmp ("on", argv[i] + 8) == 0);
1941123123Simp			ioctl (fd, SERIAL_SETMONITOR, &monitor);
1942123123Simp		} else if (strncasecmp ("use16=", argv[i], 6) == 0) {
1943123123Simp			use16 = (strcasecmp ("on", argv[i] + 6) == 0);
1944123123Simp			ioctl (fd, SERIAL_SETUSE16, &use16);
1945123123Simp		} else if (strncasecmp ("crc4=", argv[i], 5) == 0) {
1946123123Simp			crc4 = (strcasecmp ("on", argv[i] + 5) == 0);
1947123123Simp			ioctl (fd, SERIAL_SETCRC4, &crc4);
1948123123Simp		} else if (strcasecmp ("syn=int", argv[i]) == 0) {
1949123123Simp			clk = E1CLK_INTERNAL;
1950123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
1951123123Simp		} else if (strcasecmp ("syn=rcv", argv[i]) == 0) {
1952123123Simp			clk = E1CLK_RECEIVE;
1953123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
1954123123Simp		} else if (strcasecmp ("syn=rcv0", argv[i]) == 0) {
1955123123Simp			clk = E1CLK_RECEIVE_CHAN0;
1956123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
1957123123Simp		} else if (strcasecmp ("syn=rcv1", argv[i]) == 0) {
1958123123Simp			clk = E1CLK_RECEIVE_CHAN1;
1959123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
1960123123Simp		} else if (strcasecmp ("syn=rcv2", argv[i]) == 0) {
1961123123Simp			clk = E1CLK_RECEIVE_CHAN2;
1962123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
1963123123Simp		} else if (strcasecmp ("syn=rcv3", argv[i]) == 0) {
1964123123Simp			clk = E1CLK_RECEIVE_CHAN3;
1965123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
1966123123Simp		} else if (strncasecmp ("ts=", argv[i], 3) == 0) {
1967123123Simp			timeslots = scan_timeslots (argv[i] + 3);
1968123123Simp			ioctl (fd, SERIAL_SETTIMESLOTS, &timeslots);
1969123123Simp		} else if (strncasecmp ("pass=", argv[i], 5) == 0) {
1970123123Simp			timeslots = scan_timeslots (argv[i] + 5);
1971123123Simp			ioctl (fd, SERIAL_SETSUBCHAN, &timeslots);
1972123123Simp		} else if (strncasecmp ("dlci", argv[i], 4) == 0) {
1973123123Simp			dlci = strtol (argv[i]+4, 0, 10);
1974123123Simp			ioctl (fd, SERIAL_ADDDLCI, &dlci);
1975123123Simp		} else if (strncasecmp ("dir=", argv[i], 4) == 0) {
1976123123Simp			dir = strtol (argv[i]+4, 0, 10);
1977123123Simp			ioctl (fd, SERIAL_SETDIR, &dir);
1978123123Simp		} else if (strncasecmp ("port=", argv[i], 5) == 0) {
1979123123Simp			if (strncasecmp ("rs232", argv[i]+5, 5) == 0) {
1980123123Simp				port = 0;
1981123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
1982123123Simp			} else if (strncasecmp ("v35", argv[i]+5, 3) == 0) {
1983123123Simp				port = 1;
1984123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
1985123123Simp			} else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) {
1986123123Simp				port = 2;
1987123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
1988123123Simp			} else
1989123123Simp				fprintf (stderr, "invalid port type\n");
1990123123Simp				exit (-1);
1991123123Simp#if 1
1992123123Simp		} else if (strcasecmp ("reset", argv[i]) == 0) {
1993123123Simp			ioctl (fd, SERIAL_RESET, 0);
1994123123Simp		} else if (strcasecmp ("hwreset", argv[i]) == 0) {
1995123123Simp			ioctl (fd, SERIAL_HARDRESET, 0);
1996123123Simp#endif
1997123123Simp		} else if (strncasecmp ("cablen=", argv[i], 7) == 0) {
1998123123Simp			loop = (strcasecmp ("on", argv[i] + 7) == 0);
1999123123Simp			ioctl (fd, SERIAL_SETCABLEN, &cablen);
2000123123Simp		}
2001123123Simp	}
2002123123Simp}
2003123123Simp
2004123123Simpstatic void
2005123123Simpget_mask (void)
2006123123Simp{
2007123123Simp#ifdef __linux__
2008123123Simp	int fd;
2009123123Simp
2010123123Simp	fd = open ("/dev/serial/ctl0", 0);
2011123123Simp	if (fd < 0) {
2012123123Simp		perror ("/dev/serial/ctl0");
2013123123Simp		exit (-1);
2014123123Simp	}
2015123123Simp	if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
2016123123Simp		perror ("getting list of channels");
2017123123Simp		exit (-1);
2018123123Simp	}
2019123123Simp	close (fd);
2020123123Simp#else
2021123123Simp	int fd, fd1, fd2, i;
2022123123Simp	char buf [80];
2023123123Simp
2024123123Simp	for (i=0, fd=-1; i<12 && fd<0; i++) {
2025123123Simp		sprintf (buf, "/dev/cx%d", i*4);
2026123123Simp		fd = open (buf, 0);
2027123123Simp	}
2028123123Simp
2029123123Simp	for (i=0, fd1=-1; i<3 && fd1<0; i++) {
2030123123Simp		sprintf (buf, "/dev/ct%d", i*2);
2031123123Simp		fd1 = open (buf, 0);
2032123123Simp	}
2033123123Simp
2034123123Simp	for (i=0, fd2=-1; i<3 && fd2<0; i++) {
2035123123Simp		sprintf (buf, "/dev/cp%d", i*4);
2036123123Simp		fd2 = open (buf, 0);
2037123123Simp	}
2038123123Simp
2039123123Simp	if ((fd < 0) && (fd1 < 0) && (fd2 < 0)) {
2040123123Simp		fprintf (stderr, "No Cronyx adapters installed\n");
2041123123Simp		exit (-1);
2042123123Simp	}
2043123123Simp
2044123123Simp	if (fd >= 0) {
2045123123Simp		if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
2046123123Simp			perror ("getting list of channels");
2047123123Simp			exit (-1);
2048123123Simp		}
2049123123Simp		close (fd);
2050123123Simp	}
2051123123Simp
2052123123Simp	if (fd1 >= 0) {
2053123123Simp		if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) {
2054123123Simp			perror ("getting list of channels");
2055123123Simp			exit (-1);
2056123123Simp		}
2057123123Simp		close (fd1);
2058123123Simp	}
2059123123Simp
2060123123Simp	if (fd2 >= 0) {
2061123123Simp		if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) {
2062123123Simp			perror ("getting list of channels");
2063123123Simp			exit (-1);
2064123123Simp		}
2065123123Simp		close (fd2);
2066123123Simp	}
2067123123Simp#endif
2068123123Simp}
2069123123Simp
2070123123Simpstatic int
2071123123Simpopen_chan_ctl (int num)
2072123123Simp{
2073123123Simp	char device [80];
2074123123Simp	int fd;
2075123123Simp
2076123123Simp#ifdef __linux__
2077123123Simp	sprintf (device, "/dev/serial/ctl%d", num);
2078123123Simp#else
2079123123Simp	switch (adapter_type) {
2080123123Simp	case 0:
2081123123Simp		sprintf (device, "/dev/cx%d", num);
2082123123Simp		break;
2083123123Simp	case 1:
2084123123Simp		sprintf (device, "/dev/ct%d", num);
2085123123Simp		break;
2086123123Simp	case 2:
2087123123Simp		sprintf (device, "/dev/cp%d", num);
2088123123Simp		break;
2089123123Simp	}
2090123123Simp#endif
2091123123Simp	fd = open (device, 0);
2092123123Simp	if (fd < 0) {
2093123123Simp		if (errno == ENODEV)
2094123123Simp			fprintf (stderr, "chan%d: not configured\n", num);
2095123123Simp		else
2096123123Simp			perror (device);
2097123123Simp		exit (-1);
2098123123Simp	}
2099123123Simp#ifdef __linux__
2100123123Simp	if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0)
2101123123Simp		sprintf (chan_name, "chan%d", num);
2102123123Simp#else
2103123123Simp	switch (adapter_type) {
2104123123Simp	case 0: sprintf (chan_name, "cx%d", num); break;
2105123123Simp	case 1: sprintf (chan_name, "ct%d", num); break;
2106123123Simp	case 2: sprintf (chan_name, "cp%d", num); break;
2107123123Simp	}
2108123123Simp#endif
2109123123Simp	return fd;
2110123123Simp}
2111123123Simp
2112123123Simpint
2113123123Simpmain (int argc, char **argv)
2114123123Simp{
2115123123Simp	char *p;
2116123123Simp	int fd, need_header, chan_num;
2117123123Simp
2118123123Simp	if (argc > 1 && strcmp(argv[1], "help") == 0)
2119123123Simp		usage();
2120123123Simp
2121123123Simp	for (;;) {
2122123123Simp		switch (getopt (argc, argv, "mseftucviax")) {
2123123123Simp		case EOF:
2124123123Simp			break;
2125123123Simp		case 'a':
2126123123Simp			++aflag;
2127123123Simp			continue;
2128123123Simp		case 'm':
2129123123Simp			++mflag;
2130123123Simp			continue;
2131123123Simp		case 's':
2132123123Simp			++sflag;
2133123123Simp			continue;
2134123123Simp		case 'e':
2135123123Simp			++eflag;
2136123123Simp			continue;
2137123123Simp		case 'f':
2138123123Simp			++eflag;
2139123123Simp			++fflag;
2140123123Simp			continue;
2141123123Simp		case 't':
2142123123Simp			++tflag;
2143123123Simp			continue;
2144123123Simp		case 'u':
2145123123Simp			++tflag;
2146123123Simp			++uflag;
2147123123Simp			continue;
2148123123Simp		case 'c':
2149123123Simp			++cflag;
2150123123Simp			continue;
2151123123Simp		case 'v':
2152123123Simp			++vflag;
2153123123Simp			continue;
2154123123Simp		case 'i':
2155123123Simp			++iflag;
2156123123Simp			continue;
2157123123Simp		case 'x':
2158123123Simp			++xflag;
2159123123Simp			continue;
2160123123Simp		default:
2161123123Simp			usage();
2162123123Simp		}
2163123123Simp		break;
2164123123Simp	}
2165123123Simp	argc -= optind;
2166123123Simp	argv += optind;
2167123123Simp
2168123123Simp	if (argc <= 0) {
2169123123Simp		get_mask ();
2170123123Simp		need_header = 1;
2171123123Simp		adapter_type = 0;
2172123123Simp#ifndef __linux__
2173123123Simp		for (; adapter_type < 3; ++adapter_type)
2174123123Simp#endif
2175123123Simp		{
2176123123Simp		for (chan_num=0; chan_num<MAXCHAN; ++chan_num)
2177123123Simp			if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) {
2178123123Simp				fd = open_chan_ctl (chan_num);
2179123123Simp				if (vflag) {
2180123123Simp#ifdef __linux__
2181123123Simp				char buf[256];
2182123123Simp				if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) {
2183123123Simp					printf ("Version: %s\n", buf);
2184123123Simp					close (fd);
2185123123Simp					return (0);
2186123123Simp				}
2187123123Simp#endif
2188123123Simp				}
2189123123Simp				if (iflag) {
2190123123Simp					print_chan (fd);
2191123123Simp					print_ifconfig (fd);
2192123123Simp				} else if (sflag||xflag)
2193123123Simp					print_stats (fd, need_header);
2194123123Simp				else if (mflag)
2195123123Simp					print_modems (fd, need_header);
2196123123Simp				else if (eflag)
2197123123Simp					print_e1_stats (fd, need_header);
2198123123Simp				else if (tflag)
2199123123Simp					print_e3_stats (fd, need_header);
2200123123Simp				else if (cflag)
2201123123Simp					clear_stats (fd);
2202123123Simp				else
2203123123Simp					print_chan (fd);
2204123123Simp				close (fd);
2205123123Simp				need_header = 0;
2206123123Simp			}
2207123123Simp		}
2208123123Simp		return (0);
2209123123Simp	}
2210123123Simp
2211123123Simp	p = argv[0] + strlen (argv[0]);
2212123123Simp	while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9')
2213123123Simp		--p;
2214123123Simp	chan_num = strtol (p, 0, 10);
2215123123Simp#ifndef __linux__
2216123123Simp	if (strncasecmp ("cx", argv[0], 2)==0)
2217123123Simp		adapter_type = 0;
2218123123Simp	else if (strncasecmp ("ct", argv[0], 2)==0)
2219123123Simp		adapter_type = 1;
2220123123Simp	else if (strncasecmp ("cp", argv[0], 2)==0)
2221123123Simp		adapter_type = 2;
2222123123Simp	else {
2223123123Simp		fprintf (stderr, "Wrong channel name\n");
2224123123Simp		exit (-1);
2225123123Simp	}
2226123123Simp#endif
2227123123Simp	argc--;
2228123123Simp	argv++;
2229123123Simp
2230123123Simp	fd = open_chan_ctl (chan_num);
2231123123Simp	if (vflag) {
2232123123Simp#ifdef __linux__
2233123123Simp		char buf[256];
2234123123Simp		if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0)
2235123123Simp			printf ("Version: %s\n", buf);
2236123123Simp#endif
2237123123Simp	}
2238123123Simp	if (iflag) {
2239123123Simp		print_chan (fd);
2240123123Simp		print_ifconfig (fd);
2241123123Simp		close (fd);
2242123123Simp		return (0);
2243123123Simp	}
2244123123Simp	if (sflag||xflag) {
2245123123Simp		print_stats (fd, 1);
2246123123Simp		close (fd);
2247123123Simp		return (0);
2248123123Simp	}
2249123123Simp	if (mflag) {
2250123123Simp		print_modems (fd, 1);
2251123123Simp		close (fd);
2252123123Simp		return (0);
2253123123Simp	}
2254123123Simp	if (eflag) {
2255123123Simp		print_e1_stats (fd, 1);
2256123123Simp		close (fd);
2257123123Simp		return (0);
2258123123Simp	}
2259123123Simp	if (tflag) {
2260123123Simp		print_e3_stats (fd, 1);
2261123123Simp		close (fd);
2262123123Simp		return (0);
2263123123Simp	}
2264123123Simp	if (cflag) {
2265123123Simp		clear_stats (fd);
2266123123Simp		close (fd);
2267123123Simp		return (0);
2268123123Simp	}
2269123123Simp	if (argc > 0)
2270123123Simp		setup_chan (fd, argc, argv);
2271123123Simp	else
2272123123Simp		print_chan (fd);
2273123123Simp	close (fd);
2274123123Simp	return (0);
2275123123Simp}
2276