294 lines
7.9 KiB
C
294 lines
7.9 KiB
C
/*
|
|
* Internal functions for Tenovis lib
|
|
*
|
|
*/
|
|
|
|
#include "tenovis_int.h"
|
|
#include "tenovis.h"
|
|
|
|
static tenovisdev_t *tdevlist = NULL;
|
|
static pthread_mutex_t tdevlist_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
tenovisdev_t *
|
|
alloc_tdevice(int fid)
|
|
{
|
|
tenovisdev_t *dev;
|
|
|
|
dev = malloc(sizeof(tenovisdev_t));
|
|
if (!dev) {
|
|
close(fid);
|
|
errno = ENODEV;
|
|
return(NULL);
|
|
}
|
|
memset(dev, 0, sizeof(tenovisdev_t));
|
|
dev->fid = fid;
|
|
dev->size = TN_INBUFFER_SIZE;
|
|
dev->buf.p = malloc(dev->size);
|
|
if (!dev->buf.p) {
|
|
close(fid);
|
|
free(dev);
|
|
errno = ENODEV;
|
|
return(NULL);
|
|
}
|
|
pthread_mutex_init(&dev->mutex, NULL);
|
|
pthread_mutex_lock(&tdevlist_lock);
|
|
dev->prev = tdevlist;
|
|
while(dev->prev && dev->prev->next)
|
|
dev->prev = dev->prev->next;
|
|
if (tdevlist)
|
|
dev->prev->next = dev;
|
|
else
|
|
tdevlist = dev;
|
|
pthread_mutex_unlock(&tdevlist_lock);
|
|
return(dev);
|
|
}
|
|
|
|
tenovisdev_t *
|
|
get_tdevice(int fid)
|
|
{
|
|
tenovisdev_t *dev;
|
|
|
|
pthread_mutex_lock(&tdevlist_lock);
|
|
dev = tdevlist;
|
|
while(dev) {
|
|
if (dev->fid==fid)
|
|
break;
|
|
dev = dev->next;
|
|
}
|
|
pthread_mutex_unlock(&tdevlist_lock);
|
|
return(dev);
|
|
}
|
|
|
|
int
|
|
free_tdevice(tenovisdev_t *dev)
|
|
{
|
|
int ret;
|
|
|
|
if (dev->prev)
|
|
dev->prev->next = dev->next;
|
|
if (dev->next)
|
|
dev->next->prev = dev->prev;
|
|
if (tdevlist==dev)
|
|
tdevlist=dev->next;
|
|
pthread_mutex_lock(&dev->mutex);
|
|
if (dev->buf.p)
|
|
free(dev->buf.p);
|
|
dev->buf.p = NULL;
|
|
pthread_mutex_unlock(&dev->mutex);
|
|
ret = pthread_mutex_destroy(&dev->mutex);
|
|
if (ret)
|
|
fprintf(stderr, __FUNCTION__ "mutex destroy returns %d\n",
|
|
ret);
|
|
ret = mISDN_close(dev->fid);
|
|
free(dev);
|
|
return(ret);
|
|
}
|
|
|
|
int
|
|
setup_tdevice(tenovisdev_t *dev)
|
|
{
|
|
int ret;
|
|
stack_info_t *stinf;
|
|
layer_info_t linf;
|
|
interface_info_t iinf;
|
|
|
|
ret = mISDN_write_frame(dev->fid, dev->buf.p, 0,
|
|
MGR_SETDEVOPT | REQUEST, FLG_mISDNPORT_ONEFRAME,
|
|
0, NULL, TIMEOUT_1SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "MGR_SETDEVOPT ret(%d)\n", ret);
|
|
#endif
|
|
ret = mISDN_read(dev->fid, dev->buf.p, 1024, TIMEOUT_10SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_read ret(%d) pr(%x) di(%x) l(%d)\n",
|
|
ret, dev->buf.f->prim, dev->buf.f->dinfo, dev->buf.f->len);
|
|
#endif
|
|
ret = mISDN_get_stack_count(dev->fid);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "stackcnt %d\n", ret);
|
|
#endif
|
|
if (ret <= 0) {
|
|
free_tdevice(dev);
|
|
errno = ENODEV;
|
|
return(-1);
|
|
}
|
|
ret = mISDN_get_stack_info(dev->fid, 1, dev->buf.p, dev->size);
|
|
stinf = (stack_info_t *)&dev->buf.f->data.p;
|
|
#ifdef PRINTDEBUG
|
|
mISDNprint_stack_info(stdout, stinf);
|
|
fprintf(stdout, "ext(%x) instcnt(%d) childcnt(%d)\n",
|
|
stinf->extentions, stinf->instcnt, stinf->childcnt);
|
|
#endif
|
|
dev->dstid = stinf->id;
|
|
dev->dl0id = mISDN_get_layerid(dev->fid, dev->dstid, 0);
|
|
dev->dl1id = mISDN_get_layerid(dev->fid, dev->dstid, 1);
|
|
dev->dl2id = mISDN_get_layerid(dev->fid, dev->dstid, 2);
|
|
dev->dl3id = mISDN_get_layerid(dev->fid, dev->dstid, 3);
|
|
dev->dl4id = mISDN_get_layerid(dev->fid, dev->dstid, 4);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, " dl0id = %08x\n", dev->dl0id);
|
|
fprintf(stdout, " dl1id = %08x\n", dev->dl1id);
|
|
fprintf(stdout, " dl2id = %08x\n", dev->dl2id);
|
|
fprintf(stdout, " dl3id = %08x\n", dev->dl3id);
|
|
fprintf(stdout, " dl4id = %08x\n", dev->dl4id);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl2id;
|
|
iinf.stat = IF_UP;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l2 up own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl2id;
|
|
iinf.stat = IF_DOWN;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l2 down own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl3id;
|
|
iinf.stat = IF_UP;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l3 up own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl3id;
|
|
iinf.stat = IF_DOWN;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l3 down own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
#endif
|
|
memset(&linf, 0, sizeof(layer_info_t));
|
|
strcpy(&linf.name[0], "tenovis L2");
|
|
linf.object_id = -1;
|
|
linf.extentions = EXT_INST_MIDDLE;
|
|
linf.pid.protocol[stinf->instcnt] = ISDN_PID_ANY;
|
|
linf.pid.layermask = ISDN_LAYER(stinf->instcnt);
|
|
linf.st = dev->dstid;
|
|
dev->tlid = mISDN_new_layer(dev->fid, &linf);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_new_layer ret(%x)\n", dev->tlid);
|
|
ret = mISDN_get_stack_info(dev->fid, 1, dev->buf.p, dev->size);
|
|
stinf = (stack_info_t *)&dev->buf.f->data.p;
|
|
mISDNprint_stack_info(stdout, stinf);
|
|
#endif
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.extentions = EXT_INST_MIDDLE;
|
|
iinf.owner = dev->tlid;
|
|
iinf.peer = dev->dl3id;
|
|
iinf.stat = IF_UP;
|
|
ret = mISDN_write_frame(dev->fid, dev->buf.p, dev->tlid,
|
|
MGR_SETIF | REQUEST, 0, sizeof(interface_info_t),
|
|
&iinf, TIMEOUT_1SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_write_frame ret(%d)\n", ret);
|
|
#endif
|
|
ret = mISDN_read(dev->fid, dev->buf.p, 1024, TIMEOUT_10SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_read ret(%d) pr(%x) di(%x) l(%d)\n",
|
|
ret, dev->buf.f->prim, dev->buf.f->dinfo,
|
|
dev->buf.f->len);
|
|
#endif
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.extentions = EXT_INST_MIDDLE;
|
|
iinf.owner = dev->tlid;
|
|
iinf.peer = dev->dl2id;
|
|
iinf.stat = IF_DOWN;
|
|
ret = mISDN_write_frame(dev->fid, dev->buf.p, dev->tlid,
|
|
MGR_SETIF | REQUEST, 0, sizeof(interface_info_t),
|
|
&iinf, TIMEOUT_1SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_write_frame ret(%d)\n", ret);
|
|
#endif
|
|
ret = mISDN_read(dev->fid, dev->buf.p, 1024, TIMEOUT_10SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_read ret(%d) pr(%x) di(%x) l(%d)\n",
|
|
ret, dev->buf.f->prim, dev->buf.f->dinfo,
|
|
dev->buf.f->len);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl2id;
|
|
iinf.stat = IF_UP;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l2 up own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl2id;
|
|
iinf.stat = IF_DOWN;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l2 down own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl3id;
|
|
iinf.stat = IF_UP;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l3 up own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
memset(&iinf, 0, sizeof(interface_info_t));
|
|
iinf.owner = dev->dl3id;
|
|
iinf.stat = IF_DOWN;
|
|
ret = mISDN_get_interface_info(dev->fid, &iinf);
|
|
fprintf(stdout, "l3 down own(%x) -> peer(%x)\n",
|
|
iinf.owner, iinf.peer);
|
|
#endif
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
shutdown_tdevice(tenovisdev_t *dev)
|
|
{
|
|
int ret;
|
|
|
|
pthread_mutex_lock(&dev->mutex);
|
|
if (dev->buf.p) {
|
|
if (dev->tlid) {
|
|
ret = mISDN_write_frame(dev->fid, dev->buf.p,
|
|
dev->tlid, MGR_DELLAYER | REQUEST,
|
|
0, 0, NULL, TIMEOUT_1SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "MGR_DELLAYER ret(%d)\n", ret);
|
|
#endif
|
|
ret = mISDN_read(dev->fid, dev->buf.p, 1024,
|
|
TIMEOUT_10SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, "mISDN_read ret(%d) pr(%x) di(%x) l(%d)\n",
|
|
ret, dev->buf.f->prim, dev->buf.f->dinfo,
|
|
dev->buf.f->len);
|
|
#endif
|
|
}
|
|
}
|
|
pthread_mutex_unlock(&dev->mutex);
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
intern_read(tenovisdev_t *dev)
|
|
{
|
|
int ret;
|
|
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, __FUNCTION__" addr(%x) prim(%x)\n",
|
|
dev->buf.f->addr, dev->buf.f->prim);
|
|
#endif
|
|
if (dev->buf.f->addr == (dev->tlid | IF_UP)) {
|
|
if (dev->buf.f->prim == (DL_ESTABLISH | REQUEST)) {
|
|
dev->Flags |= TN_FLG_L2_ACTIV;
|
|
ret = mISDN_write_frame(dev->fid, dev->buf.p,
|
|
dev->tlid | IF_UP, DL_ESTABLISH | CONFIRM,
|
|
0, 0, NULL, TIMEOUT_1SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, __FUNCTION__": estab cnf ret(%d)\n",
|
|
ret);
|
|
#endif
|
|
} else if (dev->buf.f->prim == (DL_RELEASE | REQUEST)) {
|
|
dev->Flags &= ~TN_FLG_L2_ACTIV;
|
|
ret = mISDN_write_frame(dev->fid, dev->buf.p,
|
|
dev->tlid | IF_UP, DL_RELEASE | CONFIRM,
|
|
0, 0, NULL, TIMEOUT_1SEC);
|
|
#ifdef PRINTDEBUG
|
|
fprintf(stdout, __FUNCTION__": rel cnf ret(%d)\n",
|
|
ret);
|
|
#endif
|
|
}
|
|
}
|
|
return(-2);
|
|
}
|
|
|