From 3071a4da29200e918cedee6cebc3e18c39590fe6 Mon Sep 17 00:00:00 2001 From: Matthew Fredrickson Date: Wed, 21 Nov 2007 21:49:30 +0000 Subject: [PATCH] Add BRI support to libpri git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@486 2fbb986a-6c06-0410-b554-c9c1f0a7f128 --- libpri.h | 2 +- pri.c | 18 ++++++++----- pri_internal.h | 3 ++- pritest.c | 2 +- q921.c | 4 +-- q931.c | 73 +++++++++++++++++++++++++++++++++++--------------- 6 files changed, 68 insertions(+), 34 deletions(-) diff --git a/libpri.h b/libpri.h index ba89053..896791d 100644 --- a/libpri.h +++ b/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); diff --git a/pri.c b/pri.c index a36be62..8422fe6 100644 --- a/pri.c +++ b/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) diff --git a/pri_internal.h b/pri_internal.h index 0c71748..721d1c3 100644 --- a/pri_internal.h +++ b/pri_internal.h @@ -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 diff --git a/pritest.c b/pritest.c index 2abaf86..c7f1105 100644 --- a/pritest.c +++ b/pritest.c @@ -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; diff --git a/q921.c b/q921.c index 1e24b31..4efd1eb 100644 --- a/q921.c +++ b/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; diff --git a/q931.c b/q931.c index 6dff20e..462fe1d 100644 --- a/q931.c +++ b/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; }