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:
Matthew Fredrickson
2007-11-21 21:49:30 +00:00
parent 9857425714
commit 3071a4da29
6 changed files with 68 additions and 34 deletions

View File

@@ -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
View File

@@ -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)

View File

@@ -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

View File

@@ -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
View File

@@ -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
View File

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