Update the configure script as well.
[dahdi/tools.git] / dahdi_scan.c
1 /*
2  * Scan and output information about DAHDI spans and ports.
3  * 
4  * Written by Brandon Kruse <bkruse@digium.com>
5  * and Kevin P. Fleming <kpfleming@digium.com>
6  * Copyright (C) 2007 Digium, Inc.
7  *
8  * Based on zttool written by Mark Spencer <markster@digium.com>
9  *
10  * All rights reserved.
11  *
12  */
13
14 /*
15  * See http://www.asterisk.org for more information about
16  * the Asterisk project. Please do not directly contact
17  * any of the maintainers of this project for assistance;
18  * the project provides a web site, mailing lists and IRC
19  * channels for your use.
20  *
21  * This program is free software, distributed under the terms of
22  * the GNU General Public License Version 2 as published by the
23  * Free Software Foundation. See the LICENSE file included with
24  * this program for more details.
25  */
26
27 #include <stdio.h> 
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <sys/ioctl.h>
33 #include <fcntl.h>
34 #include <errno.h>
35
36 #include <dahdi/user.h>
37
38 #include "dahdi_tools_version.h"
39
40 static inline int is_digital_span(struct dahdi_spaninfo *s)
41 {
42         return (s->linecompat > 0);
43 }
44
45 static int get_basechan(unsigned int spanno)
46 {
47         int res;
48         int basechan;
49         char filename[256];
50         FILE *fp;
51
52         snprintf(filename, sizeof(filename),
53                  "/sys/bus/dahdi_spans/devices/span-%u/basechan", spanno);
54         fp = fopen(filename, "r");
55         if (NULL == fp) {
56                 return -1;
57         }
58         res = fscanf(fp, "%d", &basechan);
59         fclose(fp);
60         if (EOF == res) {
61                 return -1;
62         }
63         return basechan;
64 }
65
66
67 int main(int argc, char *argv[])
68 {
69         int ctl;
70         int x, y, z;
71         struct dahdi_params params;
72         unsigned int basechan = 1;
73         int direct_basechan;
74         struct dahdi_spaninfo s;
75         char buf[100];
76         char alarms[50];
77         int filter_count = 0;
78         int span_filter[DAHDI_MAX_SPANS];
79
80         if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
81                 fprintf(stderr, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
82                 exit(1);
83         }
84
85         for (x = 1; x < argc && filter_count < DAHDI_MAX_SPANS; x++) {
86                 int s = atoi(argv[x]);
87                 if (s > 0) {
88                         span_filter[filter_count++] = s;
89                 }
90         }
91
92         for (x = 1; x < DAHDI_MAX_SPANS; x++) {
93
94                 memset(&s, 0, sizeof(s));
95                 s.spanno = x;
96                 if (ioctl(ctl, DAHDI_SPANSTAT, &s))
97                         continue;
98
99                 if (filter_count > 0) {
100                         int match = 0;
101                         for (z = 0; z < filter_count; z++) {
102                                 if (x == span_filter[z]) {
103                                         match = 1;
104                                         break;
105                                 }
106                         }
107                         if (!match) {
108                                 basechan += s.totalchans;
109                                 continue;
110                         }
111                 }
112
113                 /* DAHDI-Linux 2.5.x exposes the base channel in sysfs. Let's
114                  * try to look for it there in case there are holes in the span
115                  * numbering. */
116                 direct_basechan = get_basechan(x);
117                 if (-1 != direct_basechan) {
118                         basechan = direct_basechan;
119                 }
120
121                 alarms[0] = '\0';
122                 if (s.alarms) {
123                         if (s.alarms & DAHDI_ALARM_BLUE)
124                                 strcat(alarms,"BLU/");
125                         if (s.alarms & DAHDI_ALARM_YELLOW)
126                                 strcat(alarms, "YEL/");
127                         if (s.alarms & DAHDI_ALARM_RED) {
128                                 strcat(alarms, "RED/");
129
130 /* Extended alarm feature test. Allows compilation with
131  * versions of dahdi-linux prior to 2.4
132  */
133 #ifdef DAHDI_ALARM_LFA
134                                 if (s.alarms & DAHDI_ALARM_LFA)
135                                         strcat(alarms, "LFA/");
136 #endif /* ifdef DAHDI_ALARM_LFA */
137                         }
138                         if (s.alarms & DAHDI_ALARM_LOOPBACK)
139                                 strcat(alarms,"LB/");
140                         if (s.alarms & DAHDI_ALARM_RECOVER)
141                                 strcat(alarms,"REC/");
142                         if (s.alarms & DAHDI_ALARM_NOTOPEN)
143                                 strcat(alarms, "NOP/");
144                         if (!strlen(alarms))
145                                 strcat(alarms, "UUU/");
146                         if (strlen(alarms)) {
147                                 /* Strip trailing / */
148                                 alarms[strlen(alarms)-1]='\0';
149                         }
150                 } else {
151                         if (s.numchans) {
152 #ifdef DAHDI_ALARM_LFA
153                                 /* If we continuously receive framing errors
154                                  * but our span is still in service, and we
155                                  * are configured for E1 & crc4. We've lost
156                                  * crc4-multiframe alignment
157                                  */
158                                 if ((s.linecompat & DAHDI_CONFIG_CRC4) &&
159                                     (s.fecount > 0)) {
160                                         struct dahdi_spaninfo t;
161                                         memset(&t, 0, sizeof(t));
162                                         t.spanno = x;
163                                         sleep(1);
164                                         if (ioctl(ctl, DAHDI_SPANSTAT, &t))
165                                                 continue;
166
167                                         /* Test fecount at two separate time
168                                          * intervals, if they differ, throw LMFA
169                                          */
170                                         if ((t.fecount > s.fecount) &&
171                                                 !t.alarms) {
172                                                 strcat(alarms, "LMFA/");
173                                         }
174                                 }
175 #endif /* ifdef DAHDI_ALARM_LFA */
176                                 strcat(alarms, "OK");
177                         } else {
178                                 strcpy(alarms, "UNCONFIGURED");
179                         }
180                 }
181
182                 fprintf(stdout, "[%d]\n", x);
183                 fprintf(stdout, "active=yes\n");
184                 fprintf(stdout, "alarms=%s\n", alarms);
185                 fprintf(stdout, "description=%s\n", s.desc);
186                 fprintf(stdout, "name=%s\n", s.name);
187                 fprintf(stdout, "manufacturer=%s\n", s.manufacturer);
188                 fprintf(stdout, "devicetype=%s\n", s.devicetype);
189                 fprintf(stdout, "location=%s\n", s.location);
190                 fprintf(stdout, "basechan=%d\n", basechan);
191                 fprintf(stdout, "totchans=%d\n", s.totalchans);
192                 fprintf(stdout, "irq=%d\n", s.irq);
193                 y = basechan;
194                 memset(&params, 0, sizeof(params));
195                 params.channo = y;
196                 if (ioctl(ctl, DAHDI_GET_PARAMS, &params)) {
197                         basechan += s.totalchans;
198                         continue;
199                 }
200
201                 if (is_digital_span(&s)) {
202                         /* this is a digital span */
203                         fprintf(stdout, "type=digital-%s\n", s.spantype);
204                         fprintf(stdout, "syncsrc=%d\n", s.syncsrc);
205                         fprintf(stdout, "lbo=%s\n", s.lboname);
206                         fprintf(stdout, "coding_opts=");
207                         buf[0] = '\0';
208                         if (s.linecompat & DAHDI_CONFIG_B8ZS) strcat(buf, "B8ZS,");
209                         if (s.linecompat & DAHDI_CONFIG_AMI) strcat(buf, "AMI,");
210                         if (s.linecompat & DAHDI_CONFIG_HDB3) strcat(buf, "HDB3,");
211                         buf[strlen(buf) - 1] = '\0';
212                         fprintf(stdout, "%s\n", buf);
213                         fprintf(stdout, "framing_opts=");
214                         buf[0] = '\0';
215                         if (s.linecompat & DAHDI_CONFIG_ESF) strcat(buf, "ESF,");
216                         if (s.linecompat & DAHDI_CONFIG_D4) strcat(buf, "D4,");
217                         if (s.linecompat & DAHDI_CONFIG_CCS) strcat(buf, "CCS,");
218                         if (s.linecompat & DAHDI_CONFIG_CRC4) strcat(buf, "CRC4,");
219                         buf[strlen(buf) - 1] = '\0';
220                         fprintf(stdout, "%s\n", buf);
221                         fprintf(stdout, "coding=");
222                         if (s.lineconfig & DAHDI_CONFIG_B8ZS) fprintf(stdout, "B8ZS");
223                         else if (s.lineconfig & DAHDI_CONFIG_AMI) fprintf(stdout, "AMI");
224                         else if (s.lineconfig & DAHDI_CONFIG_HDB3) fprintf(stdout, "HDB3");
225                         fprintf(stdout, "\n");
226                         fprintf(stdout, "framing=");
227                         if (s.lineconfig & DAHDI_CONFIG_ESF) fprintf(stdout, "ESF");
228                         else if (s.lineconfig & DAHDI_CONFIG_D4) fprintf(stdout, "D4");
229                         else if (s.lineconfig & DAHDI_CONFIG_CCS) fprintf(stdout, "CCS");
230                         else fprintf(stdout, "CAS");
231                         if (s.lineconfig & DAHDI_CONFIG_CRC4) fprintf(stdout, "/CRC4");
232                         fprintf(stdout, "\n");
233                 } else {
234                         /* this is an analog span */
235                         fprintf(stdout, "type=analog\n");
236                         for (y = basechan; y < (basechan + s.totalchans); y++) {
237                                 memset(&params, 0, sizeof(params));
238                                 params.channo = y;
239                                 if (ioctl(ctl, DAHDI_GET_PARAMS, &params)) {
240                                         fprintf(stdout, "port=%d,unknown\n", y);
241                                         continue;
242                                 };
243                                 fprintf(stdout, "port=%d,", y);
244                                 switch (params.sigcap & (__DAHDI_SIG_FXO | __DAHDI_SIG_FXS)) {
245                                 case __DAHDI_SIG_FXO:
246                                         fprintf(stdout, "FXS");
247                                         break;
248                                 case __DAHDI_SIG_FXS:
249                                         fprintf(stdout, "FXO");
250                                         break;
251                                 default:
252                                         fprintf(stdout, "none");
253                                 }
254                                 if (params.sigcap & DAHDI_SIG_BROKEN)
255                                         fprintf(stdout, " FAILED");
256                                 fprintf(stdout, "\n");
257                         }
258                 }
259           
260                 basechan += s.totalchans;
261         }
262
263         exit(0);
264 }