Add BRI support to libpri
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@486 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
2
libpri.h
2
libpri.h
@@ -421,7 +421,7 @@ typedef int (*pri_io_cb)(struct pri *pri, void *buf, int buflen);
|
||||
must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
|
||||
must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
|
||||
extern struct pri *pri_new(int fd, int nodetype, int switchtype);
|
||||
extern struct pri *pri_new_bri(int fd, int nodetype, int switchtype);
|
||||
extern struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype);
|
||||
|
||||
/* Create D-channel just as above with user defined I/O callbacks and data */
|
||||
extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
|
||||
|
||||
18
pri.c
18
pri.c
@@ -187,12 +187,13 @@ static int __pri_write(struct pri *pri, void *buf, int buflen)
|
||||
return res;
|
||||
}
|
||||
|
||||
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei)
|
||||
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri)
|
||||
{
|
||||
struct pri *p;
|
||||
p = malloc(sizeof(struct pri));
|
||||
if (p) {
|
||||
memset(p, 0, sizeof(struct pri));
|
||||
p->bri = bri;
|
||||
p->fd = fd;
|
||||
p->read_func = rd;
|
||||
p->write_func = wr;
|
||||
@@ -223,7 +224,7 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
||||
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
||||
p->sapi = Q921_SAPI_GR303_EOC;
|
||||
p->tei = Q921_TEI_GR303_EOC_OPS;
|
||||
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH);
|
||||
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, Q921_TEI_GR303_EOC_PATH, 0);
|
||||
if (!p->subchannel) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
@@ -232,7 +233,7 @@ struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master,
|
||||
p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
|
||||
p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
|
||||
p->tei = Q921_TEI_GR303_TMC_CALLPROC;
|
||||
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING);
|
||||
p->subchannel = __pri_new_tei(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, Q921_TEI_GR303_TMC_SWITCHING, 0);
|
||||
if (!p->subchannel) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
@@ -276,12 +277,15 @@ int pri_restart(struct pri *pri)
|
||||
|
||||
struct pri *pri_new(int fd, int nodetype, int switchtype)
|
||||
{
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI);
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI, 0);
|
||||
}
|
||||
|
||||
struct pri *pri_new_bri(int fd, int nodetype, int switchtype)
|
||||
struct pri *pri_new_bri(int fd, int ptpmode, int nodetype, int switchtype)
|
||||
{
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_GROUP);
|
||||
if (ptpmode)
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_PRI, 1);
|
||||
else
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, Q921_TEI_GROUP, 1);
|
||||
}
|
||||
|
||||
struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
|
||||
@@ -290,7 +294,7 @@ struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read,
|
||||
io_read = __pri_read;
|
||||
if (!io_write)
|
||||
io_write = __pri_write;
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI);
|
||||
return __pri_new_tei(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, Q921_TEI_PRI, 0);
|
||||
}
|
||||
|
||||
void *pri_get_userdata(struct pri *pri)
|
||||
|
||||
@@ -61,6 +61,7 @@ struct pri {
|
||||
int localtype; /* Local network type (unknown, network, cpe) */
|
||||
int remotetype; /* Remote network type (unknown, network, cpe) */
|
||||
|
||||
int bri;
|
||||
int sapi;
|
||||
int tei;
|
||||
int protodisc;
|
||||
@@ -269,6 +270,6 @@ extern void pri_error(struct pri *pri, char *fmt, ...);
|
||||
|
||||
void libpri_copy_string(char *dst, const char *src, size_t size);
|
||||
|
||||
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei);
|
||||
struct pri *__pri_new_tei(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int tei, int bri);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -294,7 +294,7 @@ static int run_pri(int dfd, int swtype, int node)
|
||||
fd_set rfds, efds;
|
||||
int res,x;
|
||||
|
||||
pri = pri_new(dfd, node, swtype);
|
||||
pri = pri_new_bri(dfd, 1, node, swtype);
|
||||
if (!pri) {
|
||||
fprintf(stderr, "Unable to create PRI\n");
|
||||
return -1;
|
||||
|
||||
4
q921.c
4
q921.c
@@ -799,7 +799,7 @@ static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
|
||||
if(sub->subchannel->tei == tei)
|
||||
++tei;
|
||||
}
|
||||
sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei);
|
||||
sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
|
||||
if (!sub->subchannel) {
|
||||
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
|
||||
return NULL;
|
||||
@@ -819,7 +819,7 @@ static pri_event *q921_receive_MDL(struct pri *pri, q921_u *h, int len)
|
||||
pri_error(pri, "TEI already assigned (new is %d, current is %d)\n", tei, pri->subchannel->tei);
|
||||
}
|
||||
pri_message(pri, "TEI assiged to %d\n", tei);
|
||||
pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei);
|
||||
pri->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1);
|
||||
if (!pri->subchannel) {
|
||||
pri_error(pri, "Unable to allocate D-channel for new TEI %d\n", tei);
|
||||
return NULL;
|
||||
|
||||
73
q931.c
73
q931.c
@@ -294,15 +294,22 @@ static FUNC_RECV(receive_channel_id)
|
||||
}
|
||||
#endif
|
||||
#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
|
||||
switch (ie->data[0] & 3) {
|
||||
case 0:
|
||||
if (pri->bri) {
|
||||
if (!(ie->data[0] & 3))
|
||||
call->justsignalling = 1;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
|
||||
return -1;
|
||||
else
|
||||
call->channelno = ie->data[0] & 3;
|
||||
} else {
|
||||
switch (ie->data[0] & 3) {
|
||||
case 0:
|
||||
call->justsignalling = 1;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ie->data[0] & 0x08)
|
||||
@@ -366,7 +373,11 @@ static FUNC_SEND(transmit_channel_id)
|
||||
/* Start with standard stuff */
|
||||
if (pri->switchtype == PRI_SWITCH_GR303_TMC)
|
||||
ie->data[pos] = 0x69;
|
||||
else
|
||||
else if (pri->bri) {
|
||||
ie->data[pos] = 0x80;
|
||||
if (call->channelno > -1)
|
||||
ie->data[pos] |= (call->channelno & 0x3);
|
||||
} else
|
||||
ie->data[pos] = 0xa1;
|
||||
/* Add exclusive flag if necessary */
|
||||
if (call->chanflags & FLAG_EXCLUSIVE)
|
||||
@@ -383,6 +394,10 @@ static FUNC_SEND(transmit_channel_id)
|
||||
ie->data[pos++] = 0x80 | call->ds1no;
|
||||
} else
|
||||
pos++;
|
||||
|
||||
if (pri->bri)
|
||||
return pos + 2;
|
||||
|
||||
if ((call->channelno > -1) || (call->slotmap != -1)) {
|
||||
/* We'll have the octet 8.2 and 8.3's present */
|
||||
ie->data[pos++] = 0x83;
|
||||
@@ -2375,26 +2390,40 @@ static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q9
|
||||
{
|
||||
/* Returns header and message header and modifies length in place */
|
||||
q931_h *h = (q931_h *)buf;
|
||||
q931_mh * mh = (q931_mh *)(h->contents + 2);
|
||||
q931_mh * mh;
|
||||
h->pd = pri->protodisc;
|
||||
h->x0 = 0; /* Reserved 0 */
|
||||
h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
|
||||
if (call->cr || call->forceinvert) {
|
||||
h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
|
||||
h->crv[1] = (call->cr & 0xff);
|
||||
if (!pri->bri) {
|
||||
h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
|
||||
if (call->cr || call->forceinvert) {
|
||||
h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
|
||||
h->crv[1] = (call->cr & 0xff);
|
||||
} else {
|
||||
/* Unless of course this has no call reference */
|
||||
h->crv[0] = 0;
|
||||
h->crv[1] = 0;
|
||||
}
|
||||
if (pri->subchannel) {
|
||||
/* On GR-303, top bit is always 0 */
|
||||
h->crv[0] &= 0x7f;
|
||||
}
|
||||
} else {
|
||||
/* Unless of course this has no call reference */
|
||||
h->crv[0] = 0;
|
||||
h->crv[1] = 0;
|
||||
}
|
||||
if (pri->subchannel) {
|
||||
/* On GR-303, top bit is always 0 */
|
||||
h->crv[0] &= 0x7f;
|
||||
h->crlen = 1;
|
||||
if (call->cr || call->forceinvert) {
|
||||
h->crv[0] = (((call->cr ^ 0x8000) & 0x8000) >> 8) | (call->cr & 0x7f);
|
||||
} else {
|
||||
/* Unless of course this has no call reference */
|
||||
h->crv[0] = 0;
|
||||
}
|
||||
}
|
||||
mh = (q931_mh *)(h->contents + h->crlen);
|
||||
mh->f = 0;
|
||||
*hb = h;
|
||||
*mhb = mh;
|
||||
*len -= 5;
|
||||
if (h->crlen == 2)
|
||||
*len -= 5;
|
||||
else
|
||||
*len -= 4;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user