Index: pri_q921.h =================================================================== --- pri_q921.h (revision 803) +++ pri_q921.h (working copy) @@ -190,6 +190,8 @@ extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len); +extern int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr); + extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr); extern pri_event *q921_dchannel_up(struct pri *pri); Index: libpri.h =================================================================== --- libpri.h (revision 803) +++ libpri.h (working copy) @@ -40,6 +40,7 @@ /* Node types */ #define PRI_NETWORK 1 #define PRI_CPE 2 +#define BRI_NETWORK_PTMP 3 /* Debugging */ #define PRI_DEBUG_Q921_RAW (1 << 0) /* Show raw HDLC frames */ Index: pri.c =================================================================== --- pri.c (revision 803) +++ pri.c (working copy) @@ -50,6 +50,7 @@ case PRI_UNKNOWN: return "Unknown node type"; case PRI_NETWORK: + case BRI_NETWORK_PTMP: return "Network"; case PRI_CPE: return "CPE"; Index: q931.c =================================================================== --- q931.c (revision 803) +++ q931.c (working copy) @@ -271,6 +271,9 @@ case PRI_NETWORK: return "NET"; break; + case BRI_NETWORK_PTMP: + return "NET (PtmP)"; + break; default: return "UNKNOWN"; } @@ -2645,7 +2648,19 @@ static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr) { - q921_transmit_iframe(pri, h, len, cr); + q931_mh *mh; + + if (pri->localtype == BRI_NETWORK_PTMP) { + mh = (q931_mh *)(h->contents + 1); + if (mh->msg == Q931_SETUP) { + q921_transmit_uframe(pri, h, len, cr); + } else { + pri_message(pri, "(q931_xmit) i called iframe with: pri->sapi:%d pri->tei:%d pri->q921_state:%d\n", pri->sapi, pri->tei, pri->q921_state); + q921_transmit_iframe(pri, h, len, cr); + } + } else + q921_transmit_iframe(pri, h, len, cr); + /* The transmit operation might dump the q921 header, so logging the q931 message body after the transmit puts the sections of the message in the right order in the log */ @@ -2688,7 +2703,16 @@ /* Invert the logic */ len = sizeof(buf) - len; - ctrl = call->pri; +pri_message(ctrl, "(1 send_message) ctrl->sapi:%d ctrl->tei:%d ctrl->q921_state:%d\n", ctrl->sapi, ctrl->tei, ctrl->q921_state); + + if (ctrl->localtype == BRI_NETWORK_PTMP) { + if(ctrl->sapi == 63) + ctrl = call->pri; + } else + ctrl = call->pri; + +pri_message(ctrl, "(2 send_message) ctrl->sapi:%d ctrl->tei:%d ctrl->q921_state:%d\n", ctrl->sapi, ctrl->tei, ctrl->q921_state); + if (ctrl->bri && (ctrl->localtype == PRI_CPE)) { /* * Must use the BRI subchannel structure to send with the correct TEI. @@ -2697,6 +2721,7 @@ */ ctrl = ctrl->subchannel; } +pri_message(ctrl, "(3 send_message) ctrl->sapi:%d ctrl->tei:%d ctrl->q921_state:%d\n", ctrl->sapi, ctrl->tei, ctrl->q921_state); if (ctrl) { q931_xmit(ctrl, h, len, 1); } @@ -3011,7 +3036,7 @@ c->progressmask = PRI_PROG_CALLED_NOT_ISDN; } else c->progressmask = 0; - if(pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG) + if(pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP || pri->switchtype == PRI_SWITCH_QSIG) UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE); else UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CONNECT_REQUEST); @@ -3622,7 +3647,7 @@ for (x=0;x that's not an error */ - if (((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) && + if (((pri->localtype != PRI_NETWORK && pri->localtype != BRI_NETWORK_PTMP) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) && ((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) { pri_error(pri, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x])); missingmand++; @@ -3880,7 +3905,7 @@ } if (!(c->ourcallstate == Q931_CALL_STATE_CONNECT_REQUEST) && !(c->ourcallstate == Q931_CALL_STATE_ACTIVE && - (pri->localtype == PRI_NETWORK || pri->switchtype == PRI_SWITCH_QSIG))) { + (pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP || pri->switchtype == PRI_SWITCH_QSIG))) { q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); break; } Index: q921.c =================================================================== --- q921.c (revision 803) +++ q921.c (working copy) @@ -109,7 +109,7 @@ return; Q921_INIT(pri, *f); - f->h.c_r = (pri->localtype == PRI_NETWORK) ? iscommand : !iscommand; + f->h.c_r = (pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP) ? iscommand : !iscommand; f->ft = Q921_FRAMETYPE_U; f->data[0] = 0x0f; /* Management entity */ f->data[1] = (ri >> 8) & 0xff; @@ -154,13 +154,14 @@ h.u.ft = Q921_FRAMETYPE_U; switch(pri->localtype) { case PRI_NETWORK: + case BRI_NETWORK_PTMP: h.h.c_r = 0; break; case PRI_CPE: h.h.c_r = 1; break; default: - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); + pri_error(pri, "(1) Don't know how to U/A on a type %d node\n", pri->localtype); return; } if (pri->debug & (PRI_DEBUG_Q921_STATE | PRI_DEBUG_Q921_DUMP)) @@ -186,13 +187,14 @@ h.u.ft = Q921_FRAMETYPE_U; switch(pri->localtype) { case PRI_NETWORK: + //case BRI_NETWORK_PTMP: h.h.c_r = 1; break; case PRI_CPE: h.h.c_r = 0; break; default: - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); + pri_error(pri, "(2) Don't know how to U/A on a type %d node\n", pri->localtype); return; } if (pri->bri && (pri->state == Q921_AWAITING_ESTABLISH)) { @@ -352,13 +354,14 @@ h.s.p_f = pf; switch(pri->localtype) { case PRI_NETWORK: + case BRI_NETWORK_PTMP: h.h.c_r = 0; break; case PRI_CPE: h.h.c_r = 1; break; default: - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); + pri_error(pri, "(3) Don't know how to U/A on a type %d node\n", pri->localtype); return; } if (pri->debug & PRI_DEBUG_Q921_DUMP) @@ -377,6 +380,7 @@ h.s.p_f = pbit; /* Poll/Final set appropriately */ switch(pri->localtype) { case PRI_NETWORK: + case BRI_NETWORK_PTMP: if (cmd) h.h.c_r = 1; else @@ -389,7 +393,7 @@ h.h.c_r = 1; break; default: - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype); + pri_error(pri, "(4) Don't know how to U/A on a type %d node\n", pri->localtype); return; } pri->v_na = pri->v_r; /* Make a note that we've already acked this */ @@ -482,16 +486,49 @@ } } +int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr) +{ + q921_u *uf; + uf = malloc(sizeof(q921_u) + len + 2); + memset(uf,0,sizeof(q921_u) + len + 2); + + uf->h.sapi = 0; + uf->h.ea1 = 0; + uf->h.ea2 = 1; + uf->h.tei = 127; + uf->m3 = 0; + uf->m2 = 0; + uf->ft = Q921_FRAMETYPE_U; + switch(pri->localtype) { + case BRI_NETWORK_PTMP: + uf->h.c_r = 1; + break; + default: + pri_error(pri, "Don't know how to send U frames on a type %d node\n", pri->localtype); + return -1; + } + memcpy(uf->data,buf,len); + q921_transmit(pri, (q921_h*)&(uf->h), 3+len); + +pri_error(pri, "nt_ptmp: in q921_transmit_uframe and tei is:%d\n", uf->h.tei); + + free(uf); + return 0; +} + int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr) { q921_frame *f, *prev=NULL; - + +pri_error(pri, "(q921_transmit_iframe) pri->sapi:%d pri->tei:%d pri->q921_state:%d\n", pri->sapi, pri->tei, pri->q921_state); + for (f=pri->txqueue; f; f = f->next) prev = f; f = calloc(1, sizeof(q921_frame) + len + 2); if (f) { Q921_INIT(pri, f->h); switch(pri->localtype) { case PRI_NETWORK: + case BRI_NETWORK_PTMP: if (cr) f->h.h.c_r = 1; else @@ -520,6 +557,12 @@ pri->txqueue = f; /* Immediately transmit unless we're in a recovery state, or the window size is too big */ + + if (pri->q921_state == 0) { + pri_error(pri, "pri->q921_state:%d\n", pri->q921_state); + pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED; + pri_error(pri, "So we do fake the value with Q921_LINK_CONNECTION_ESTABLISHED pri->q921_state:%d\n", pri->q921_state); + } if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) { if (pri->windowlen < pri->window) { pri->windowlen++; @@ -658,6 +701,7 @@ case 0: case 2: /* Informational frame */ + /* what is what */ pri_message(pri, "%c N(S): %03d 0: %d\n" "%c N(R): %03d P: %d\n" @@ -815,7 +859,19 @@ pri_event *q921_dchannel_down(struct pri *pri) { + /* Reset counters, reset sabme timer etc */ + if (pri->localtype == BRI_NETWORK_PTMP) { + if (pri->t203_timer) { + pri_schedule_del(pri, pri->t203_timer); + pri->t203_timer = 0; + if (pri->debug & PRI_DEBUG_Q921_STATE) { + pri_message(pri, "Stopping T_203 timer\n"); + } + } + } + + /* Reset counters, reset sabme timer etc */ q921_reset(pri); /* Notify Layer 3 */ @@ -873,6 +929,7 @@ int ri; struct pri *sub; int tei; + if (pri->debug & PRI_DEBUG_Q921_STATE) pri_message(pri, "Received MDL message\n"); if (h->data[0] != 0x0f) { @@ -893,13 +950,26 @@ } /* Go to master */ for (sub = pri; sub->master; sub = sub->master); + //tei = 0; tei = 64; + +//#if 0 /*! \todo XXX Error: The following loop never terminates! */ while(sub->subchannel) { - if(sub->subchannel->tei == tei) + pri_error(pri, "sub->subchannel->tei:%d, tei:%d\n", sub->subchannel->tei, tei); + if(sub->subchannel->tei >= tei) { ++tei; + } + else { + sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1); + break; + } } - sub->subchannel = __pri_new_tei(-1, pri->localtype, pri->switchtype, pri, NULL, NULL, NULL, tei, 1); +//#endif + + if (!sub->subchannel) + 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; @@ -1145,7 +1215,7 @@ /* Acknowledge */ q921_send_ua(pri, h->u.p_f); ev = q921_dchannel_down(pri); - q921_restart(pri, 0); + q921_restart(pri, 0); //NT-PTMP todo return ev; case 3: if (h->u.m2 == 3) { @@ -1207,6 +1277,9 @@ static pri_event *__q921_receive(struct pri *pri, q921_h *h, int len) { + + /* incoming */ + pri_event *ev; /* Discard FCS */ len -= 2; @@ -1224,16 +1297,26 @@ return NULL; #endif - if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) { - /* Check for SAPIs we don't yet handle */ - /* If it's not us, try any subchannels we have */ - if (pri->subchannel) - return q921_receive(pri->subchannel, h, len + 2); - else { - return NULL; + + +pri_error(pri, "q921_receive. h->h.sapi:%d vs. pri->tei:%d and h->h.tei:%d vs. pri->tei:%d pri->q921_state:%d\n", h->h.sapi, pri->sapi, h->h.tei, pri->tei, pri->q921_state); + + //if (pri->localtype != BRI_NETWORK_PTMP) { + if (!((h->h.sapi == pri->sapi) && ((h->h.tei == pri->tei) || (h->h.tei == Q921_TEI_GROUP)))) { + /* Check for SAPIs we don't yet handle */ + /* If it's not us, try any subchannels we have */ + if (pri->subchannel) { + pri->subchannel->tei = h->h.tei; + pri_message(pri, "NT-PTMP -----> using subchannel with SAPI/TEI=%d/%d\n", pri->subchannel->sapi, pri->subchannel->tei); + return q921_receive(pri->subchannel, h, len + 2); + } else { + pri_error(pri, "q921_receive return NULL\n"); + return NULL; + } } + //} - } + if (pri->debug & PRI_DEBUG_Q921_DUMP) pri_message(pri, "Handling message for SAPI/TEI=%d/%d\n", h->h.sapi, h->h.tei); ev = __q921_receive_qualified(pri, h, len); @@ -1260,7 +1343,10 @@ /* Reset our interface */ q921_reset(pri); /* Do the SABME XXX Maybe we should implement T_WAIT? XXX */ - q921_send_sabme(pri, now); + /* NT-PTMP */ + if (pri->localtype != BRI_NETWORK_PTMP) { + q921_send_sabme(pri, now); + } } void q921_start(struct pri *pri, int isCPE) @@ -1270,7 +1356,7 @@ pri->q921_state = Q921_DOWN; if (isCPE) q921_tei_request(pri); - } else { + } else if (pri->localtype != BRI_NETWORK_PTMP) { q921_send_sabme(pri, isCPE); } }