传真发送的318配置和启动的流程

 

apps/main.c

main

int main(int argc, char **argv)
{	
	if(server_init()){
		log_err("failed to init server");
		goto main_done;
	}		
	if(cmd_init()){
		log_err("failed to init device");
		goto main_done;
	}		 
	server_run(); 	
main_done:
	server_exit();	
	return 0;		
}

apps/server.c

server_read

static int server_read(int fd, char *buf, int max, struct sockaddr_in *addr)
{
	int len = sizeof(*addr);
	
	return recvfrom(fd, buf, max, 0, (struct sockaddr*)addr, &len);
}

server_write

static int server_write(int fd, char *buf, int len, struct sockaddr_in *addr)
{
	sendto(fd, buf, len, 0, (struct sockaddr*)addr, sizeof(*addr));
}

server_bind

static int server_bind(int fd)
{
	struct sockaddr_in addr;
	int port = 800;
	
	log_info("port is %d", port);
	
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = INADDR_ANY;
	return bind(fd, (struct sockaddr*)&addr, sizeof(addr));

}

server_run

int server_run(void)
{
	struct pollfd entry;
	int ret;
	struct client *cli = &client;
	struct sockaddr_in addr;
	
	while(!server_stop){
		entry.fd = server_fd;
		entry.events = POLLIN;
		
		do{
			ret = poll(&entry, 1, 1000);
			if (ret < 0 && errno != EAGAIN && errno != EINTR){
				return -1;
			}
		} while (ret < 0);
		
		if(!(entry.revents &POLLIN)){
			goto server_update;
		}
		
		ret = server_read(entry.fd, cli->buf, sizeof(cli->buf), &addr);
		if(ret <= 0){
			goto server_update;
		}
		log_debug("recv data:%d", ret);
		cli->buf_len = ret;
		cli->buf_ptr = cli->buf;
		if(!cmd_parse(cli)){
			cli->cmd_exec(cli);
		}
		
		log_debug("send data:%d", cli->buf_len);
		server_write(entry.fd, cli->buf, cli->buf_len, &addr);
		if(cli->cmd_post){
			cli->cmd_post(cli);
		}
server_update:
		cmd_update();
	}
		
	return 0;
}

server_exit

void server_exit(void)
{
	server_stop = 1;
}

server_init

int server_init(void)
{
	int fd, flag;
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd < 0){
		return -1;
	}
	
	if(server_bind(fd)){
		close(fd);
		return -1;
	}
	
	flag = fcntl(fd, F_GETFL, 0);
	if(-1 == flag){
		flag = 0;
	}
	fcntl(fd, F_SETFL, flag | O_NONBLOCK);
	
	server_fd = fd;
	server_stop = 0;
	
	return 0;
}


apps/cmd.c

device_register


void device_register(int type, struct device *dev)
{
	device[type] = dev;
}

device_unregister


void device_unregister(int type)
{
	device[type] = NULL;
}

cmd_build_error


static void cmd_build_error(struct client *cli, int error)
{
	struct cmd_head *head = (struct cmd_head*)cli->buf;
	
	cli->buf_ptr = cli->buf;
	
	head->magic = htonl(CMD_MAGIC);
	head->version = htonl(CMD_VERSION);
	head->cmd = htonl(cli->cmd + 1);
	head->seq = htonl(cli->seq);
	head->len = htonl(sizeof(unsigned int));
	
	*(unsigned int*)(head + 1) = htonl(error);
	cli->buf_len = sizeof(*head) + sizeof(unsigned int);
	
	log_warn("build failed. error:%x", error);
}

cmd_build_success


static void cmd_build_success(struct client *cli, void* buf, int len)
{
	struct cmd_head *head = (struct cmd_head*)cli->buf;
	
	head->magic = htonl(CMD_MAGIC);
	head->version = htonl(CMD_VERSION);
	head->cmd = htonl(cli->cmd + 1);
	head->seq = htonl(cli->seq);
	head->len = htonl(sizeof(unsigned int));
	
	cli->buf_ptr = cli->buf + sizeof(*head);
	*(unsigned int*)cli->buf_ptr = 0;
	if(buf){
		memcpy(cli->buf_ptr + sizeof(unsigned int), buf, len);
	}
	head->len = sizeof(unsigned int) + len;
	cli->buf_len = sizeof(*head) + head->len;
	head->len = htonl(head->len);
	cli->buf_ptr = cli->buf;
	
	log_info("build success. len:%d", cli->buf_len);
}

cmd_build_upload


static struct cmd_head* cmd_build_upload(struct client *cli, int cmd)
{
	struct cmd_head *head = (struct cmd_head*)cli->buf;
	
	cli->buf_ptr = cli->buf;
	head->magic = htonl(CMD_MAGIC);
	head->version = htonl(CMD_VERSION);
	head->cmd = htonl(cli->cmd);
	head->seq = htonl(cli->upseq++);
	head->len = 0;
	
	return head;
}

channel_to_device


static struct device* channel_to_device(int *ch_no)
{
	int cnt, ch = *ch_no;
	
	for(cnt = DEV_TYPE_UNUSED + 1; cnt < DEV_TYPE_MAX; cnt ++){
		if(NULL == device[cnt]){
			continue;
		}
		if(ch >= device[cnt]->base && ch < device[cnt]->base + device[cnt]->size){
			*ch_no = ch - device[cnt]->base;
			return device[cnt];
		}
	}
	
	return NULL;
}

cmd_channel_init


static void cmd_channel_init(struct client *cli)
{
	struct param *pparam, param;
	int ch;
	struct device *dev;
	
	if(cli->buf_len != sizeof(param) + sizeof(ch)){
		cmd_build_error(cli, CMD_ERR_PARAM);
		log_err("channel param len is error.%d(%d)", cli->buf_len - 4, sizeof(param));
		return;
	}
	
	memcpy(&ch, cli->buf_ptr, sizeof(ch));
	ch = ntohl(ch);
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	cli->buf_ptr += sizeof(ch);
	pparam = (struct param*)cli->buf_ptr;
	memset(¶m, 0, sizeof(param));
	param.direction = ntohl(pparam->direction);
	param.codec = ntohl(pparam->codec);
	memcpy(param.daddr, pparam->daddr, sizeof(param.daddr));
	memcpy(param.saddr, pparam->saddr, sizeof(param.saddr));
	param.dport = ntohs(pparam->dport);
	param.sport = ntohs(pparam->sport);
	param.ssrc = ntohl(pparam->ssrc);
	param.ipver = ntohl(pparam->ipver);
	memcpy(param.gw_mac, pparam->gw_mac, 6);
	
	log_info("%s channel init ch:%d, dport:%d, daddr:%02x%02x%02x%02x sport:%d, ssrc:%x, codec:%d",
		 dev->name, ch, param.dport, param.daddr[0], param.daddr[1], param.daddr[2], param.daddr[3],
			param.sport, param.ssrc, param.codec);
	if(dev->ch_init(ch, ¶m)){
		cmd_build_error(cli, CMD_ERR_PARAM);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	}
}

cmd_channel_stat


static void cmd_channel_stat(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch, dir, stat;
	struct device *dev;
	
	ch = ntohl(*pint++);
	dir = ntohl(*pint++);
	stat = ntohl(*pint++);
	
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	log_info("%s channel stat ch:%d, stat:%d", dev->name, ch, stat);
	if(dev->ch_stat(ch, dir, stat)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_channel_shutdown


static void cmd_channel_shutdown(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch, dir;
	struct device *dev;
	
	ch = ntohl(*pint++);
	dir= ntohl(*pint++);
	
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	log_info("channel shutdown ch:%d, dir:%d", ch, dir);
	if(dev->ch_shutdown(ch, dir)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_channel_ptt

static void cmd_channel_ptt(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch;
	struct ptt_data data;
	struct device *dev;
	
	ch = ntohl(*pint++);
	data.type = ntohl(*pint++);
	data.ptt = ntohl(*pint++);
	
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	log_info("%s ptt ch:%d, type:%d, ptt:%d", dev->name, ch, data.type, data.ptt);
	if(dev->ch_ioctl(ch, CH_IOCTL_PTT, &data)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_channel_exit


static void cmd_channel_exit(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch;
	struct device *dev;
	
	ch = ntohl(*pint++);
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	log_info("%s channel exit ch:%d", dev->name, ch);
	if(dev->ch_exit(ch)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_device_cfg


static void cmd_device_cfg(struct client *cli)
{
	unsigned int *buf = (unsigned int*)cli->buf_ptr;
	int type, cnt;
	int* value;
	time_t t;
	int dcnt;
	struct device *dev;
	uint8_t addr[16];
	
	log_debug("dev cfg buf len:%d", cli->buf_len);
	for(cnt = 0; cnt < cli->buf_len; cnt += 8){
		type = ntohl(*buf++);
		value = buf++;
		
		log_debug("dev type %d", type);
		switch(type)
		{
		case DEV_CFG_TIME:
			t = ntohl(*value);
			stime(&t);
			break;
		default:
			break;
		}
	}
	
	cmd_build_success(cli, NULL, 0);
	
	return;

sys_cfg_failed:
	cmd_build_error(cli, CMD_ERR_DEVICE);
}

cmd_channel_t38cfg


static void cmd_channel_t38cfg(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch;
	struct device *dev;
	struct t38_param param;
	
	ch = ntohl(*pint++);
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	param.loss_conceal = ntohl(*pint++);
	param.speed = ntohl(*pint++);
	param.err_method = ntohl(*pint++);
	param.numFEC = ntohl(*pint++);
	param.numIFPs = ntohl(*pint++);
	param.data_redundancy = ntohl(*pint++);
	param.t30_redundancy = ntohl(*pint++);
	param.dir = ntohl(*pint++);
	
	log_debug("%s channel t38cfg ch:%d", dev->name, ch);
	if(dev->ch_t38cfg(ch, ¶m)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_channel_t38en


static void cmd_channel_t38en(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch, enable;
	struct device *dev;
	
	ch = ntohl(*pint++);
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	enable = *pint++;
	log_info("%s channel t38en ch:%d, enable", dev->name, ch, enable);
	if(dev->ch_t38en(ch, enable)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_device_reset


static void cmd_device_reset(struct client *cli)
{
	int cnt;
	
	for(cnt = DEV_TYPE_UNUSED + 1; cnt < DEV_TYPE_MAX; cnt ++){
		if(NULL == device[cnt]){
			continue;
		}
		device[cnt]->dev_reset(NULL);
	}
	
	cmd_build_success(cli, NULL, 0);
}

cmd_channel_link


static void cmd_channel_link(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch, link;
	struct device *dev;
	
	ch = ntohl(*pint++);
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("channel beyond.%d", ch);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	link = dev->ch_link(ch);
	log_info("channel link ch:%d, link:%#x", ch, link);
	link = htonl(link);
	cmd_build_success(cli, &link, sizeof(link));
}

cmd_channel_loopback


static void cmd_channel_loopback(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int ch1, ch2, enable;
	struct device *dev, *dev1;
	
	ch1 = ntohl(*pint++);
	ch2 = ntohl(*pint++);
	enable = ntohl(*pint++);
	dev = channel_to_device(&ch1);
	dev1 = channel_to_device(&ch2);
	if(NULL == dev || dev != dev1){
		log_warn("channel beyond.%d, %d", ch1, ch2);
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	log_info("%s channel loopback ch1:%d, ch2:%d, enable", dev->name, ch1, ch2, enable);
	if(dev->ch_loopback(ch1, ch2, enable)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		cmd_build_success(cli, NULL, 0);
	} 
}

cmd_device_raw


static void cmd_device_raw(struct client *cli)
{
	unsigned int *pint = (unsigned int*)cli->buf_ptr;
	int addr, is_read, value = 0;
	int ch = 0;
	struct device *dev;
	
	addr = ntohl(*pint++);
	is_read = ntohl(*pint++);
	value = ntohl(*pint++);
	dev = channel_to_device(&ch);
	if(NULL == dev){
		log_warn("no dev");
		cmd_build_error(cli, CMD_ERR_CH);
		return;
	}
	
	log_debug("%s addr:%x, is_read:%d, value:%x", dev->name, addr, is_read, value);
	if(dev->dev_raw(addr, is_read, &value)){
		cmd_build_error(cli, CMD_ERR_DEVICE);
	}
	else{
		value = htonl(value);
		cmd_build_success(cli, &value, sizeof(value));
	} 
}

cmd_array


static struct cmd_func cmd_array[] =
{
	{.cmd = CMD_CHANNEL_INIT, .name="ch init", .func = cmd_channel_init,},
	{.cmd = CMD_CHANNEL_STAT, .name="ch stat", .func = cmd_channel_stat,},
	{.cmd = CMD_CHANNEL_EXIT, .name="ch exit", .func = cmd_channel_exit,},
	{.cmd = CMD_CHANNEL_PTT, .name="ch ptt", .func = cmd_channel_ptt,},
	{.cmd = CMD_CHANNEL_SHUTDOWN, .name="ch shutdown", .func = cmd_channel_shutdown,},
	{.cmd = CMD_DEVICE_CFG, .name="dev cfg", .func = cmd_device_cfg,},
	{.cmd = CMD_CHANNEL_T38CFG, .name="ch t38cfg", .func = cmd_channel_t38cfg,},
	{.cmd = CMD_CHANNEL_T38EN, .name="ch t38en", .func = cmd_channel_t38en,},
	{.cmd = CMD_DEVICE_RESET, .name="dev reset", .func = cmd_device_reset,},
	{.cmd = CMD_CHANNEL_LINK, .name="ch link", .func = cmd_channel_link,},
	{.cmd = CMD_CHANNEL_LOOPBACK, .name="ch loopback", .func = cmd_channel_loopback,},
	{.cmd = CMD_DEVICE_RAW, .name="dev raw", .func = cmd_device_raw,},
};

cmd_find_cmd


static int cmd_find_cmd(struct client *cli, unsigned int cmd, uint8_t **name)
{
	int max = sizeof(cmd_array)/sizeof(cmd_array[0]);
	int cnt;
	struct cmd_func *func = cmd_array;
	
	for(cnt = 0; cnt < max; cnt ++, func++){
		if(func->cmd == cmd){
			cli->cmd_exec = func->func;
			*name = func->name;
			return 0;
		}
	}
	
	return -1;
}

cmd_parse


int cmd_parse(struct client *cli)
{
	struct cmd_head *head = (struct cmd_head*)cli->buf;
	int error = 0;
	unsigned int version, magic;
	uint8_t *name;
	
	magic = ntohl(head->magic);
	version = ntohl(head->version);
	cli->cmd = ntohl(head->cmd);
	cli->seq = ntohl(head->seq);
	cli->buf_ptr = (unsigned char*)(head + 1);
	cli->buf_len -= sizeof(*head);
	
	if(CMD_MAGIC != magic){
		log_warn("magic:%x, %x", CMD_MAGIC, magic);
		error = CMD_ERR_MAGIC;
		goto failed;
	}
	if(CMD_VERSION != version){
		log_warn("version:%x, %x", CMD_VERSION, version);
		error = CMD_ERR_VERSION;
		goto failed;
	}
	
	if(cmd_find_cmd(cli, cli->cmd, &name)){
		error = CMD_ERR_CMD;
		goto failed;
	}
	cli->cmd_post = NULL;
	
	log_info("cmd:%s", name);
	
	return 0;
	
failed:
	log_warn("parse cmd error:%x", error);
	cmd_build_error(cli, error);
	return -1;	
} 

cmd_init


int cmd_init(void)
{
	int type, ret;
	
	for(type = DEV_TYPE_UNUSED + 1; type < DEV_TYPE_MAX; type ++){
		if(device[type] && device[type]->dev_init){
			log_info("device %d init", type);
			ret = device[type]->dev_init(NULL);
			log_info("device %d inited result %d", type, ret);
		}
	}
	
	return 0;
}

cmd_exit


void cmd_exit(void)
{
}

cmd_update


int cmd_update(void)
{
	int type;
	
	for(type = DEV_TYPE_UNUSED + 1; type < DEV_TYPE_MAX; type ++){
		if(device[type] && device[type]->dev_update){
			device[type]->dev_update();
		}
	}
	
	return 0;
}


apps/syscfg.c

syscfg_exit


void syscfg_exit(void)
{
	arp_ipchg_unregister();
	
	arp_exit();
}

syscfg_init


int syscfg_init(void)
{
	if(syscfg_init_cfg()){
		log_err("Failed to open netcfg");
	}
	
	syscfg_init_ethernet();
	syscfg_update_ethernet();
	
	a8_ip_chg = 0;
	a8_ip_chg_done = 0;
	arp_ipchg_register(syscfg_ipchg_notify);
	
	if(arp_init()){
		log_err("Failed to init arp");
		return -1;
	}
	syscfg_contact_peer();
	
	return 0;
}

syscfg_ipchg_proc


void syscfg_ipchg_proc(void)
{
	uint8_t buf[16], *p;
	int len;
	
	if(a8_ip_chg_done == a8_ip_chg){
		return;
	}
	
	arp_get_new_peer_addr(buf, &len);
	switch(len)
	{
	case 4:
		syscfg_set_ip(SYSCFG_IP_PEER, SYSCFG_IP_VER4, buf, len);
		p = strrchr(self_addr, '.');
		if(NULL == p){
			log_err("ipv4 addr has no dot seperator");
		}
		else{
			buf[3] = atoi(p + 1);
			syscfg_set_ip(SYSCFG_IP_SELF, SYSCFG_IP_VER4, buf, len);
		}
		syscfg_cfg_update();
		break;
	default:
		break;
	}
	
	a8_ip_chg_done = a8_ip_chg;
}

syscfg_ipchg_notify


static void syscfg_ipchg_notify(void)
{
	a8_ip_chg++;
}

syscfg_cfg_update


void syscfg_cfg_update(void)
{
	uint8_t *p;
	
	if(peer_change){
		peer_change = 0;
		memcpy(peer_addr, peer_addr_cache, sizeof(peer_addr));
		peer_addr[sizeof(peer_addr) - 1] = 0;
		p = strrchr(peer_addr,'\n');
		if(p){
			*p = 0;
		}
	}
	
	if(self_change){
		self_change = 0;
		memcpy(self_addr, self_addr_cache, sizeof(self_addr));
		self_addr[sizeof(self_addr) - 1] = 0;
		p = strrchr(self_addr,'\n');
		if(p){
			*p = 0;
		}
	}
	
	syscfg_init_ethernet();
	syscfg_update_ethernet();
	syscfg_contact_peer();
	syscfg_cfg_save();
}

syscfg_set_ip


int syscfg_set_ip(int type, int af, uint8_t* addr, int prefix)
{
	switch(type)
	{
	case SYSCFG_IP_PEER:
		switch(af)
		{
		case SYSCFG_IP_VER4:
			snprintf(peer_addr_cache, sizeof(peer_addr_cache),
				"%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
			break;
		case SYSCFG_IP_VER6:
			if(inet_ntop(AF_INET6, addr, peer_addr_cache, sizeof(peer_addr_cache))){
				return -1;
			}
			peer_prefix = prefix;
			break;
		default:
			return -1;
		}
		peer_change = 1;
		break;
	case SYSCFG_IP_SELF:
		switch(af)
		{
		case SYSCFG_IP_VER4:
			snprintf(self_addr_cache, sizeof(self_addr_cache),
				"%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
			break;
		case SYSCFG_IP_VER6:
			if(inet_ntop(AF_INET6, addr, self_addr_cache, sizeof(self_addr_cache))){
				return -1;
			}
			self_prefix = prefix;
			break;
		default:
			return -1;
		}
		self_change = 1;
		break;
	default:
		return -1;
	}
	
	return 0;
}

syscfg_update_ethernet


static int syscfg_update_ethernet(void)
{
	uint8_t addr[16];
	
	if(strchr(peer_addr, '.')){
		sscanf(peer_addr, "%hhu.%hhu.%hhu.%hhu", addr, addr + 1, addr + 2, addr + 3);
		arp_set_peer(addr, peer_prefix);
	}
	else{
		inet_pton(AF_INET6, peer_addr, addr);
		arp_set_peer(addr, peer_prefix);
	}
	
	return 0;
}

syscfg_contact_peer


static void syscfg_contact_peer(void)
{
	if(strchr(peer_addr, '.')){
		syscfg_contact_peer_ipv4();
	}
	else{
		syscfg_contact_peer_ipv6();
	}
}

syscfg_contact_peer_ipv6


static int syscfg_contact_peer_ipv6(void)
{
	int fd;
	struct sockaddr_in6 addr;
	uint8_t buf[10];
	
	fd = socket(AF_INET6, SOCK_DGRAM, 0);
	if(fd < 0){
		return -1;
	}
	
	memset(&addr, 0, sizeof(addr));
	addr.sin6_family = AF_INET6;
	addr.sin6_port = htons(1024);	//dummy port
	memcpy(&addr.sin6_addr, peer_addr, sizeof(addr.sin6_addr));
	
	sendto(fd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr));
	close(fd);
	
	return 0;
}

syscfg_contact_peer_ipv4


static int syscfg_contact_peer_ipv4(void)
{
	int fd;
	struct sockaddr_in addr;
	struct arpreq arpreq;
	uint8_t buf[10];
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd < 0){
		return -1;
	}
	
	memset(&arpreq, 0, sizeof(arpreq));
	arpreq.arp_flags = ATF_PERM;
	strcpy(arpreq.arp_dev, "eth0");
	ioctl(fd, SIOCDARP, &arpreq);
	
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = 1024;	//dummy port, in order to update arp cache
	inet_aton(peer_addr, &addr.sin_addr);
	
	sendto(fd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, sizeof(addr));
	close(fd);
	
	return 0;
}

syscfg_init_ethernet


static int syscfg_init_ethernet(void)
{
	uint8_t cmd[80];
	
	snprintf(cmd, sizeof(cmd), "ifconfig eth0 %s", self_addr);
	system(cmd);
	snprintf(cmd, sizeof(cmd), "route del default");
	system(cmd);
	if(strchr(peer_addr, ':')){
		snprintf(cmd, sizeof(cmd), "route add default gw %s/%d metric 1 dev eth0", peer_addr, peer_prefix);
	}
	else{
		snprintf(cmd, sizeof(cmd), "route add default gw %s metric 1 dev eth0", peer_addr);
	}
	system(cmd);
}

syscfg_cfg_save


static int syscfg_cfg_save(void)
{
	int fd;
	uint8_t buf[256];
	int len;
	
	fd = open(NET_CFG_TMP, O_WRONLY | O_CREAT | O_TRUNC, 755);
	if(fd < 0){
		log_err("Faield to create netcfg");
		return -1;
	}
	
	write(fd, shell_hdr, strlen(shell_hdr));
	len = snprintf(buf, sizeof(buf), "NET_ETH0=%s/%d\n", self_addr, self_prefix);
	write(fd, buf, len);
	len = snprintf(buf, sizeof(buf), "NET_GW=%s/%d\n", peer_addr, peer_prefix);
	write(fd, buf, len);
	len = snprintf(buf, sizeof(buf), "NET_PORT=%d\n", svr_port);
	write(fd, buf, len);
	close(fd);
	
	snprintf(buf, sizeof(buf), "mv %s %s", NET_CFG_TMP, NET_CFG_PATH);
	system(buf);
}

syscfg_init_cfg


static int syscfg_init_cfg(void)
{
	FILE *fp;
	uint8_t buf[80], *p;
	
	fp = fopen(NET_CFG_PATH, "r");
	if(NULL == fp){
		return -1;
	}
	
	buf[0] = 0;
	while(fgets(buf, sizeof(buf), fp)){
		if(!buf[0]){
			continue;
		}
		
		if(!(p = strchr(buf, '='))){
			continue;
		}
		
		if(!memcmp(buf, "NET_ETH0", strlen("NET_ETH0"))){
			snprintf(self_addr, sizeof(self_addr), "%s", p + 1);
			p = strrchr(self_addr, '\n');
			if(p){
				*p = 0;
			}
			p = strchr(peer_addr, '/');
			if(p){
				*p++ = 0;
				self_prefix = atoi(p);
			}
		}
		else if(!memcmp(buf, "NET_GW", strlen("NET_GW"))){
			snprintf(peer_addr, sizeof(peer_addr), "%s", p + 1);
			p = strrchr(peer_addr, '\n');
			if(p){
				*p = 0;
			}
			p = strchr(peer_addr, '/');
			if(p){
				*p++ = 0;
				peer_prefix = atoi(p);
			}
		}
		else if(!memcmp(buf, "NET_PORT", strlen("NET_PORT"))){
			svr_port =atoi(p + 1);
		}
	}
	fclose(fp);
	
	return 0;
}

syscfg_set_port


void syscfg_set_port(int port)
{
	svr_port = port;
}

syscfg_get_port

int syscfg_get_port(void)
{
	return svr_port;
}

#define SERVER_PORT			800

apps/arp.c

arp_exit


void arp_exit(void)
{
	neighbour_run = 0;
	if(neighbour_th){
		pthread_join(neighbour_th, NULL);
	}
	
	arp_mon_run = 0;
	if(arp_mon_th){
		pthread_join(arp_mon_th, NULL);
	}
}

arp_init


int arp_init(void)
{
	int fd;
	struct sockaddr_nl addr;
	
	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
	if(fd < 0){
		return -1;
	}
	
	memset(&addr, 0, sizeof(addr));
	addr.nl_family = AF_NETLINK;
	addr.nl_groups = 1 << (RTNLGRP_NEIGH - 1);
	addr.nl_pid = getpid();
	if(bind(fd, (struct sockaddr*)&addr, sizeof(addr))){
		close(fd);
		return -1;
	}
	
	neighbour_run = 1;
	if(pthread_create(&neighbour_th, NULL, neighbour_update_proc, (void*)fd)){
		log_err("Failed to create arp proc");
		close(fd);
		return -1;
	}
	
	arp_mon_run = 1;
	if(pthread_create(&arp_mon_th, NULL, arp_monitor_multicast, NULL)){
		log_err("Failed to create arp monitor");
	}
	
	return 0;
}

arp_set_peer


void arp_set_peer(uint8_t* peer, int prefix)
{
	peer_prefix = prefix;
	memcpy(peer_addr, peer, peer_prefix ? 16 : 4);
}

arp_wait


void arp_wait(void)
{
	uint32_t now = consumer;
	
	while(consumer == now);
}

arp_get_peer


void arp_get_peer(uint8_t *dmac)
{
	pthread_mutex_lock(&arp_lock);
	memcpy(dmac, peer_mac, 6);
	pthread_mutex_unlock(&arp_lock);
}

neighbour_update_proc


static void* neighbour_update_proc(void *arg)
{
	int fd = (int)arg;
	int len;
	uint8_t buf[256], dmac[6];
	struct pollfd entry;
	
	//only ipv4 have the ability to get exist neighbour by arp cmd
	//when ipv6, we can send icmp msg to invoke one neighbour update event to get the peer mac
	if(!peer_prefix && !arp_init_peer_by_arp(peer_addr, dmac)){
		arp_notify_all(dmac);
	}
	
	entry.events = POLLIN;
	entry.fd = fd;
	
	while(neighbour_run){
		if(poll(&entry, 1, 1000) <= 0){
			continue;
		}
			
		if(!(entry.revents & POLLIN)){
			continue;
		}
		
		len = recv(fd, buf, sizeof(buf), 0);
		if(arp_parse(buf, len, peer_addr, dmac)){
			continue;
		}
		arp_notify_all(dmac);
	}
	
	close(fd);
	
	return NULL;
}

arp_notify_all


static void arp_notify_all(uint8_t* dmac)
{
	int cnt;
	
	pthread_mutex_lock(&arp_lock);
	if(!memcmp(peer_mac, dmac, 6)){
		pthread_mutex_unlock(&arp_lock);
		return;
	}
	memcpy(peer_mac, dmac, 6);
	pthread_mutex_unlock(&arp_lock);
	consumer++;
	
	log_info("update peer mac %x %x %x %x %x %x", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
	for(cnt = 0; cnt < ARP_DEV_MAX; cnt ++){
		if(arp_procs[cnt]){
			arp_procs[cnt]();
		}
	}
}

arp_parse


static int arp_parse(uint8_t* buf, int len, uint8_t* peer, uint8_t* dmac)
{
	struct nlmsghdr *nlh;
	struct ndmsg *ndm;
	struct nlmsghdr *hdr;
	struct nlattr *nla;
	unsigned char* pdata;
	uint8_t dst[16];
	int tmp, dlen, stat;
	
	if(len < NLMSG_HDRLEN){
		log_err("arp len %d < hdr(%d)", len, NLMSG_HDRLEN);
		return -1;
	}
	
	hdr = (struct nlmsghdr*)buf;
	if(RTM_NEWNEIGH != hdr->nlmsg_type){
		log_err("arp type not neigh.%d", hdr->nlmsg_type);
		return -1;
	}
	
	len -= NLMSG_HDRLEN;
	if(len < (int)sizeof(*ndm)){
		log_err("arp len %d < ndm(%d)", len, sizeof(*ndm));
		return -1;
	}
	
	len -= sizeof(*ndm);
	nla = (struct nlattr *)((unsigned char*)hdr + NLMSG_HDRLEN + sizeof(*ndm));
	for(stat = 0; len > 0 && 3 != stat; len -= tmp){
		pdata = (unsigned char*)nla + sizeof(*nla);
		switch(nla->nla_type)
		{
		case NDA_DST:
			if(nla->nla_len <= sizeof(*nla)){
				log_err("sip len is error.%d, %d", nla->nla_len, sizeof(*nla));
				return -1;
			}
			dlen = nla->nla_len - sizeof(*nla);
			if(4 != dlen && 16 != dlen){
				return -1;
			}
			memcpy(dst, pdata, dlen);
			stat |= 1;
			break;
		case NDA_LLADDR:
			if(nla->nla_len != sizeof(*nla) + 6){
				log_err("sha len is error.%d, %d", nla->nla_len, sizeof(*nla));
				return -1;
			}
			memcpy(dmac, pdata, 6);
			stat |= 2;
			break;
		default:
			break;
		}
		tmp = (nla->nla_len + 3) & ~3;
		nla = (struct nlattr*)((unsigned char*)nla + tmp);
	}
	
	if(3 != stat){
		return -1;
	}
	
	if(memcmp(dst, peer, dlen)){
		log_err("ip addr error.%#x, %#x", dst, peer);
		return -1;
	}
	
	return 0;
}

arp_monitor_multicast


static void* arp_monitor_multicast(void* arg)
{
	int fd;
	struct ifreq ifr;
	struct sockaddr_ll addr;
	struct pollfd entry;
	struct arphdr *hdr;
	int len;
	uint8_t buf[256];
	uint8_t tip[4], *smac;
	unsigned int sip;
	
	fd = socket(AF_PACKET, SOCK_DGRAM, 0);
	if(fd < 0){
		log_err("Failed to open arp monitor");
		return NULL;
	}
	
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, "eth0", IFNAMSIZ - 1);
	if(ioctl(fd, SIOCGIFINDEX, &ifr)){
		log_err("Failed to get arp ifindex");
		close(fd);
		return NULL;
	}
	
	addr.sll_family = AF_PACKET;
	addr.sll_protocol = htons(ETH_P_ARP);
	addr.sll_ifindex = ifr.ifr_ifindex;
	if(bind(fd, (struct sockaddr*)&addr, sizeof(addr))){
		log_err("Failed to bind arp monitor");
		close(fd);
		return NULL;
	}
	
	entry.fd = fd;
	entry.events = POLLIN;
	while(arp_mon_run){
		if(poll(&entry, 1, 1000) <= 0){
			continue;
		}
		
		len = recv(fd, buf, sizeof(buf), 0);
		if(len <= (int)sizeof(*hdr) + 20){
			continue;
		}
		hdr = (struct arphdr*)buf;
		if(htons(ARPOP_REQUEST) != hdr->ar_op || htons(ETH_P_IP) != hdr->ar_pro){
			continue;
		}
		
		smac = buf + sizeof(*hdr);
		sip = (smac[6]) | (smac[7] << 8) | (smac[8] << 16) | (smac[9] << 24);
		memcpy(tip, smac + 6 + 4 + 6, 4);
		if(0xff != tip[3]){
			continue;
		}
		if(arp_sync_kernel(sip, smac)){
			continue;
		}
		
		log_info("success to update arp by multicast");
		arp_update_new_peer_addr(smac + 6, 4);
		if(ip_chg_cb){
			ip_chg_cb();
		}
	}
	
	close(fd);
	
	return NULL;
}

arp_get_new_peer_addr


void arp_get_new_peer_addr(uint8_t* buf, int* len)
{
	pthread_mutex_lock(&ip_lock);
	*len = recv_peer_addr_len;
	memcpy(buf, recv_peer_addr, *len);
	pthread_mutex_unlock(&ip_lock);
}

arp_update_new_peer_addr


static void arp_update_new_peer_addr(uint8_t* buf, int len)
{
	pthread_mutex_lock(&ip_lock);
	memcpy(recv_peer_addr, buf, len);
	recv_peer_addr_len = len;
	pthread_mutex_unlock(&ip_lock);
}

arp_sync_kernel


static int arp_sync_kernel(uint32_t peer, uint8_t* dmac)
{
	struct sockaddr_in *paddr;
	struct arpreq req;
	int fd;
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd < 0){
		log_err("Failed to open arp init fd");
		return -1;
	}
	
	memset(&req, 0, sizeof(req));
	strcpy(req.arp_dev, "eth0");
	paddr = (struct sockaddr_in*)&req.arp_pa;
	paddr->sin_family = AF_INET;
	paddr->sin_addr.s_addr = peer;
	
	memcpy(req.arp_ha.sa_data, dmac, 6);
	req.arp_flags = ATF_COM;
	
	ioctl(fd, SIOCSARP, &req);
	close(fd);
	
	return 0;
}

arp_init_peer_by_arp


static int arp_init_peer_by_arp(uint8_t* peer, uint8_t* dmac)
{
	struct sockaddr_in *paddr;
	struct arpreq req;
	int fd;
	uint32_t addr = (peer[3] << 24) | (peer[2] << 16) | (peer[1] << 8) | peer[0];
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd < 0){
		log_err("Failed to open arp init fd");
		return -1;
	}
	
	memset(&req, 0, sizeof(req));
	strcpy(req.arp_dev, "eth0");
	paddr = (struct sockaddr_in*)&req.arp_pa;
	paddr->sin_family = AF_INET;
	paddr->sin_addr.s_addr = addr;
	
	if(ioctl(fd, SIOCGARP, &req)){
		log_err("Failed to get mac by %#x", addr);
		close(fd);
		return -1;
	}
	close(fd);
	
	memcpy(dmac, req.arp_ha.sa_data, 6);
	if(0 == dmac[0] && 0 == dmac[1] && 0 == dmac[2]
		&&0 == dmac[3] && 0 == dmac[4] && 0 == dmac[5]){
		log_err("Peer mac is zero");
		return -1;
	}
	
	return 0;
}

arp_ipchg_unregister


void arp_ipchg_unregister(void)
{
	ip_chg_cb = NULL;
}

arp_ipchg_register


void arp_ipchg_register(ip_notify_t cb)
{
	ip_chg_cb = cb;
}

arp_notify_unregister


void arp_notify_unregister(int type)
{
	arp_procs[type] = NULL;
}

arp_notify_registe


void arp_notify_register(int type, arp_notify_cb cb)
{
	arp_procs[type] = cb;
}

apps_msp.c

msp_unregister


static void msp_unregister(void)
{
}

msp_register


static void __attribute__((constructor)) msp_register(void)
{
	device_register(DEV_TYPE_MSP, &msp_dev);
}

msp_dev


static struct device msp_dev =
{
	.base = MSP_CH_BASE,
	.size = MSP_CH_NUM_MAX,
	.name = "msp",
	
	.dev_init = msp_dev_init,
	.dev_exit = msp_dev_exit,
	.dev_reset = msp_dev_reset,
	.dev_cfg = msp_dev_cfg,
	.dev_raw = msp_dev_raw,
	
	.ch_init = msp_ch_init,
	.ch_stat = msp_ch_stat,
	.ch_shutdown = msp_ch_shutdown,
	.ch_exit = msp_ch_exit,
	.ch_ioctl = msp_ch_ioctl,
	.ch_t38cfg = msp_ch_t38cfg,
	.ch_t38en = msp_ch_t38en,
	.ch_link = msp_ch_link,
	.ch_loopback = msp_ch_loopback,
};

msp_dev_cfg


static int msp_dev_cfg(int type, int value)
{
	return 0;
}

msp_dev_reset


static int msp_dev_reset(void* arg)
{
	int cnt;
	int* phandle = msp_ch_handle;
	
	for(cnt = 0; cnt < MSP_CH_NUM_MAX; cnt++, phandle++){
		if(*phandle){
			VAPI_DestroyConnection(*phandle, NULL);
		}
	}
	memset(msp_ch_rtp_stat, 0, sizeof(msp_ch_rtp_stat));
	memset(msp_ch_handle, 0, sizeof(msp_ch_handle));
	memset(msp_ch_t38stat, 0, sizeof(msp_ch_t38stat));
	
	return 0;
}

msp_dev_exit


static int msp_dev_exit(void)
{
	VAPI_Close();
	if(msp_buf != NULL){
		VAPI_FreeMessage(msp_buf);
	}
	
	return 0;
}

msp_dev_init


static int msp_dev_init(void *arg)
{
	unsigned int prof;
	
	VAPI_SetDebugLevel(0, 0);
//	VAPI_SetDebugLevel(ALL_INFO, INFO);
	
	if(msp_eth_info(MSP_DEV_CTRL, device_config.aucHostMac, NULL)){
		log_err("failed to get %s info", MSP_DEV_CTRL);
		return -1;
	}
	memcpy(msp_host_mac, device_config.aucHostMac, sizeof(msp_host_mac));
	
	if(VAPI_Init(&device_config) != SUCCESS){
		log_err("failed to init vapi");
		return -1;
	}
	
	msp_buf = VAPI_AllocateMessage(ETH_FIFO_MAX_SIZE);
	if(NULL == msp_buf){
		log_err("failed to init msp buf");
		return -1;
	}
	
	if(VAPI_OpenDevice(MSP_DEV_NUM, NULL) != SUCCESS){
		log_err("failed to open device");
		return -2;
	}
	
	if(msp_init_tdm(MSP_DEV_NUM)){
		log_err("failed to init tdm");
		return -4;
	}
	
	prof = 0x464; //0x04c6;
	if(VAPI_InitDevice(MSP_DEV_NUM, VAPI_DEV_OPMODE_DEFAULT, VAPI_DEV_PROF_SPU_CUSTOM, &prof, NULL) != SUCCESS){
		log_err("failed to init device");
		return -5;
	}
	
	if(msp_init_network()){
		log_err("failed to init network");
		return -6;
	}
	
//	msp_init_g729_hdmode();
	VAPI_RegisterEventCallback(MSP_DEV_NUM, EVENT_LEVEL_GENERIC, msp_event_handler);
//	msp_dev_debug_init();
	msp_dev_res_available();
	
	memset(msp_ch_handle, 0, sizeof(msp_ch_handle));
	
	return 0;
}

msp_init_g729_hdmode


static int msp_init_g729_hdmode(void)
{
	int ret;
	void* msg = msp_buf;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_DEVICE, CMD_TYPE_CONF_CHANGE,
		0x0435, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init g729 hdmode.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set cmd g729 hdmode.%d",ret);
		return -1;
	}
	
	return 0;
}

msp_dev_res_available


static int msp_dev_res_available(void)
{
	void* msg = msp_buf;
	int ret;
	U16 buf[80];
	U32 len = sizeof(buf);
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_OPEN_DIAG, 0x70, 0x2, 2, 0, 0);
	if(ret != SUCCESS){
		log_err("failed to init debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, (U8*)buf, &len);
	if(ret != SUCCESS){
		log_err("failed to set debug.%d",ret);
		return -1;
	}
	
	log_info("msp resource: g723:%d, g726:%d, g729:%d, amr:%d, t38 chs:%d",
		buf[0xa], buf[0xc], buf[0xe], buf[0x10], buf[0x1a]);
	
	return 0;
}

msp_dev_debug_init


static int msp_dev_debug_init(void)
{
	void* msg = msp_buf;
	int ret;
	struct _REDIRECT_CSM_UDP cmd;
	
	VAPI_InitMessage(msg);
	memset(&cmd, 0, sizeof(cmd));
	cmd.param_4.bits.protocol = REDIRECT_CSM_PROTOCOL_OPENDIAGNOSTICS;
	cmd.packet_type = htons(REDIRECT_CSM_UDP_PACKET_TYPE_DEFAULT); /* IP protocol*/
	
	cmd.param_12.bits.ip_hl = REDIRECT_CSM_UDP_IP_HL_DEFAULT;
	cmd.param_12.bits.ip_v = REDIRECT_CSM_UDP_IP_V_DEFAULT;
	cmd.param_12.bits.ip_tos = REDIRECT_CSM_UDP_IP_TOS_DEFAULT;
	
	cmd.ip_len = REDIRECT_CSM_UDP_IP_LEN_DEFAULT;
	cmd.ip_id = REDIRECT_CSM_UDP_IP_ID_DEFAULT;
	cmd.ip_fragment = REDIRECT_CSM_UDP_IP_FRAGMENT_DEFAULT;
	cmd.param_16.word = htons(0x8011); /* UDP , TTL*/
	
	cmd.ip_checksum = REDIRECT_CSM_UDP_IP_CHECKSUM_DEFAULT;
	
	cmd.dst_mac[0] = 0xd4;
	cmd.dst_mac[1] = 0x3d;
	cmd.dst_mac[2] = 0x7e;
	cmd.dst_mac[3] = 0x45;
	cmd.dst_mac[4] = 0x37;
	cmd.dst_mac[5] = 0x1c;
	cmd.ip_dst = htonl(0xc0a80087);
	memcpy(cmd.src_mac, device_mac, 6);
	cmd.ip_src = htonl(0xc0a800fc);
	cmd.udp_sport = htons(30000);
	cmd.udp_dport = htons(30000);
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_CONFIG,
		FC_REDIRECT_CSM_UDP, sizeof(cmd)/2, (U16*)&cmd);
	if(ret != SUCCESS){
		log_err("failed to init redirect debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set debug.%d",ret);
		return -1;
	}
	
#if 1
	//in stream
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x1011, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init debug1.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set debug1.%d",ret);
		return -1;
	}
#endif
	
#if 0
	//out stream
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x1012, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init debug2.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set debug2.%d",ret);
		return -1;
	}
#endif
	
#if 1
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x0e00, 2, 1, 0);
	if(ret != SUCCESS){
		log_err("failed to init tdm rx debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set tdm rx debug.%d",ret);
		return -1;
	}
#endif
	
#if 1
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x0e01, 2, 1, 0);
	if(ret != SUCCESS){
		log_err("failed to init tdm tx debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set tdm tx debug.%d",ret);
		return -1;
	}
#endif
	
#if 1
	//rx packet
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x0802, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init pkt rx debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set pkt rx debug.%d",ret);
		return -1;
	}
#endif
	
#if 1
	//tx packet
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x0803, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init pkt tx debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set pkt tx debug.%d",ret);
		return -1;
	}
#endif
	
#if 0
	//csme mcp trace
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x00fb, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init cmd fb debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set cmd fb debug.%d",ret);
		return -1;
	}
#endif
	
#if 1
	//ec report cmd
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_OPEN_DIAG, CMD_TYPE_DIAG_MON_LIVE_CTRL, 0x00ec, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init cmd ec debug.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(MSP_DEV_NUM, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set cmd ec debug.%d",ret);
		return -1;
	}
#endif
	
	return 0;
}

msp_init_network


static int msp_init_network(void)
{
	SIpAddrInfo info;
	int ret, index = 0;
	
	if(msp_eth_info("eth0", device_mac, device_addr)){
		log_err("failed to get %s info", MSP_DEV_CTRL);
		return -1;
	}
	
	ret = VAPI_SetEthMac(index, CMD_LEVEL_DEVICE, device_mac, msp_host_mac, NULL);
	if(SUCCESS != ret){
		log_err("failed to set ethMac.", ret);
		return -1;
	}
	
	info.ucNumOfSrcIpAddr = 1;
	info.bIsMultipleMode = False;
	memcpy(info.auiDevIPAddress, device_addr, sizeof(device_addr));
	info.ucChkSumVerification = 1;
	info.ucEncapsulation = 2;
	if((ret = VAPI_SetDeviceIPAddr(index, &info, NULL)) != SUCCESS){
		log_err("failed to set ip.%d", ret);
		return -3;
	}
	
	msp_init_ipv6(index);
	
	return 0;
}

msp_init_ipv6


static int msp_init_ipv6(int index)
{
	void* msg = msp_buf;
	int ret, found = 0;
	char addr[40], devname[20];
	FILE* fp;
	int plen, scope, dad_status, if_idx;
	char addr6p[8][5];
	struct _SET_ETH_HDR hdr;
	
	fp = fopen("/proc/net/if_inet6", "r");
	if(NULL == fp){
		return -1;
	}
	
	while (1){
		ret = fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
			addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
			addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname);
		if(EOF == ret){
			break;
		}
		if(0x40 != (scope & 0xf0)){
			continue;
		}
		sprintf(addr, "%s:%s:%s:%s:%s:%s:%s:%s",
					addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
		found = 1;
		break;
	}
	fclose(fp);
	if(!found){
		return 0;
	}
	
	/* prepare the ethernet header for IPv6 operation */ 
	memset(&hdr, 0, sizeof(hdr));
	hdr.param_4.bits.protocol = SET_ETH_HDR_PROTOCOL_IP_V6;
	hdr.param_4.bits.action = SET_ETH_HDR_ACTION_REGISTER;
	memcpy(&(hdr.assignedmac), device_mac, 6);
	memcpy(&(hdr.hostmac), msp_host_mac, 6);
	hdr.type = htons(ETH_P_IPV6);
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_CONF_DEVICE, CMD_TYPE_CONF_CHANGE, FC_SET_ETH_HDR, 8, (U16 *)&hdr);
	if(SUCCESS != ret){
		return -4;
	}
	
	inet_pton(AF_INET6, addr, device_addr);
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_CONF_DEVICE, CMD_TYPE_CONF_CHANGE, FC_IP_ADDRESS_V6, 8, (U16*)device_addr);
	if(SUCCESS != ret){
		return -5;
	}
	
	ret = VAPI_SendDeviceMessage(index, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		return -6;
	}
	
	return 0;
}

msp_eth_info


static int msp_eth_info(uint8_t *name, uint8_t *mac, uint8_t *ip)
{
	int fd;
	struct ifreq ifr;
	struct sockaddr_in *paddr;
	
	fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(fd < 0){
		return -1;
	}
	
	memset(&ifr, 0, sizeof(ifr));
	strcpy(ifr.ifr_name, name);
	
	if(ip){
		if(ioctl(fd, SIOCGIFADDR, &ifr) < 0){
			close(fd);
			return -2;
		}
		paddr = (struct sockaddr_in*)&ifr.ifr_addr;
		memcpy(ip, &paddr->sin_addr.s_addr, 4);
	}
	
	if(ioctl(fd, SIOCGIFHWADDR, &ifr) < 0){
		close(fd);
		return -3;
	}
	memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
	
	close(fd);
	
	return 0;
}

msp_init_tdm


static int msp_init_tdm(int dev)
{
	int ret;
	
	if((ret = VAPI_SetTDMParams(dev, &tdm_param, NULL)) != SUCCESS){
		log_err("Failed to set tdm param.%d", ret);
		return -1;
	}
	
	msp_set_tdm_mode(dev, 0xffff);
	
	return 0;
}

msp_set_tdm_mode


static int msp_set_tdm_mode(int dev, int ch_no)
{
	void *msg = msp_buf;
	int ret = -1;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_DEVICE, CMD_TYPE_CONF_CHANGE,
		FC_SUPVSR_SET_TS_MODE, 2, ch_no, 1);
	if(ret != SUCCESS){
		log_err("failed to init tdm message.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(dev, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set tdm silent.%d", ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_DEVICE, CMD_TYPE_CONF_CHANGE,
		FC_SUPVSR_SET_PCM_LAW, 1, 1); //1 -ALaw, 0-uLaw(default)
	if(ret != SUCCESS){
		log_err("failed to init tdm alaw.%d", ret);
		return -1;
	}
	ret = VAPI_SendDeviceMessage(dev, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set tdm alaw.%d", ret);
		return -1;
	}
	
	return 0;
}

msp_event_handler


static void msp_event_handler(EEventCode event, void *data)
{
	switch(event)
	{   
	case eVAPI_UNDEFINED_EVENT:
		msp_undefined_event_proc(data);
		break;
	case eVAPI_TONE_DETECT_EVENT:
		msp_event_tone_indication(data);
		break;
	case eVAPI_REMOTE_DETECT_EVENT:
		msp_event_tone_remote(data);
		break;
	case eVAPI_FAX_SWITCH_CMPLT_EVENT:
		msp_fax_auto_switch(data);
		break;
	case eVAPI_ALERT_IND:
		msp_event_alert(data);
		break;
	case eVAPI_NTE_RECVD_EVENT:
		msp_event_nte(data);
		break;
	case eVAPI_IPTONE_DETECT_EVENT:
		msp_event_iptone(data);
		break;
	case eVAPI_SPI_EVENT:
	case eVAPI_TONE_GEN_CMPLT_EVENT:
	case eVAPI_PT_CHANGE_EVENT: 
	case eVAPI_SSRC_CHANGE_EVENT:
	case eVAPI_SSRC_VIOLATION_EVENT:
	case eVAPI_NTE_TRANSMIT_COMPLETE_EVENT:
	case eVAPI_CALLER_ID_CMPLT_EVENT:
	case eVAPI_G711_CONCURRENT_DECODER_EVENT:
	case eVAPI_PASSTHRU_CONCURRENT_DECODER_EVENT:
	case eVAPI_CALLER_ID_DETECTED_EVENT:
	case eVAPI_IMSOTDM_H245_EVENT:
	default:
		log_info("msp indicate: event:%d", event);
		break;
	}
}

msp_event_iptone


static void msp_event_iptone(SIPToneDetectEventParams* data)
{
	int cnt;
	
	for(cnt = 0; cnt < MSP_CH_NUM_MAX; cnt ++){
		if(data->ConId == msp_ch_handle[cnt]){
			break;
		}
	}
	log_info("iptone: ch%d  tone:%x", cnt, data->usDetectedTone);
}

msp_fax_auto_switch


static void msp_fax_auto_switch(SFaxSwEventParams* data)
{
	int cnt, ch;
	
	for(ch = 0; ch < MSP_CH_NUM_MAX; ch ++){
		if(data->ConId == msp_ch_handle[ch]){
			break;
		}
	}
	
	log_info("fax auto switch: ch%d, event:%x", ch, data->eSwitchEvent);
}

msp_event_nte


static void msp_event_nte(SNteRecvdEventParams* data)
{
	log_info("nte recv  ch:%d, payload:%#x", data->ConId, data->uNtePayload);
}

msp_event_alert


static void msp_event_alert(SAlrtIndParams* data)
{
	log_info("alert  type:%d", data->usAlrtType);
}

msp_event_tone_remote


static void msp_event_tone_remote(SRemoteDetectEventParams* data)
{
	int cnt;
	
	for(cnt = 0; cnt < MSP_CH_NUM_MAX; cnt ++){
		if(data->ConId == msp_ch_handle[cnt]){
			break;
		}
	}
	
	log_info("tone remote: conId:%d, tone:%d, pkttype:%d", cnt, data->ucDetectedEvent, data->ucRemotePktType);
}

msp_event_tone_indication


static void msp_event_tone_indication(SToneDetectEventParams* data)
{
	int ch_no;
	
	for(ch_no = 0; ch_no < MSP_CH_NUM_MAX; ch_no ++){
		if(data->ConId == msp_ch_handle[ch_no]){
			break;
		}
	}
	if(ch_no >= MSP_CH_NUM_MAX){
		goto tone_ch_err;
	}
	
	switch(data->usDetectedTone)
	{
	case 0x22:
		log_info("ch%d FAX V.21 detected", ch_no);
		msp_ch_switch_to_t38(ch_no, data->ConId);
		break;
	case 0x31:
		if(msp_ch_t38stat[ch_no]){
			msp_ch_rtp_stat[ch_no] = -1;
			log_info("ch%d FAX DCN detected", ch_no);
		}
		break;
	case 0xff:
		break;
	default:
tone_ch_err:
		log_info("tone indicate: conId:%d, tone:%#x", ch_no, data->usDetectedTone);
	}
}

msp_undefined_event_proc


static void msp_undefined_event_proc(SUndefinedEventParams *ev)
{
	int ch_no;
	
	for(ch_no = 0; ch_no < MSP_CH_NUM_MAX; ch_no ++){
		if(ev->ID.ConId == msp_ch_handle[ch_no]){
			break;
		}
	}
	if(ch_no >= MSP_CH_NUM_MAX){
		return;
	}
	
	switch(ev->usFnCode)
	{
	case FC_RTP_MONITOR_IND:
		if(EVENT_LEVEL_CONN != ev->ucLevel){
			break;
		}
		if(ch_no >= MSP_CH_NUM_MAX){
			break;
		}
		msp_ch_rtp_stat[ch_no] = ev->ausParams[0] ? 0 : -1;
		log_info("ch%d %d(0:start, 1:stop, 2:pt change)", ch_no, ev->ausParams[0]);
		break;
	case FC_FAXSTATE:
		break;
	case 0x420:	//tdm signal indication
		log_info("tdm signal: ch%d pattern:%d", ev->ausParams[0], ev->ausParams[1]);
		break;
	default:
		log_info("event func:%#x, param0:%x\n", ev->usFnCode, ev->ausParams[0]);
		break;
	}
}

msp_ch_loopback


static int msp_ch_loopback(int ch1, int ch2, int enable)
{
	uint32_t handle1 = msp_ch_handle[ch1];
	uint32_t handle2 = msp_ch_handle[ch2];
	int type = enable ? eTHC : eREMOVE_THC_LOOPBACK;
	int ret;
	
	if(!handle1 || !handle2){
		return -1;
	}
	
	type = enable ? eINTER_CHNL_POST_ENCAPS: eREMOVE_THC_LOOPBACK;
	ret = VAPI_Loopback(handle1, handle2, type, NULL);
	if(SUCCESS != ret){
		log_err("loopback error %d", ret);
		return -1;
	}
	
	return 0;
}

msp_ch_link


static int msp_ch_link(int ch_no)
{
	return msp_ch_rtp_stat[ch_no];
}

msp_ch_t38en


static int msp_ch_t38en(int ch_no, int enable)
{
	uint32_t handle = msp_ch_handle[ch_no];
	int ret;
	
	if(!handle){
		return -1;
	}
	
	if(msp_ch_switch_to_t38(ch_no, handle)){
		log_err("Failed to switch t38.%d", ch_no);
		return -1;
	}
	
	return 0;
}

msp_ch_t38cfg


static int msp_ch_t38cfg(int ch_no, struct t38_param *arg)
{
	SFaxConfigOpts ops;
	uint32_t handle = msp_ch_handle[ch_no];
	int ret;
	
	if(!handle){
		return -1;
	}
	
	ops.bUseExistingOpts = False;
	ops.ucFaxTxLevel = 0x8;
	ops.bEnableFaxAutoSwitch = False;
	ops.usSwitchoverEventMask = 0;
	ops.stFaxOpts.ucT38PktLossConcealment = arg->loss_conceal;
	ops.stFaxOpts.ucECMDisable = 1;
	ops.stFaxOpts.ucFaxDataRedundancyCnt = arg->data_redundancy;
	ops.stFaxOpts.ucT30RedundancyCnt = arg->t30_redundancy;
	ops.stFaxOpts.ucFaxConnSpeedLimit = arg->speed;
	ops.stFaxOpts.ucErrRcvyMethod = arg->err_method;
	ops.stFaxOpts.ucTCFProcedure = 0;
	ops.stFaxOpts.ucNumFEC = arg->numFEC;
	ops.stFaxOpts.ucNumIFPs = arg->numIFPs;
	ops.stFaxOpts.usParam2 = 0;
	ret = VAPI_ConfigureT38Options(handle, &ops, NULL);
	if(SUCCESS != ret){
		return -1;
	}
	
	return 0;
}

msp_ch_switch_to_t38


static int msp_ch_switch_to_t38(int ch_no, uint32_t handle)
{
	int ret;
	
	if(msp_ch_t38stat[ch_no]){
		return 0;
	}
	
	if(SUCCESS != VAPI_SetPayloadType(handle, eIFP, 0x62, eBoth, NULL)){
		return -1;
	}
	if(SUCCESS != VAPI_SwitchToT38(handle, NULL, NULL)){
		log_err("switch to t38");
		return -1;
	}
#if 0
	if(msp_ch_t38udpl_cfg(handle, ch_no, 0)){
		return -1;
	}
#endif
	
	ret = VAPI_SetConnectionState(handle, eActive, NULL);
	if(SUCCESS != ret){
		log_err("enable t38 %d", ret);
		return -1;
	}
	
	msp_ch_t38stat[ch_no] = 1;
	
	return 0;
}

msp_ch_t38udpl_cfg


static int msp_ch_t38udpl_cfg(uint32_t handle, int ch, int byte_based)
{
	void *msg = msp_buf;
	uint16_t value = byte_based ? 0x70 : 0x40;
	int ret = -1;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_FOIP_FAXSPLOPT, 1, value);
	if(ret != SUCCESS){
		log_err("failed to init byte based message");
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set byte based");
		return -1;
	}
	
	return 0;
}

msp_dev_raw


static int msp_dev_raw(int addr, int is_read, int* value)
{
	return -1;
}

msp_ch_ioctl


static int msp_ch_ioctl(int ch_no, int cmd, void *arg)
{
	int ret = -1;
	
	switch(cmd)
	{
	default:
		break;
	}
	
	return ret;
}

msp_ch_exit


static int msp_ch_exit(int ch_no)
{
	if(!msp_ch_handle[ch_no]){
		log_err("ch%d is not active", ch_no);
		return -1;
	}
	
	VAPI_DestroyConnection(msp_ch_handle[ch_no], NULL);
	msp_ch_handle[ch_no] = 0;
	msp_ch_t38stat[ch_no] = 0;
	
	return 0;
}

msp_ch_shutdown


static int msp_ch_shutdown(int ch_no, int dir)
{
	return -1;
}

msp_ch_stat


static int msp_ch_stat(int ch_no, int dir, int stat)
{
	uint32_t handle = msp_ch_handle[ch_no];
	int ch_stat = stat ? eActive : eInactive;
	
	if(!handle){
		return -1;
	}
	
	if(VAPI_SetConnectionState(handle, ch_stat, NULL) != SUCCESS){
		return -1;
	}
	
	return 0;
}

msp_ch_init


static int msp_ch_init(int ch_no, struct param *param)
{
	uint32_t handle, dev = MSP_DEV_NUM;
	struct timeval tv;
	int ret;
	uint16_t tmp = ch_no;
	uint8_t payload;
	ECodecIndex codec;
	int interval = MSP_CODEC_INTERVAL_DEF;
	
	if(msp_ch_handle[ch_no]){
		log_err("Please close the ch %d first", ch_no);
		return -1;
	}
	
	gettimeofday(&tv, NULL);
	handle = tv.tv_sec * 1000000ULL + tv.tv_usec;
	ret = VAPI_AllocateConnection(dev, handle, eVOIP, eNarrowBand, 1, &tmp, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to alloc connection.%d", ret);
		return -2;
    }
	
	codec = msp_audio_translate(param->codec, &payload);
	if(eG723_1 == codec){
		interval = 30;
	}
	if(VAPI_SetCodecType(handle, codec, NULL) != SUCCESS){
		log_err("failed to set codec type");
		goto channel_init_failed;
	}
	
	if(SUCCESS != VAPI_SetPayloadType(handle, codec, payload, eBoth, NULL)){
		log_err("failed to set payload");
		goto channel_init_failed;
	}
	
	switch(param->ipver)
	{
	case 4:
		if(msp_ch_init_ipv4(ch_no, handle, param)){
			goto channel_init_failed;
		}
		break;
	case 6:
		if(msp_ch_init_ipv6(ch_no, handle, param)){
			goto channel_init_failed;
		}
		break;
	default:
		log_err("ip version error.%d", param->ipver);
		goto channel_init_failed;
	}
	
	if(VAPI_SetRtpSsrcHeader(handle, param->ssrc, NULL) != SUCCESS){
		log_err("failed to set ssrc");
		goto channel_init_failed;
	}
	
	if(msp_ch_indicate_cfg(handle, 60000)){
		log_err("failed to set rtp monitor");
		goto channel_init_failed;
	}
	
	if(VAPI_SetPacketInterval(handle, interval, NULL) != SUCCESS){
		log_err("failed to set packet interval");
		goto channel_init_failed;
	}
	
	msp_ch_tonectrl_init(ch_no, handle);
	msp_ch_iptone_option(handle);
	
	if(SUCCESS != VAPI_SetEthMac(handle, CMD_LEVEL_CONN, device_mac, param->gw_mac, NULL)){
		log_err("failed to set ch%d ethMac", ch_no);
		goto channel_init_failed;
	}
	
	VAPI_EchoCancellerReset(handle, NULL);
	
	msp_ch_t38stat[ch_no] = 0;
	msp_ch_handle[ch_no] = handle;
	msp_ch_rtp_stat[ch_no] = 0;
	
	return 0;
	
channel_init_failed:
	VAPI_DestroyConnection(handle, NULL);
    return CMD_ERR_IO;
}

msp_addr2ip


static void msp_addr2ip(uint8_t* addr, int ipver, uint16_t* ip)
{
	int cnt, max = 4 == ipver ? 4 : 16;
	
	for(cnt = 0; cnt < max; cnt += 2){
		ip[cnt >> 1] = (addr[cnt] << 8) | addr[cnt + 1];
	}
}

msp_ch_iptone_option


static int msp_ch_iptone_option(uint32_t handle)
{
	void *msg = msp_buf;
	int ret;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE, 
		FC_VOIP_TONES_RELAY_OPTION, 2, 0x101, 0);
	if(ret != SUCCESS){
		log_err("failed to init iptone.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set iptone.%d",ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg,CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE, FC_IPTONEDETEN, 1, 1);
	if(ret != SUCCESS){
		log_err("failed to init iptone enable.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set iptone enable.%d",ret);
		return -1;
	}
	
	return 0;
}

msp_ch_tonectrl_init


static int msp_ch_tonectrl_init(int ch_no, uint32_t handle)
{
	void *msg = msp_buf;
	int ret;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_VOIP_TONECTRL, 5, 0xc017, 0, 0x1f, 0x1f, 0);
	if(ret != SUCCESS){
		log_err("failed to init tonectrl.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set tone contrl error.%d", ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_VOIP_TONEOPT, 2, 0x5f, 0);
	if(SUCCESS != ret){
		log_err("Failed to set toneopt.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set tone option error.%d", ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_VOIP_INDCTRL, 3, 0x3, 0, 120);
	if(SUCCESS != ret){
		log_err("Failed to set indctrl.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set tone indctrl error.%d", ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_IPDTMF_CTRL, 2, 0xc9, 0);
	if(SUCCESS != ret){
		log_err("Failed to set dtmfctrl.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set tone dtmfctrl error.%d", ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_VOIP_DTMFOPT, 1, 0x29);
	if(SUCCESS != ret){
		log_err("Failed to set dtmfopt.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set tone dtmfopt error.%d", ret);
		return -1;
	}
	
	return 0;
}

msp_ch_init_ipv6


static int msp_ch_init_ipv6(int ch_no, uint32_t handle, struct param* param)
{
	void *msg = msp_buf;
	struct _SET_IPV6_HDR_CHANNEL hdr;
	int ret;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_SET_CHANNEL_IP_MODE, 1, (U16*)1);
	if(ret != SUCCESS){
		log_err("failed to init rtp.%d", ret);
		return -1;
	}
	
	memset(&hdr, 0, sizeof(struct _SET_IPV6_HDR_CHANNEL));
	hdr.param_4.bits.serviceid = SET_IPV6_HDR_CHANNEL_SERVICEID_DEFAULTPKT;
	hdr.param_5.word = 0x0060;	/*Traffic class bit 0:3, version, flow label bits 0:3, traffic class bit 4:7*/
	hdr.param_6.word = 0x0000;	/*flow label bits 4:11 & 12:19*/
	hdr.payload_len = 0x0000;	/*len (overwritten) */
	hdr.param_8.bits.next_header_id = 0x11;
	hdr.param_8.bits.hop_limit = 0x80;

	memcpy(&hdr.ipv6_src_15_0, param->saddr, sizeof(hdr.ipv6_src_15_0));
	memcpy(&hdr.ipv6_dst_15_0, param->saddr, sizeof(hdr.ipv6_dst_15_0));
	hdr.uh_sport = htons(param->sport);
	hdr.uh_dport = htons(param->dport);
	hdr.uh_ulen = 0x0000;
	hdr.uh_sum = 0x0000;
	
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE, 
			FC_SET_IP_HDR_CHANNEL, sizeof(hdr)/2, (U16 *)&hdr);
	if(SUCCESS != ret){
		return -1;
	}
	
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set ipv6 hdr error.%d", ret);
		return -1;
	}
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_SET_CHANNEL_IP_MODE, 1, (U16*)1);
	if(ret != SUCCESS){
		log_err("failed to init rtp.%d", ret);
		return -1;
	}
	hdr.param_4.bits.serviceid = 1;
	hdr.uh_sport = htons(param->sport + 1);
	hdr.uh_dport = htons(param->dport + 1);
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE, 
			FC_SET_IP_HDR_CHANNEL, sizeof(hdr)/2, (U16 *)&hdr);
	if(SUCCESS != ret){
		return -1;
	}
	
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(SUCCESS != ret){
		log_err("set rtcp ipv6 hdr error.%d", ret);
		return -1;
	}
	
	return 0;
}

msp_ch_init_ipv4


static int msp_ch_init_ipv4(int ch_no, uint32_t handle, struct param* param)
{
	SIpParams ip;
	
	ip.ucIPServiceId = 0;
	memcpy(&ip.uiDestIpAddr, param->daddr, 4);
	ip.usDestUdpPort = htons(param->dport);
	memcpy(&ip.uiSrcIpAddr, param->saddr, 4);
	ip.usSrcUdpPort = htons(param->sport);
	if(VAPI_SetConnIpParams(handle, &ip, NULL) != SUCCESS){
		log_err("failed to set rtp addr");
		return -1;
   	 }
	
	ip.ucIPServiceId = 1;
	ip.usDestUdpPort = htons(param->dport + 1);
	ip.usSrcUdpPort = htons(param->sport + 1);
	if(VAPI_SetConnIpParams(handle, &ip, NULL) != SUCCESS){
		log_err("failed to set rtcp addr");
		return -1;
   	 }
	if(msp_ch_rtcp_cfg(handle, 1)){
		return -1;
	}
	
	return 0;
}

msp_ch_rtcp_cfg


static int msp_ch_rtcp_cfg(int handle, int enable)
{
	void *msg = msp_buf;
	struct _SDES_CNAME cname;
	struct _RTCP_ENA ena;
	int ret;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_SET_RTCP_GENERATION_GRANULARITY, 2, 5, 1);
	if(ret != SUCCESS){
		log_err("failed to init rtcp.%d", ret);
		return -1;
	}
	cname.length = strlen("eth0");
	memcpy(cname.sdes_cname, "eth0", cname.length);
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_SDES_CNAME, 1 + cname.length/2, (U16*)&cname);
	if(SUCCESS != ret){
		log_err("Failed to build cname.%d", ret);
		return -1;
	}
	
	memset(&ena, 0, sizeof(ena));
	ena.param_4.word = 0x0000;
	ena.param_4.bits.rtcp = enable ? RTCP_ENA_RTCP_ENABLE : RTCP_ENA_RTCP_DISABLE;
	ret = VAPI_SetMessageFromBuffer(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE, 
			FC_RTCP_ENA, sizeof(ena)/2, (U16 *)&ena);
	if(SUCCESS != ret){
		log_err("Failed to build rtcpen.%d", ret);
		return -1;
	}
	
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to update rtcp. %d", ret);
		return -1;
	}
	
	return 0;
}

msp_ch_indicate_cfg


static int msp_ch_indicate_cfg(int handle, int msecond)
{
	void *msg = msp_buf;
	int ret = -1;
	
	VAPI_InitMessage(msg);
	ret = VAPI_SetMessage(msg, CMD_CLASS_CONF_CHANNEL, CMD_TYPE_CONF_CHANGE,
		FC_RTP_MONITOR_ENA, 3, 1, msecond & 0xffff, (msecond >> 16) & 0xffff);
	if(ret != SUCCESS){
		log_err("failed to init indicate.%d", ret);
		return -1;
	}
	ret = VAPI_SendConnectionMessage(handle, msg, NULL, NULL, NULL);
	if(ret != SUCCESS){
		log_err("failed to set indicate.%d",ret);
		return -1;
	}
	
	return 0;
}

msp_audio_translate


static inline int msp_audio_translate(int audio, unsigned char *payload)
{   
	switch(audio)
	{      
	case CODEC_TYPE_ULAW:
		*payload = 0;
		return eG711_ULAW_PCM;
	case CODEC_TYPE_ALAW:
		*payload = 8;
		return eG711_ALAW_PCM;
	case CODEC_TYPE_G723:
		*payload = 4;
		return eG723_1;
	case CODEC_TYPE_G728:
		*payload = 15;
		return eG728_Audio;
	case CODEC_TYPE_DTMF:
		return eDTMF_RTP;
	case CODEC_TYPE_G729A:
		*payload = 18;
		return eG729_A;
	case CODEC_TYPE_G729AB:
		*payload = 103;
		return eG729_MSPD;
	case CODEC_TYPE_G726_32:
		*payload = 2;
		return eG726_32;
	default:
		break;
	}
	 
	*payload = 8;
	return eG711_ALAW_PCM;
}

tdm_param


static STdmSetupParams tdm_param =
{
	.usMode = 1,
	.usNoOfBus = 1,
	.astTdmBusParam ={
		[0] = {
			.ucBusId = 0,
			.ucTxOrder = 1,
			.ucRxPolarity = 0,
			.ucTxPolarity = 0,
			.ucRxClkMode = 0,
			.ucTxClkMode = 0,
			.ucRxClkEdge = 0,
			.ucTxClkEdge = 1,
			.ucFrameEdge = 1,
			.usNumOfTS =  MSP_CH_NUM_MAX,
			.ucInvertedFrmSig = 1,
			.ucBitOrderRcv = 1,
			.usNumTdmClkCyclesDelayTx = 0,
			.usNumTdmClkCyclesDelayRx = 0,
		}
	},
};

device_config


static SCSMEUsrData device_config =
{
	.usControlInterface = eCSM_ITF,
	.uiDevId = MSP_DEV_NUM,
	.uiVersion = 0,
	.eDevMode = eMASTER,
	.ucDevType = DEV_TYPE_M823XX_2,
	.bUseDefaultMaxChnls = False,
	.usMaxChannels = MAX_CHANNELS_M823XX,
	.aucDevMac = {0x00,0x11,0x22,0x33,0x44,0x55},
	.aucHostMac = {},
	.aucDevHardMac = {},
	.pucEthDevName = MSP_DEV_CTRL,
	.ucEthBootMode = BOOT_MODE_LEGACY,
	.ucIsAckReqd = 1,
};
















































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值