dahdi_tools 分析(一)dahdi_scan

dahdi_tools 分析(一)dahdi_scan

dahdi_scan 的使用

示例:

# dahdi_scan 
[1]
active=yes
alarms=OK
description= XX WCTDM Board 1
name=WCTDM/0
manufacturer=xx
devicetype=xx
location=PCI Bus 00 Slot 00
basechan=1
totchans=4
irq=0
type=analog
port=1,FXS
port=2,FXS
port=3,FXS
port=4,FXS

dahdi_scan 用于显示板卡的一些信息。无参数时扫描所有板卡信息,加参数时扫描指定板卡,如 dahdi_scan 4 5 6 ;只扫描 4 5 6 号板卡。

源码分析

int main(int argc, char *argv[])
{
	int ctl;
	int x, y, z;
	struct dahdi_params params;
	unsigned int basechan = 1;
	int direct_basechan;
	struct dahdi_spaninfo s;
	char buf[100];
	char alarms[50];
	
	// 打开 /dev/dahdi/ctl 
    if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
    	fprintf(stderr, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
    	exit(1);
    }
    
    for (x = 1; x < DAHDI_MAX_SPANS; x++) {
		memset(&s, 0, sizeof(s));
		s.spanno = x;
		if (ioctl(ctl, DAHDI_SPANSTAT, &s))   // 使用 ioctl DAHDI_SPANSTAT 获取板卡信息,struct dahdi_spaninfo
			continue;
        
        /* DAHDI-Linux 2.5.x exposes the base channel in sysfs. Let's
		 * try to look for it there in case there are holes in the span
		 * numbering. */
		direct_basechan = get_basechan(x);   // get_basechan 后面分析
		if (-1 != direct_basechan) {
			basechan = direct_basechan;
		}
        
         fprintf(stdout, "[%d]\n", x);
		fprintf(stdout, "active=yes\n");
		fprintf(stdout, "alarms=%s\n", alarms);
		fprintf(stdout, "description=%s\n", s.desc);
		fprintf(stdout, "name=%s\n", s.name);
		fprintf(stdout, "manufacturer=%s\n", s.manufacturer);
		fprintf(stdout, "devicetype=%s\n", s.devicetype);
		fprintf(stdout, "location=%s\n", s.location);
		fprintf(stdout, "basechan=%d\n", basechan);
		fprintf(stdout, "totchans=%d\n", s.totalchans);
		fprintf(stdout, "irq=%d\n", s.irq);    // 显示一些基本信息
        
         y = basechan;
		memset(&params, 0, sizeof(params));
		params.channo = y;
		if (ioctl(ctl, DAHDI_GET_PARAMS, &params)) {   // 看是否能获取其它信息
			basechan += s.totalchans;
			continue;
		}
        
        if (is_digital_span(&s)) {      // 判断是数字板卡还是模拟板卡
			/* this is a digital span */
			fprintf(stdout, "type=digital-%s\n", s.spantype);
			fprintf(stdout, "syncsrc=%d\n", s.syncsrc);
			fprintf(stdout, "lbo=%s\n", s.lboname);
			fprintf(stdout, "coding_opts=");
			buf[0] = '\0';
			if (s.linecompat & DAHDI_CONFIG_B8ZS) strcat(buf, "B8ZS,");
			if (s.linecompat & DAHDI_CONFIG_AMI) strcat(buf, "AMI,");
			if (s.linecompat & DAHDI_CONFIG_HDB3) strcat(buf, "HDB3,");
			buf[strlen(buf) - 1] = '\0';
			fprintf(stdout, "%s\n", buf);
			fprintf(stdout, "framing_opts=");
			buf[0] = '\0';
			if (s.linecompat & DAHDI_CONFIG_ESF) strcat(buf, "ESF,");
			if (s.linecompat & DAHDI_CONFIG_D4) strcat(buf, "D4,");
			if (s.linecompat & DAHDI_CONFIG_CCS) strcat(buf, "CCS,");
			if (s.linecompat & DAHDI_CONFIG_CRC4) strcat(buf, "CRC4,");
			buf[strlen(buf) - 1] = '\0';
			fprintf(stdout, "%s\n", buf);
			fprintf(stdout, "coding=");
			if (s.lineconfig & DAHDI_CONFIG_B8ZS) fprintf(stdout, "B8ZS");
			else if (s.lineconfig & DAHDI_CONFIG_AMI) fprintf(stdout, "AMI");
			else if (s.lineconfig & DAHDI_CONFIG_HDB3) fprintf(stdout, "HDB3");
			fprintf(stdout, "\n");
			fprintf(stdout, "framing=");
			if (s.lineconfig & DAHDI_CONFIG_ESF) fprintf(stdout, "ESF");
			else if (s.lineconfig & DAHDI_CONFIG_D4) fprintf(stdout, "D4");
			else if (s.lineconfig & DAHDI_CONFIG_CCS) fprintf(stdout, "CCS");
			else fprintf(stdout, "CAS");
			if (s.lineconfig & DAHDI_CONFIG_CRC4) fprintf(stdout, "/CRC4");
			fprintf(stdout, "\n");
		} else {
			/* this is an analog span */
			fprintf(stdout, "type=analog\n");
			for (y = basechan; y < (basechan + s.totalchans); y++) {
				memset(&params, 0, sizeof(params));
				params.channo = y;
				if (ioctl(ctl, DAHDI_GET_PARAMS, &params)) {         // 获取params参数
					fprintf(stdout, "port=%d,unknown\n", y);
					continue;
				};
				fprintf(stdout, "port=%d,", y);
				switch (params.sigcap & (__DAHDI_SIG_FXO | __DAHDI_SIG_FXS)) {  // 根据 params.sigcap 区分是FXS还是FXO
				case __DAHDI_SIG_FXO:
					fprintf(stdout, "FXS");
					break;
				case __DAHDI_SIG_FXS:
					fprintf(stdout, "FXO");
					break;
				default:
					fprintf(stdout, "none");
				}
				if (params.sigcap & DAHDI_SIG_BROKEN)
					fprintf(stdout, " FAILED");
				fprintf(stdout, "\n");
			}
		}
	  
		basechan += s.totalchans;
        
		
	}
}

代码里面核心的部分就是 ioctl DAHDI_SPANSTAT 获取板卡信息,即 struct dahdi_spaninfo ,然后打印出来。然后根据是数字板卡还是模拟板卡打印不同的信息。

有两个函数这里分析一下

  • get_basechan
  • is_digital_span

get_basechan

static int get_basechan(unsigned int spanno)
{
	int res;
	int basechan;
	char filename[256];
	FILE *fp;

	snprintf(filename, sizeof(filename),
		 "/sys/bus/dahdi_spans/devices/span-%u/basechan", spanno);
	fp = fopen(filename, "r");
	if (NULL == fp) {
		return -1;
	}
	res = fscanf(fp, "%d", &basechan);
	fclose(fp);
	if (EOF == res) {
		return -1;
	}
	return basechan;
}

通过读取 /sys/bus/dahdi_spans/devices/span-x/basechan , 来获取 basechan ,即该板卡 的第一个通道的号码。

当一个系统上存在多个板卡时。ls /sys/bus/dahdi_spans/devices 可以看的到

# ls /sys/bus/dahdi_spans/devices
span-1  span-2  span-3  span-4  span-5  span-6  span-7  span-8  span-9

进去可以看到:

span-1]# ls -1
alarms
basechan
channels
dahdi!chan!001!001
...
...
ddev
desc
driver
is_digital
is_sync_master
lbo
linecompat
lineconfig
local_spanno
name
power
spantype
subsystem
syncsrc
uevent

is_digital_span

static inline int is_digital_span(struct dahdi_spaninfo *s)
{
	return (s->linecompat > 0);
}

s->linecompat > 0 时表示数字板卡。

struct dahdi_spaninfo

数据结构定义如下:

struct dahdi_spaninfo {
	int	spanno;		/* span number */
	char	name[20];	/* Name */
	char	desc[40];	/* Description */
	int	alarms;		/* alarms status */
	int	txlevel;	/* what TX level is set to */
	int	rxlevel;	/* current RX level */

	int	bpvcount;	/* current BPV count */
	int	crc4count;	/* current CRC4 error count */
	int	ebitcount;	/* current E-bit error count */
	int	fascount;	/* current FAS error count */
	__u32	fecount;	/* Framing error counter */
	__u32	cvcount;	/* Coding violations counter */
	__u32	becount;	/* current bit error count */
	__u32	prbs;		/* current PRBS detected pattern */
	__u32	errsec;		/* errored seconds */

	int	irqmisses;	/* current IRQ misses */
	int	syncsrc;	/* span # of current sync source,
				   or 0 for free run */
	int	numchans;	/* number of configured channels on this span */
	int	totalchans;	/* total number of channels on the span */
	int	totalspans;	/* total number of spans in entire system */
	int	lbo;		/* line build out */
	int	lineconfig;	/* framing/coding */
	char 	lboname[40];	/* line build out in text form */
	char	location[40];	/* span's device location in system */
	char	manufacturer[40]; /* manufacturer of span's device */
	char	devicetype[40];	/* span's device type */
	int	irq;		/* span's device IRQ */
	int	linecompat;	/* span global signaling or 0 for
				   analog spans.*/
	char	spantype[6];	/* type of span in text form */
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值