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 *
7155064Srik * Copyright (C) 1999-2005 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 *
17155064Srik * Cronyx Id: sconfig.c,v 1.4.2.2 2005/11/09 13:01:35 rik Exp $
18123123Simp */
19162253Scharnier
20162253Scharnier#include <sys/cdefs.h>
21162253Scharnier__FBSDID("$FreeBSD: releng/10.2/sbin/sconfig/sconfig.c 180132 2008-06-30 21:18:27Z rik $");
22162253Scharnier
23123123Simp#include <stdio.h>
24123123Simp#include <stdlib.h>
25123123Simp#include <string.h>
26123123Simp#include <unistd.h>
27123123Simp#include <fcntl.h>
28123123Simp#include <errno.h>
29123123Simp#include <ctype.h>
30123123Simp#include <sys/ioctl.h>
31123123Simp#include <sys/types.h>
32123123Simp#include <sys/stat.h>
33123123Simp#include <sys/socket.h>
34123123Simp#include <net/if.h>
35123123Simp#include <machine/cserial.h>
36123123Simp
37123123Simp#define MAXCHAN 128
38123123Simp
39123123Simpint vflag, eflag, sflag, mflag, cflag, fflag, iflag, aflag, xflag;
40123123Simpint tflag, uflag;
41155064Srikchar mask[64];
42155064Srikint adapter_type;		/* 0-sigma, 1-tau, 2-taupci, 3-tau32 */
43123123Simpchar chan_name[16];
44123123Simp
45123123Simpstatic void
46123123Simpusage (void)
47123123Simp{
48123123Simp	printf(
49123123Simp"Serial Adapter Configuration Utility\n"
50155064Srik"Copyright (C) 1998-2005 Cronyx Engineering.\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"
106155064Srik#ifdef __linux__
107155064Srik"\tami={on,off}\t\t -- E1 AMI or HDB3 line code\n"
108155064Srik"\tmtu={size}\t\t -- set MTU in bytes\n"
109155064Srik#endif
110123123Simp"\tsyn={int,rcv,rcvX}\t -- G.703 transmit clock\n"
111123123Simp"\tts=...\t\t\t -- E1 timeslots\n"
112123123Simp"\tpass=...\t\t -- E1 subchannel timeslots\n"
113123123Simp"\tdir=<num>\t\t -- connect channel to link<num>\n"
114155064Srik/*"\trqken={size}\t\t -- set receive queue length in packets\n"*/
115123123Simp/*"\tcablen={on,off}\t\t -- T3/STS-1 high transmitter output for long cable\n"*/
116123123Simp"\tdebug={0,1,2}\t\t -- enable/disable debug messages\n"
117123123Simp	);
118123123Simp	exit (0);
119123123Simp}
120123123Simp
121123123Simpstatic unsigned long
122123123Simpscan_timeslots (char *s)
123123123Simp{
124123123Simp	char *e;
125123123Simp	long v;
126123123Simp	int i;
127123123Simp	unsigned long ts, lastv;
128123123Simp
129123123Simp	ts = lastv = 0;
130123123Simp	for (;;) {
131123123Simp		v = strtol (s, &e, 10);
132123123Simp		if (e == s)
133123123Simp			break;
134123123Simp		if (*e == '-') {
135123123Simp			lastv = v;
136123123Simp			s = e+1;
137123123Simp			continue;
138123123Simp		}
139123123Simp		if (*e == ',')
140123123Simp			++e;
141123123Simp
142123123Simp		if (lastv)
143123123Simp			for (i=lastv; i<v; ++i)
144123123Simp				ts |= 1L << i;
145123123Simp		ts |= 1L << v;
146123123Simp
147123123Simp		lastv = 0;
148123123Simp		s = e;
149123123Simp	}
150123123Simp	return ts;
151123123Simp}
152123123Simp
153123123Simpstatic int
154123123Simpppp_ok (void)
155123123Simp{
156123123Simp#ifdef __linux__
157123123Simp	int s, p;
158123123Simp	struct ifreq ifr;
159123123Simp	char pttyname[32];
160123123Simp	char *p1, *p2;
161123123Simp	int i, j;
162123123Simp	int ppp_disc = N_PPP;
163123123Simp
164123123Simp	/*
165123123Simp	 * Open a socket for doing the ioctl operations.
166123123Simp	 */
167123123Simp	s = socket (AF_INET, SOCK_DGRAM, 0);
168123123Simp	if (s < 0) {
169123123Simp		fprintf (stderr, "Error opening socket.\n");
170123123Simp		return 0;
171123123Simp	}
172123123Simp	strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
173123123Simp	if (ioctl (s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0) {
174123123Simp		/* Ok. */
175123123Simp		close (s);
176123123Simp		return 1;
177123123Simp	}
178123123Simp	close (s);
179123123Simp
180123123Simp	/* open pseudo-tty and try to set PPP discipline */
181123123Simp	sprintf (pttyname, "/dev/ptyXX");
182123123Simp	p1 = &pttyname[8];
183123123Simp	p2 = &pttyname[9];
184123123Simp	for (i=0; i<16; i++) {
185123123Simp		struct stat stb;
186123123Simp
187123123Simp		*p1 = "pqrstuvwxyzabcde"[i];
188123123Simp		*p2 = '0';
189123123Simp		if (stat (pttyname, &stb) < 0)
190123123Simp			continue;
191123123Simp		for (j=0; j<16; j++) {
192123123Simp			*p2 = "0123456789abcdef"[j];
193123123Simp			p = open (pttyname, 2);
194123123Simp			if (p > 0) {
195123123Simp				if (ioctl (p, TIOCSETD, &ppp_disc) < 0) {
196123123Simp					fprintf (stderr, "No PPP discipline in kernel.\n");
197123123Simp					close (p);
198123123Simp					return 0;
199123123Simp				}
200123123Simp				close (p);
201123123Simp				return 1;
202123123Simp			}
203123123Simp		}
204123123Simp	}
205123123Simp	fprintf (stderr, "Cannot get pseudo-tty.\n");
206123123Simp	return 0;
207123123Simp#else
208123123Simp	return 1;
209123123Simp#endif
210123123Simp}
211123123Simp
212123123Simpstatic char *
213123123Simpformat_timeslots (unsigned long s)
214123123Simp{
215123123Simp	static char buf [100];
216123123Simp	char *p = buf;
217123123Simp	int i;
218123123Simp
219123123Simp	for (i=1; i<32; ++i)
220123123Simp		if ((s >> i) & 1) {
221123123Simp			int prev = (i > 1)  & (s >> (i-1));
222123123Simp			int next = (i < 31) & (s >> (i+1));
223123123Simp
224123123Simp			if (prev) {
225123123Simp				if (next)
226123123Simp					continue;
227123123Simp				*p++ = '-';
228123123Simp			} else if (p > buf)
229123123Simp				*p++ = ',';
230123123Simp
231123123Simp			if (i >= 10)
232123123Simp				*p++ = '0' + i / 10;
233123123Simp			*p++ = '0' + i % 10;
234123123Simp		}
235123123Simp	*p = 0;
236123123Simp	return buf;
237123123Simp}
238123123Simp
239123123Simpstatic void
240123123Simpprint_modems (int fd, int need_header)
241123123Simp{
242123123Simp	int status;
243123123Simp
244123123Simp	if (ioctl (fd, TIOCMGET, &status) < 0) {
245123123Simp		perror ("getting modem status");
246123123Simp		return;
247123123Simp	}
248123123Simp	if (need_header)
249123123Simp		printf ("Channel\tLE\tDTR\tDSR\tRTS\tCTS\tCD\n");
250123123Simp	printf ("%s\t%s\t%s\t%s\t%s\t%s\t%s\n", chan_name,
251123123Simp		status & TIOCM_LE  ? "On" : "-",
252123123Simp		status & TIOCM_DTR ? "On" : "-",
253123123Simp		status & TIOCM_DSR ? "On" : "-",
254123123Simp		status & TIOCM_RTS ? "On" : "-",
255123123Simp		status & TIOCM_CTS ? "On" : "-",
256123123Simp		status & TIOCM_CD  ? "On" : "-");
257123123Simp}
258123123Simp
259123123Simpstatic void
260162253Scharnier#ifdef __linux__
261123123Simpprint_ifconfig (int fd)
262162253Scharnier#else
263162253Scharnierprint_ifconfig (int fd __unused)
264162253Scharnier#endif
265123123Simp{
266123123Simp	char buf [64];
267123123Simp#ifdef __linux__
268123123Simp	char protocol [8];
269123123Simp
270123123Simp	if (ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0 &&
271123123Simp	    strcmp (protocol, "fr") == 0)
272123123Simp		sprintf (buf, "ifconfig %sd16 2>/dev/null", chan_name);
273123123Simp	else
274123123Simp#endif
275123123Simp	sprintf (buf, "ifconfig %s 2>/dev/null", chan_name);
276123123Simp	system (buf);
277123123Simp}
278123123Simp
279180132Srikstatic void
280180132Srikset_debug_ifconfig (int on)
281180132Srik{
282180132Srik	char buf [64];
283180132Srik	sprintf (buf, "ifconfig %s %sdebug 2>/dev/null", chan_name,
284180132Srik		 on ? "" : "-");
285180132Srik	system (buf);
286180132Srik}
287180132Srik
288123123Simpstatic char *
289123123Simpformat_long (unsigned long val)
290123123Simp{
291123123Simp	static char s[32];
292123123Simp	int l;
293123123Simp	l = sprintf (s, "%lu", val);
294123123Simp	if (l>7 && !sflag) {
295123123Simp		s[3] = s[2];
296123123Simp		s[2] = s[1];
297123123Simp		s[1] = '.';
298123123Simp		s[4] = 'e';
299123123Simp		sprintf (s + 5, "%02d", l-1);
300123123Simp	}
301123123Simp	return s;
302123123Simp}
303123123Simp
304123123Simpstatic void
305123123Simpprint_stats (int fd, int need_header)
306123123Simp{
307123123Simp	struct serial_statistics st;
308123123Simp	unsigned long sarr [9];
309123123Simp	int i;
310123123Simp
311123123Simp	if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) {
312123123Simp		perror ("getting statistics");
313123123Simp		return;
314123123Simp	}
315123123Simp	if (need_header) {
316123123Simp		if (sflag) {
317123123Simp			printf ("        ------------Receive-----------      "
318123123Simp				"------------Transmit----------\n");
319123123Simp			printf ("Channel Interrupts  Packets     Errors      "
320123123Simp				"Interrupts  Packets     Errors\n");
321123123Simp		}
322123123Simp		else    {
323123123Simp			printf ("        --------Receive---------------  "
324123123Simp				"--------Transmit--------------  Modem\n");
325123123Simp			printf ("Channel Intrs   Bytes   Packets Errors  "
326123123Simp				"Intrs   Bytes   Packets Errors  Intrs\n");
327123123Simp		}
328123123Simp	}
329123123Simp
330123123Simp	sarr [0] = st.rintr;
331123123Simp	sarr [1] = st.ibytes;
332123123Simp	sarr [2] = st.ipkts;
333123123Simp	sarr [3] = st.ierrs;
334123123Simp	sarr [4] = st.tintr;
335123123Simp	sarr [5] = st.obytes;
336123123Simp	sarr [6] = st.opkts;
337123123Simp	sarr [7] = st.oerrs;
338123123Simp	sarr [8] = st.mintr;
339123123Simp	printf ("%s", chan_name);
340123123Simp	if (sflag) {
341123123Simp		printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0],
342123123Simp			sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]);
343123123Simp	} else {
344123123Simp		for (i = 0; i < 9; i++)
345123123Simp			printf ("\t%s", format_long (sarr [i]));
346123123Simp		printf ("\n");
347123123Simp	}
348123123Simp}
349123123Simp
350123123Simpstatic void
351123123Simpclear_stats (int fd)
352123123Simp{
353123123Simp	if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) {
354123123Simp		perror ("clearing statistics");
355123123Simp		exit (-1);
356123123Simp	}
357123123Simp}
358123123Simp
359123123Simpstatic char *
360123123Simpformat_e1_status (unsigned long status)
361123123Simp{
362123123Simp	static char buf [80];
363123123Simp
364155064Srik	if (status == 0)
365155064Srik		return "n/a";
366123123Simp	if (status & E1_NOALARM)
367123123Simp		return "Ok";
368123123Simp	buf[0] = 0;
369123123Simp	if (status & E1_LOS)     strcat (buf, ",LOS");
370123123Simp	if (status & E1_AIS)     strcat (buf, ",AIS");
371123123Simp	if (status & E1_LOF)     strcat (buf, ",LOF");
372123123Simp	if (status & E1_LOMF)    strcat (buf, ",LOMF");
373155064Srik	if (status & E1_CRC4E)   strcat (buf, ",CRC4E");
374123123Simp	if (status & E1_FARLOF)  strcat (buf, ",FARLOF");
375123123Simp	if (status & E1_AIS16)   strcat (buf, ",AIS16");
376123123Simp	if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
377123123Simp/*	if (status & E1_TSTREQ)  strcat (buf, ",TSTREQ");*/
378123123Simp/*	if (status & E1_TSTERR)  strcat (buf, ",TSTERR");*/
379123123Simp	if (buf[0] == ',')
380123123Simp		return buf+1;
381123123Simp	return "Unknown";
382123123Simp}
383123123Simp
384123123Simpstatic void
385123123Simpprint_frac (int leftalign, unsigned long numerator, unsigned long divider)
386123123Simp{
387123123Simp	int n;
388123123Simp
389123123Simp	if (numerator < 1 || divider < 1) {
390123123Simp		printf (leftalign ? "/-   " : "    -");
391123123Simp		return;
392123123Simp	}
393123123Simp	n = (int) (0.5 + 1000.0 * numerator / divider);
394123123Simp	if (n < 1000) {
395123123Simp		printf (leftalign ? "/.%-3d" : " .%03d", n);
396123123Simp		return;
397123123Simp	}
398123123Simp	putchar (leftalign ? '/' : ' ');
399123123Simp
400123123Simp	if      (n >= 1000000) n = (n+500) / 1000 * 1000;
401123123Simp	else if (n >= 100000)  n = (n+50)  / 100 * 100;
402123123Simp	else if (n >= 10000)   n = (n+5)   / 10 * 10;
403123123Simp
404123123Simp	switch (n) {
405123123Simp	case 1000:    printf (".999"); return;
406123123Simp	case 10000:   n = 9990;   break;
407123123Simp	case 100000:  n = 99900;  break;
408123123Simp	case 1000000: n = 999000; break;
409123123Simp	}
410123123Simp	if (n < 10000)        printf ("%d.%d", n/1000, n/10%100);
411123123Simp	else if (n < 100000)  printf ("%d.%d", n/1000, n/100%10);
412123123Simp	else if (n < 1000000) printf ("%d.", n/1000);
413123123Simp	else                  printf ("%d", n/1000);
414123123Simp}
415123123Simp
416123123Simpstatic void
417123123Simpprint_e1_stats (int fd, int need_header)
418123123Simp{
419123123Simp	struct e1_statistics st;
420123123Simp	int i, maxi;
421123123Simp
422123123Simp	if (need_header)
423123123Simp		printf ("Chan\t Unav/Degr  Bpv/Fsyn  CRC/RCRC  Err/Lerr  Sev/Bur   Oof/Slp  Status\n");
424123123Simp
425123123Simp	if (ioctl (fd, SERIAL_GETESTAT, &st) < 0)
426123123Simp		return;
427123123Simp	printf ("%s\t", chan_name);
428123123Simp
429123123Simp	/* Unavailable seconds, degraded minutes */
430123123Simp	print_frac (0, st.currnt.uas, st.cursec);
431123123Simp	print_frac (1, 60 * st.currnt.dm, st.cursec);
432123123Simp
433123123Simp	/* Bipolar violations, frame sync errors */
434123123Simp	print_frac (0, st.currnt.bpv, st.cursec);
435123123Simp	print_frac (1, st.currnt.fse, st.cursec);
436123123Simp
437123123Simp	/* CRC errors, remote CRC errors (E-bit) */
438123123Simp	print_frac (0, st.currnt.crce, st.cursec);
439123123Simp	print_frac (1, st.currnt.rcrce, st.cursec);
440123123Simp
441123123Simp	/* Errored seconds, line errored seconds */
442123123Simp	print_frac (0, st.currnt.es, st.cursec);
443123123Simp	print_frac (1, st.currnt.les, st.cursec);
444123123Simp
445123123Simp	/* Severely errored seconds, bursty errored seconds */
446123123Simp	print_frac (0, st.currnt.ses, st.cursec);
447123123Simp	print_frac (1, st.currnt.bes, st.cursec);
448123123Simp
449123123Simp	/* Out of frame seconds, controlled slip seconds */
450123123Simp	print_frac (0, st.currnt.oofs, st.cursec);
451123123Simp	print_frac (1, st.currnt.css, st.cursec);
452123123Simp
453123123Simp	printf (" %s\n", format_e1_status (st.status));
454123123Simp
455123123Simp	if (fflag) {
456123123Simp		/* Print total statistics. */
457123123Simp		printf ("\t");
458123123Simp		print_frac (0, st.total.uas, st.totsec);
459123123Simp		print_frac (1, 60 * st.total.dm, st.totsec);
460123123Simp
461123123Simp		print_frac (0, st.total.bpv, st.totsec);
462123123Simp		print_frac (1, st.total.fse, st.totsec);
463123123Simp
464123123Simp		print_frac (0, st.total.crce, st.totsec);
465123123Simp		print_frac (1, st.total.rcrce, st.totsec);
466123123Simp
467123123Simp		print_frac (0, st.total.es, st.totsec);
468123123Simp		print_frac (1, st.total.les, st.totsec);
469123123Simp
470123123Simp		print_frac (0, st.total.ses, st.totsec);
471123123Simp		print_frac (1, st.total.bes, st.totsec);
472123123Simp
473123123Simp		print_frac (0, st.total.oofs, st.totsec);
474123123Simp		print_frac (1, st.total.css, st.totsec);
475123123Simp
476123123Simp		printf (" -- Total\n");
477123123Simp
478123123Simp		/* Print 24-hour history. */
479123123Simp		maxi = (st.totsec - st.cursec) / 900;
480123123Simp		if (maxi > 48)
481123123Simp			maxi = 48;
482123123Simp		for (i=0; i<maxi; ++i) {
483123123Simp			printf ("       ");
484123123Simp			print_frac (0, st.interval[i].uas, 15*60);
485123123Simp			print_frac (1, 60 * st.interval[i].dm, 15*60);
486123123Simp
487123123Simp			print_frac (0, st.interval[i].bpv, 15*60);
488123123Simp			print_frac (1, st.interval[i].fse, 15*60);
489123123Simp
490123123Simp			print_frac (0, st.interval[i].crce, 15*60);
491123123Simp			print_frac (1, st.interval[i].rcrce, 15*60);
492123123Simp
493123123Simp			print_frac (0, st.interval[i].es, 15*60);
494123123Simp			print_frac (1, st.interval[i].les, 15*60);
495123123Simp
496123123Simp			print_frac (0, st.interval[i].ses, 15*60);
497123123Simp			print_frac (1, st.interval[i].bes, 15*60);
498123123Simp
499123123Simp			print_frac (0, st.interval[i].oofs, 15*60);
500123123Simp			print_frac (1, st.interval[i].css, 15*60);
501123123Simp
502123123Simp			if (i < 3)
503123123Simp				printf (" -- %dm\n", (i+1)*15);
504123123Simp			else
505123123Simp				printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15);
506123123Simp		}
507123123Simp	}
508123123Simp}
509123123Simp
510123123Simpstatic char *
511123123Simpformat_e3_status (unsigned long status)
512123123Simp{
513123123Simp	static char buf [80];
514123123Simp
515123123Simp	buf[0] = 0;
516123123Simp	if (status & E3_LOS)     strcat (buf, ",LOS");
517123123Simp	if (status & E3_TXE)     strcat (buf, ",XMIT");
518123123Simp	if (buf[0] == ',')
519123123Simp		return buf+1;
520123123Simp	return "Ok";
521123123Simp}
522123123Simp
523123123Simpstatic char *
524162253Scharnierformat_e3_cv (unsigned long cv, unsigned long baud, unsigned long atime)
525123123Simp{
526123123Simp	static char buf[80];
527123123Simp
528162253Scharnier	if (!cv || !baud || !atime)
529123123Simp		sprintf (buf, "         -         ");
530123123Simp	else
531162253Scharnier		sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/atime);
532123123Simp	return buf;
533123123Simp}
534123123Simp
535123123Simpstatic void
536123123Simpprint_e3_stats (int fd, int need_header)
537123123Simp{
538123123Simp	struct e3_statistics st;
539123123Simp	int i, maxi;
540123123Simp	long baud;
541123123Simp
542123123Simp	if (need_header)
543123123Simp		printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n");
544123123Simp
545123123Simp	if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 ||
546123123Simp	    ioctl (fd, SERIAL_GETBAUD, &baud) < 0)
547123123Simp		return;
548123123Simp
549123123Simp	if (!st.cursec)
550123123Simp		st.cursec = 1;
551123123Simp
552123123Simp	printf ("%s\t%s\t\t\t\t\t", chan_name,
553123123Simp		format_e3_cv (st.ccv, baud, st.cursec));
554123123Simp
555123123Simp	printf (" %s\n", format_e3_status (st.status));
556123123Simp
557123123Simp
558123123Simp	if (uflag) {
559123123Simp		/* Print total statistics. */
560123123Simp		printf ("\t%s\t\t\t\t\t",
561123123Simp			format_e3_cv (st.tcv, baud, st.totsec));
562123123Simp		printf (" -- Total\n");
563123123Simp
564123123Simp		/* Print 24-hour history. */
565123123Simp		maxi = (st.totsec - st.cursec) / 900;
566123123Simp		if (maxi > 48)
567123123Simp			maxi = 48;
568123123Simp		for (i=0; i<maxi; ++i) {
569123123Simp			printf ("\t%s\t\t\t\t\t",
570123123Simp				format_e3_cv (st.icv[i], baud, 15*60));
571123123Simp			if (i < 3)
572123123Simp				printf (" -- %2dm\n", (i+1)*15);
573123123Simp			else
574123123Simp				printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15);
575123123Simp		}
576123123Simp	}
577123123Simp}
578123123Simp
579123123Simpstatic void
580123123Simpprint_chan (int fd)
581123123Simp{
582123123Simp	char protocol [8];
583123123Simp	char cfg;
584123123Simp	int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4;
585123123Simp	int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor;
586155064Srik	int cable, dir, scrambler, ami, mtu;
587155064Srik	int cablen, rloop, rqlen;
588123123Simp	long baud, timeslots, subchan;
589123123Simp	int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid;
590123123Simp	int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid;
591123123Simp	int timeslots_valid, subchan_valid, higain_valid, level_valid;
592123123Simp	int keepalive_valid, debug_valid, cfg_valid, port_valid;
593123123Simp	int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid;
594155064Srik	int cable_valid, dir_valid, scrambler_valid, ami_valid, mtu_valid;
595155064Srik	int cablen_valid, rloop_valid, rqlen_valid;
596123123Simp
597123123Simp	protocol_valid  = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0;
598123123Simp	cfg_valid       = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0;
599123123Simp	baud_valid      = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0;
600123123Simp	loop_valid      = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0;
601123123Simp	dpll_valid      = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0;
602123123Simp	nrzi_valid      = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0;
603123123Simp	invclk_valid    = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0;
604123123Simp	invrclk_valid	= ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0;
605123123Simp	invtclk_valid	= ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0;
606123123Simp	clk_valid       = ioctl (fd, SERIAL_GETCLK, &clk) >= 0;
607123123Simp	timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, &timeslots) >= 0;
608123123Simp	subchan_valid   = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0;
609123123Simp	higain_valid    = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0;
610123123Simp	phony_valid     = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0;
611123123Simp	unfram_valid    = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0;
612123123Simp	monitor_valid   = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0;
613123123Simp	use16_valid     = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0;
614123123Simp	crc4_valid      = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0;
615155064Srik	ami_valid	= ioctl (fd, SERIAL_GETLCODE, &ami) >= 0;
616123123Simp	level_valid     = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0;
617123123Simp	keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0;
618123123Simp	debug_valid     = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0;
619123123Simp	port_valid	= ioctl (fd, SERIAL_GETPORT, &port) >= 0;
620123123Simp	cable_valid	= ioctl (fd, SERIAL_GETCABLE, &cable) >= 0;
621123123Simp	dir_valid	= ioctl (fd, SERIAL_GETDIR, &dir) >= 0;
622123123Simp	scrambler_valid	= ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0;
623123123Simp	cablen_valid	= ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0;
624123123Simp	rloop_valid	= ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0;
625155064Srik	mtu_valid	= ioctl (fd, SERIAL_GETMTU, &mtu) >= 0;
626155064Srik	rqlen_valid	= ioctl (fd, SERIAL_GETRQLEN, &rqlen) >= 0;
627123123Simp
628123123Simp	printf ("%s", chan_name);
629123123Simp	if (port_valid)
630123123Simp		switch (port) {
631123123Simp		case 0:	printf (" (rs232)"); break;
632123123Simp		case 1:	printf (" (v35)"); break;
633123123Simp		case 2:	printf (" (rs530)"); break;
634123123Simp		}
635123123Simp	else if (cable_valid)
636123123Simp		switch (cable) {
637123123Simp		case 0:	printf (" (rs232)"); break;
638123123Simp		case 1:	printf (" (v35)"); break;
639123123Simp		case 2:	printf (" (rs530)"); break;
640123123Simp		case 3:	printf (" (x21)"); break;
641123123Simp		case 4:	printf (" (rs485)"); break;
642123123Simp		case 9:	printf (" (no cable)"); break;
643123123Simp		}
644123123Simp	if (debug_valid && debug)
645123123Simp		printf (" debug=%d", debug);
646123123Simp	if (protocol_valid && *protocol)
647123123Simp		printf (" %.8s", protocol);
648123123Simp	else
649123123Simp		printf (" idle");
650123123Simp	if (cablen_valid)
651123123Simp		printf (" cablen=%s", cablen ? "on" : "off");
652123123Simp	if (keepalive_valid)
653123123Simp		printf (" keepalive=%s", keepalive ? "on" : "off");
654123123Simp
655123123Simp	if (cfg_valid)
656123123Simp		switch (cfg) {
657123123Simp		case 'a' :	printf (" cfg=A");	break;
658123123Simp		case 'b' :	printf (" cfg=B");	break;
659123123Simp		case 'c' :	printf (" cfg=C");	break;
660123123Simp		case 'd' :	printf (" cfg=D");	break;
661123123Simp		default  :	printf (" cfg=unknown");
662123123Simp		}
663123123Simp	if (dir_valid)
664123123Simp		printf (" dir=%d", dir);
665123123Simp
666123123Simp	if (baud_valid) {
667123123Simp		if (baud)
668123123Simp			printf (" %ld", baud);
669123123Simp		else
670123123Simp			printf (" extclock");
671123123Simp	}
672155064Srik	if (mtu_valid)
673155064Srik		printf (" mtu=%d", mtu);
674155064Srik
675155064Srik	if (aflag && rqlen_valid)
676155064Srik		printf (" rqlen=%d", rqlen);
677155064Srik
678123123Simp	if (clk_valid)
679123123Simp		switch (clk) {
680123123Simp		case E1CLK_INTERNAL:	  printf (" syn=int");     break;
681123123Simp		case E1CLK_RECEIVE:	  printf (" syn=rcv");     break;
682123123Simp		case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0");    break;
683123123Simp		case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1");    break;
684123123Simp		case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2");    break;
685123123Simp		case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3");    break;
686123123Simp		default:                  printf (" syn=%d", clk); break;
687123123Simp		}
688123123Simp
689123123Simp	if (dpll_valid)
690123123Simp		printf (" dpll=%s", dpll ? "on" : "off");
691123123Simp	if (nrzi_valid)
692123123Simp		printf (" nrzi=%s", nrzi ? "on" : "off");
693123123Simp	if (invclk_valid)
694123123Simp		printf (" invclk=%s", invclk ? "on" : "off");
695123123Simp	if (invrclk_valid)
696123123Simp		printf (" invrclk=%s", invrclk ? "on" : "off");
697123123Simp	if (invtclk_valid)
698123123Simp		printf (" invtclk=%s", invtclk ? "on" : "off");
699123123Simp	if (unfram_valid)
700123123Simp		printf (" unfram=%s", unfram ? "on" : "off");
701123123Simp	if (use16_valid)
702123123Simp		printf (" use16=%s", use16 ? "on" : "off");
703123123Simp	if (aflag) {
704123123Simp		if (crc4_valid)
705123123Simp			printf (" crc4=%s", crc4 ? "on" : "off");
706123123Simp		if (higain_valid)
707123123Simp			printf (" higain=%s", higain ? "on" : "off");
708123123Simp		if (monitor_valid)
709123123Simp			printf (" monitor=%s", monitor ? "on" : "off");
710123123Simp		if (phony_valid)
711123123Simp			printf (" phony=%s", phony ? "on" : "off");
712123123Simp		if (scrambler_valid)
713123123Simp			printf (" scrambler=%s", scrambler ? "on" : "off");
714123123Simp		if (loop_valid)
715123123Simp			printf (" loop=%s", loop ? "on" : "off");
716123123Simp		if (rloop_valid)
717123123Simp			printf (" rloop=%s", rloop ? "on" : "off");
718155064Srik		if (ami_valid)
719155064Srik			printf (" ami=%s", ami ? "on" : "off");
720123123Simp	}
721123123Simp	if (timeslots_valid)
722123123Simp		printf (" ts=%s", format_timeslots (timeslots));
723123123Simp	if (subchan_valid)
724123123Simp		printf (" pass=%s", format_timeslots (subchan));
725123123Simp	if (level_valid)
726123123Simp		printf (" (level=-%.1fdB)", level / 10.0);
727123123Simp	printf ("\n");
728123123Simp}
729123123Simp
730123123Simpstatic void
731123123Simpsetup_chan (int fd, int argc, char **argv)
732123123Simp{
733155064Srik	int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram, ami;
734123123Simp	int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk;
735123123Simp	int monitor, dir, scrambler, rloop, cablen;
736180132Srik	int mode_valid;
737155064Srik	long baud, timeslots, mtu, rqlen;
738123123Simp
739123123Simp	for (i=0; i<argc; ++i) {
740123123Simp		if (argv[i][0] >= '0' && argv[i][0] <= '9') {
741123123Simp			baud = strtol (argv[i], 0, 10);
742123123Simp			ioctl (fd, SERIAL_SETBAUD, &baud);
743123123Simp		} else if (strcasecmp ("extclock", argv[i]) == 0) {
744123123Simp			baud = 0;
745123123Simp			ioctl (fd, SERIAL_SETBAUD, &baud);
746123123Simp		} else if (strncasecmp ("cfg=", argv[i], 4) == 0) {
747123123Simp			if (strncasecmp ("a", argv[i]+4, 1) == 0)
748123123Simp				ioctl (fd, SERIAL_SETCFG, "a");
749123123Simp			else if (strncasecmp ("b", argv[i]+4, 1) == 0)
750123123Simp				ioctl (fd, SERIAL_SETCFG, "b");
751123123Simp			else if (strncasecmp ("c", argv[i]+4, 1) == 0)
752123123Simp				ioctl (fd, SERIAL_SETCFG, "c");
753123123Simp			else if (strncasecmp ("d", argv[i]+4, 1) == 0)
754123123Simp				ioctl (fd, SERIAL_SETCFG, "d");
755123123Simp			else {
756123123Simp				fprintf (stderr, "invalid cfg\n");
757123123Simp				exit (-1);
758123123Simp			}
759123123Simp		} else if (strcasecmp ("idle", argv[i]) == 0)
760123123Simp			ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0");
761123123Simp		else if (strcasecmp ("async", argv[i]) == 0) {
762123123Simp			mode = SERIAL_ASYNC;
763123123Simp			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
764123123Simp				ioctl (fd, SERIAL_SETPROTO, "async\0\0");
765123123Simp		} else if (strcasecmp ("sync", argv[i]) == 0) {
766123123Simp			mode = SERIAL_HDLC;
767123123Simp			if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
768155064Srik				ioctl (fd, SERIAL_SETPROTO, "sync\0\0\0");
769123123Simp		} else if (strcasecmp ("cisco", argv[i]) == 0) {
770123123Simp			mode = SERIAL_HDLC;
771123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
772123123Simp			ioctl (fd, SERIAL_SETPROTO, "cisco\0\0");
773123123Simp		} else if (strcasecmp ("rbrg", argv[i]) == 0) {
774123123Simp			mode = SERIAL_HDLC;
775123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
776123123Simp			ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0");
777123123Simp		} else if (strcasecmp ("raw", argv[i]) == 0) {
778123123Simp			mode = SERIAL_HDLC;
779123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
780123123Simp			ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0");
781123123Simp		} else if (strcasecmp ("packet", argv[i]) == 0) {
782123123Simp			mode = SERIAL_HDLC;
783123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
784155064Srik			ioctl (fd, SERIAL_SETPROTO, "packet\0");
785123123Simp		} else if (strcasecmp ("ppp", argv[i]) == 0) {
786123123Simp			/* check that ppp line discipline is present */
787123123Simp			if (ppp_ok ()) {
788123123Simp				mode = SERIAL_HDLC;
789123123Simp				ioctl (fd, SERIAL_SETMODE, &mode);
790123123Simp				ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0");
791123123Simp			}
792123123Simp		} else if (strncasecmp ("keepalive=", argv[i], 10) == 0) {
793123123Simp			keepalive = (strcasecmp ("on", argv[i] + 10) == 0);
794123123Simp			ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive);
795123123Simp		} else if (strcasecmp ("fr", argv[i]) == 0) {
796123123Simp			mode = SERIAL_HDLC;
797123123Simp			ioctl (fd, SERIAL_SETMODE, &mode);
798123123Simp			ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0");
799155064Srik		} else if (strcasecmp ("zaptel", argv[i]) == 0) {
800155064Srik			mode = SERIAL_HDLC;
801155064Srik			ioctl (fd, SERIAL_SETMODE, &mode);
802155064Srik			ioctl (fd, SERIAL_SETPROTO, "zaptel\0");
803123123Simp		} else if (strncasecmp ("debug=", argv[i], 6) == 0) {
804123123Simp			debug = strtol (argv[i]+6, 0, 10);
805180132Srik			mode_valid = ioctl (fd, SERIAL_GETMODE, &mode) >= 0;
806180132Srik			if (!mode_valid || mode != SERIAL_ASYNC) {
807180132Srik				if (debug == 0) {
808180132Srik					set_debug_ifconfig(0);
809180132Srik				} else {
810180132Srik					ioctl (fd, SERIAL_SETDEBUG, &debug);
811180132Srik					set_debug_ifconfig(1);
812180132Srik				}
813180132Srik			} else {
814180132Srik				ioctl (fd, SERIAL_SETDEBUG, &debug);
815180132Srik			}
816123123Simp		} else if (strncasecmp ("loop=", argv[i], 5) == 0) {
817123123Simp			loop = (strcasecmp ("on", argv[i] + 5) == 0);
818123123Simp			ioctl (fd, SERIAL_SETLOOP, &loop);
819123123Simp		} else if (strncasecmp ("rloop=", argv[i], 6) == 0) {
820123123Simp			rloop = (strcasecmp ("on", argv[i] + 6) == 0);
821123123Simp			ioctl (fd, SERIAL_SETRLOOP, &rloop);
822123123Simp		} else if (strncasecmp ("dpll=", argv[i], 5) == 0) {
823123123Simp			dpll = (strcasecmp ("on", argv[i] + 5) == 0);
824123123Simp			ioctl (fd, SERIAL_SETDPLL, &dpll);
825123123Simp		} else if (strncasecmp ("nrzi=", argv[i], 5) == 0) {
826123123Simp			nrzi = (strcasecmp ("on", argv[i] + 5) == 0);
827123123Simp			ioctl (fd, SERIAL_SETNRZI, &nrzi);
828123123Simp		} else if (strncasecmp ("invclk=", argv[i], 7) == 0) {
829123123Simp			invclk = (strcasecmp ("on", argv[i] + 7) == 0);
830123123Simp			ioctl (fd, SERIAL_SETINVCLK, &invclk);
831123123Simp		} else if (strncasecmp ("invrclk=", argv[i], 8) == 0) {
832123123Simp			invrclk = (strcasecmp ("on", argv[i] + 8) == 0);
833123123Simp			ioctl (fd, SERIAL_SETINVRCLK, &invrclk);
834123123Simp		} else if (strncasecmp ("invtclk=", argv[i], 8) == 0) {
835123123Simp			invtclk = (strcasecmp ("on", argv[i] + 8) == 0);
836123123Simp			ioctl (fd, SERIAL_SETINVTCLK, &invtclk);
837123123Simp		} else if (strncasecmp ("higain=", argv[i], 7) == 0) {
838123123Simp			higain = (strcasecmp ("on", argv[i] + 7) == 0);
839123123Simp			ioctl (fd, SERIAL_SETHIGAIN, &higain);
840123123Simp		} else if (strncasecmp ("phony=", argv[i], 6) == 0) {
841123123Simp			phony = (strcasecmp ("on", argv[i] + 6) == 0);
842123123Simp			ioctl (fd, SERIAL_SETPHONY, &phony);
843123123Simp		} else if (strncasecmp ("unfram=", argv[i], 7) == 0) {
844123123Simp			unfram = (strcasecmp ("on", argv[i] + 7) == 0);
845123123Simp			ioctl (fd, SERIAL_SETUNFRAM, &unfram);
846123123Simp		} else if (strncasecmp ("scrambler=", argv[i], 10) == 0) {
847123123Simp			scrambler = (strcasecmp ("on", argv[i] + 10) == 0);
848123123Simp			ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler);
849123123Simp		} else if (strncasecmp ("monitor=", argv[i], 8) == 0) {
850123123Simp			monitor = (strcasecmp ("on", argv[i] + 8) == 0);
851123123Simp			ioctl (fd, SERIAL_SETMONITOR, &monitor);
852123123Simp		} else if (strncasecmp ("use16=", argv[i], 6) == 0) {
853123123Simp			use16 = (strcasecmp ("on", argv[i] + 6) == 0);
854123123Simp			ioctl (fd, SERIAL_SETUSE16, &use16);
855123123Simp		} else if (strncasecmp ("crc4=", argv[i], 5) == 0) {
856123123Simp			crc4 = (strcasecmp ("on", argv[i] + 5) == 0);
857123123Simp			ioctl (fd, SERIAL_SETCRC4, &crc4);
858155064Srik		} else if (strncasecmp ("ami=", argv[i], 4) == 0) {
859155064Srik			ami = (strcasecmp ("on", argv[i] + 4) == 0);
860155064Srik			ioctl (fd, SERIAL_SETLCODE, &ami);
861155064Srik		} else if (strncasecmp ("mtu=", argv[i], 4) == 0) {
862155064Srik			mtu = strtol (argv[i] + 4, 0, 10);
863155064Srik			ioctl (fd, SERIAL_SETMTU, &mtu);
864155064Srik		} else if (strncasecmp ("rqlen=", argv[i], 6) == 0) {
865155064Srik			rqlen = strtol (argv[i] + 6, 0, 10);
866155064Srik			ioctl (fd, SERIAL_SETRQLEN, &rqlen);
867123123Simp		} else if (strcasecmp ("syn=int", argv[i]) == 0) {
868123123Simp			clk = E1CLK_INTERNAL;
869123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
870123123Simp		} else if (strcasecmp ("syn=rcv", argv[i]) == 0) {
871123123Simp			clk = E1CLK_RECEIVE;
872123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
873123123Simp		} else if (strcasecmp ("syn=rcv0", argv[i]) == 0) {
874123123Simp			clk = E1CLK_RECEIVE_CHAN0;
875123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
876123123Simp		} else if (strcasecmp ("syn=rcv1", argv[i]) == 0) {
877123123Simp			clk = E1CLK_RECEIVE_CHAN1;
878123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
879123123Simp		} else if (strcasecmp ("syn=rcv2", argv[i]) == 0) {
880123123Simp			clk = E1CLK_RECEIVE_CHAN2;
881123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
882123123Simp		} else if (strcasecmp ("syn=rcv3", argv[i]) == 0) {
883123123Simp			clk = E1CLK_RECEIVE_CHAN3;
884123123Simp			ioctl (fd, SERIAL_SETCLK, &clk);
885123123Simp		} else if (strncasecmp ("ts=", argv[i], 3) == 0) {
886123123Simp			timeslots = scan_timeslots (argv[i] + 3);
887123123Simp			ioctl (fd, SERIAL_SETTIMESLOTS, &timeslots);
888123123Simp		} else if (strncasecmp ("pass=", argv[i], 5) == 0) {
889123123Simp			timeslots = scan_timeslots (argv[i] + 5);
890123123Simp			ioctl (fd, SERIAL_SETSUBCHAN, &timeslots);
891123123Simp		} else if (strncasecmp ("dlci", argv[i], 4) == 0) {
892123123Simp			dlci = strtol (argv[i]+4, 0, 10);
893123123Simp			ioctl (fd, SERIAL_ADDDLCI, &dlci);
894123123Simp		} else if (strncasecmp ("dir=", argv[i], 4) == 0) {
895123123Simp			dir = strtol (argv[i]+4, 0, 10);
896123123Simp			ioctl (fd, SERIAL_SETDIR, &dir);
897123123Simp		} else if (strncasecmp ("port=", argv[i], 5) == 0) {
898123123Simp			if (strncasecmp ("rs232", argv[i]+5, 5) == 0) {
899123123Simp				port = 0;
900123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
901123123Simp			} else if (strncasecmp ("v35", argv[i]+5, 3) == 0) {
902123123Simp				port = 1;
903123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
904123123Simp			} else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) {
905123123Simp				port = 2;
906123123Simp				ioctl (fd, SERIAL_SETPORT, &port);
907123123Simp			} else
908123123Simp				fprintf (stderr, "invalid port type\n");
909123123Simp				exit (-1);
910123123Simp#if 1
911123123Simp		} else if (strcasecmp ("reset", argv[i]) == 0) {
912123123Simp			ioctl (fd, SERIAL_RESET, 0);
913123123Simp		} else if (strcasecmp ("hwreset", argv[i]) == 0) {
914123123Simp			ioctl (fd, SERIAL_HARDRESET, 0);
915123123Simp#endif
916123123Simp		} else if (strncasecmp ("cablen=", argv[i], 7) == 0) {
917123123Simp			loop = (strcasecmp ("on", argv[i] + 7) == 0);
918123123Simp			ioctl (fd, SERIAL_SETCABLEN, &cablen);
919123123Simp		}
920123123Simp	}
921123123Simp}
922123123Simp
923123123Simpstatic void
924123123Simpget_mask (void)
925123123Simp{
926123123Simp#ifdef __linux__
927123123Simp	int fd;
928123123Simp
929123123Simp	fd = open ("/dev/serial/ctl0", 0);
930123123Simp	if (fd < 0) {
931123123Simp		perror ("/dev/serial/ctl0");
932123123Simp		exit (-1);
933123123Simp	}
934123123Simp	if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
935123123Simp		perror ("getting list of channels");
936123123Simp		exit (-1);
937123123Simp	}
938123123Simp	close (fd);
939123123Simp#else
940155064Srik	int fd, fd1, fd2, fd3, i;
941123123Simp	char buf [80];
942123123Simp
943123123Simp	for (i=0, fd=-1; i<12 && fd<0; i++) {
944123123Simp		sprintf (buf, "/dev/cx%d", i*4);
945123123Simp		fd = open (buf, 0);
946123123Simp	}
947123123Simp
948123123Simp	for (i=0, fd1=-1; i<3 && fd1<0; i++) {
949123123Simp		sprintf (buf, "/dev/ct%d", i*2);
950123123Simp		fd1 = open (buf, 0);
951123123Simp	}
952123123Simp
953123123Simp	for (i=0, fd2=-1; i<3 && fd2<0; i++) {
954123123Simp		sprintf (buf, "/dev/cp%d", i*4);
955123123Simp		fd2 = open (buf, 0);
956123123Simp	}
957123123Simp
958155064Srik	/* Try only one */
959155064Srik	for (i=0, fd3=-1; i<1 && fd3<0; i++) {
960155064Srik		sprintf (buf, "/dev/ce%d", i*4);
961155064Srik		fd3 = open (buf, 0);
962155064Srik	}
963155064Srik
964155064Srik	if ((fd < 0) && (fd1 < 0) && (fd2 < 0) && (fd3 < 0)) {
965123123Simp		fprintf (stderr, "No Cronyx adapters installed\n");
966123123Simp		exit (-1);
967123123Simp	}
968123123Simp
969123123Simp	if (fd >= 0) {
970123123Simp		if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
971123123Simp			perror ("getting list of channels");
972123123Simp			exit (-1);
973123123Simp		}
974123123Simp		close (fd);
975123123Simp	}
976123123Simp
977123123Simp	if (fd1 >= 0) {
978123123Simp		if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) {
979123123Simp			perror ("getting list of channels");
980123123Simp			exit (-1);
981123123Simp		}
982123123Simp		close (fd1);
983123123Simp	}
984123123Simp
985123123Simp	if (fd2 >= 0) {
986123123Simp		if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) {
987123123Simp			perror ("getting list of channels");
988123123Simp			exit (-1);
989123123Simp		}
990123123Simp		close (fd2);
991123123Simp	}
992155064Srik
993155064Srik	if (fd3 >= 0) {
994155064Srik		if (ioctl (fd3, SERIAL_GETREGISTERED, (mask+48)) < 0) {
995155064Srik			perror ("getting list of channels");
996155064Srik			exit (-1);
997155064Srik		}
998155064Srik		close (fd3);
999155064Srik	}
1000123123Simp#endif
1001123123Simp}
1002123123Simp
1003123123Simpstatic int
1004123123Simpopen_chan_ctl (int num)
1005123123Simp{
1006123123Simp	char device [80];
1007123123Simp	int fd;
1008123123Simp
1009123123Simp#ifdef __linux__
1010123123Simp	sprintf (device, "/dev/serial/ctl%d", num);
1011123123Simp#else
1012123123Simp	switch (adapter_type) {
1013123123Simp	case 0:
1014123123Simp		sprintf (device, "/dev/cx%d", num);
1015123123Simp		break;
1016123123Simp	case 1:
1017123123Simp		sprintf (device, "/dev/ct%d", num);
1018123123Simp		break;
1019123123Simp	case 2:
1020123123Simp		sprintf (device, "/dev/cp%d", num);
1021123123Simp		break;
1022155064Srik	case 3:
1023155064Srik		sprintf (device, "/dev/ce%d", num);
1024155064Srik		break;
1025123123Simp	}
1026123123Simp#endif
1027123123Simp	fd = open (device, 0);
1028123123Simp	if (fd < 0) {
1029123123Simp		if (errno == ENODEV)
1030123123Simp			fprintf (stderr, "chan%d: not configured\n", num);
1031123123Simp		else
1032123123Simp			perror (device);
1033123123Simp		exit (-1);
1034123123Simp	}
1035123123Simp#ifdef __linux__
1036123123Simp	if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0)
1037123123Simp		sprintf (chan_name, "chan%d", num);
1038123123Simp#else
1039123123Simp	switch (adapter_type) {
1040123123Simp	case 0: sprintf (chan_name, "cx%d", num); break;
1041123123Simp	case 1: sprintf (chan_name, "ct%d", num); break;
1042123123Simp	case 2: sprintf (chan_name, "cp%d", num); break;
1043155064Srik	case 3: sprintf (chan_name, "ce%d", num); break;
1044123123Simp	}
1045123123Simp#endif
1046123123Simp	return fd;
1047123123Simp}
1048123123Simp
1049123123Simpint
1050123123Simpmain (int argc, char **argv)
1051123123Simp{
1052123123Simp	char *p;
1053123123Simp	int fd, need_header, chan_num;
1054123123Simp
1055123123Simp	if (argc > 1 && strcmp(argv[1], "help") == 0)
1056123123Simp		usage();
1057123123Simp
1058123123Simp	for (;;) {
1059123123Simp		switch (getopt (argc, argv, "mseftucviax")) {
1060176407Sru		case -1:
1061123123Simp			break;
1062123123Simp		case 'a':
1063123123Simp			++aflag;
1064123123Simp			continue;
1065123123Simp		case 'm':
1066123123Simp			++mflag;
1067123123Simp			continue;
1068123123Simp		case 's':
1069123123Simp			++sflag;
1070123123Simp			continue;
1071123123Simp		case 'e':
1072123123Simp			++eflag;
1073123123Simp			continue;
1074123123Simp		case 'f':
1075123123Simp			++eflag;
1076123123Simp			++fflag;
1077123123Simp			continue;
1078123123Simp		case 't':
1079123123Simp			++tflag;
1080123123Simp			continue;
1081123123Simp		case 'u':
1082123123Simp			++tflag;
1083123123Simp			++uflag;
1084123123Simp			continue;
1085123123Simp		case 'c':
1086123123Simp			++cflag;
1087123123Simp			continue;
1088123123Simp		case 'v':
1089123123Simp			++vflag;
1090123123Simp			continue;
1091123123Simp		case 'i':
1092123123Simp			++iflag;
1093123123Simp			continue;
1094123123Simp		case 'x':
1095123123Simp			++xflag;
1096123123Simp			continue;
1097123123Simp		default:
1098123123Simp			usage();
1099123123Simp		}
1100123123Simp		break;
1101123123Simp	}
1102123123Simp	argc -= optind;
1103123123Simp	argv += optind;
1104123123Simp
1105123123Simp	if (argc <= 0) {
1106123123Simp		get_mask ();
1107123123Simp		need_header = 1;
1108123123Simp		adapter_type = 0;
1109123123Simp#ifndef __linux__
1110155064Srik		for (; adapter_type < 4; ++adapter_type)
1111123123Simp#endif
1112123123Simp		{
1113123123Simp		for (chan_num=0; chan_num<MAXCHAN; ++chan_num)
1114123123Simp			if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) {
1115123123Simp				fd = open_chan_ctl (chan_num);
1116123123Simp				if (vflag) {
1117123123Simp#ifdef __linux__
1118123123Simp				char buf[256];
1119123123Simp				if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) {
1120123123Simp					printf ("Version: %s\n", buf);
1121123123Simp					close (fd);
1122123123Simp					return (0);
1123123123Simp				}
1124123123Simp#endif
1125123123Simp				}
1126123123Simp				if (iflag) {
1127123123Simp					print_chan (fd);
1128123123Simp					print_ifconfig (fd);
1129123123Simp				} else if (sflag||xflag)
1130123123Simp					print_stats (fd, need_header);
1131123123Simp				else if (mflag)
1132123123Simp					print_modems (fd, need_header);
1133123123Simp				else if (eflag)
1134123123Simp					print_e1_stats (fd, need_header);
1135123123Simp				else if (tflag)
1136123123Simp					print_e3_stats (fd, need_header);
1137123123Simp				else if (cflag)
1138123123Simp					clear_stats (fd);
1139123123Simp				else
1140123123Simp					print_chan (fd);
1141123123Simp				close (fd);
1142123123Simp				need_header = 0;
1143123123Simp			}
1144123123Simp		}
1145123123Simp		return (0);
1146123123Simp	}
1147123123Simp
1148123123Simp	p = argv[0] + strlen (argv[0]);
1149123123Simp	while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9')
1150123123Simp		--p;
1151123123Simp	chan_num = strtol (p, 0, 10);
1152123123Simp#ifndef __linux__
1153123123Simp	if (strncasecmp ("cx", argv[0], 2)==0)
1154123123Simp		adapter_type = 0;
1155123123Simp	else if (strncasecmp ("ct", argv[0], 2)==0)
1156123123Simp		adapter_type = 1;
1157123123Simp	else if (strncasecmp ("cp", argv[0], 2)==0)
1158123123Simp		adapter_type = 2;
1159155064Srik	else if (strncasecmp ("ce", argv[0], 2)==0)
1160155064Srik		adapter_type = 3;
1161123123Simp	else {
1162123123Simp		fprintf (stderr, "Wrong channel name\n");
1163123123Simp		exit (-1);
1164123123Simp	}
1165123123Simp#endif
1166123123Simp	argc--;
1167123123Simp	argv++;
1168123123Simp
1169123123Simp	fd = open_chan_ctl (chan_num);
1170123123Simp	if (vflag) {
1171123123Simp#ifdef __linux__
1172123123Simp		char buf[256];
1173123123Simp		if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0)
1174123123Simp			printf ("Version: %s\n", buf);
1175123123Simp#endif
1176123123Simp	}
1177123123Simp	if (iflag) {
1178123123Simp		print_chan (fd);
1179123123Simp		print_ifconfig (fd);
1180123123Simp		close (fd);
1181123123Simp		return (0);
1182123123Simp	}
1183123123Simp	if (sflag||xflag) {
1184123123Simp		print_stats (fd, 1);
1185123123Simp		close (fd);
1186123123Simp		return (0);
1187123123Simp	}
1188123123Simp	if (mflag) {
1189123123Simp		print_modems (fd, 1);
1190123123Simp		close (fd);
1191123123Simp		return (0);
1192123123Simp	}
1193123123Simp	if (eflag) {
1194123123Simp		print_e1_stats (fd, 1);
1195123123Simp		close (fd);
1196123123Simp		return (0);
1197123123Simp	}
1198123123Simp	if (tflag) {
1199123123Simp		print_e3_stats (fd, 1);
1200123123Simp		close (fd);
1201123123Simp		return (0);
1202123123Simp	}
1203123123Simp	if (cflag) {
1204123123Simp		clear_stats (fd);
1205123123Simp		close (fd);
1206123123Simp		return (0);
1207123123Simp	}
1208123123Simp	if (argc > 0)
1209123123Simp		setup_chan (fd, argc, argv);
1210123123Simp	else
1211123123Simp		print_chan (fd);
1212123123Simp	close (fd);
1213123123Simp	return (0);
1214123123Simp}
1215