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,
};