diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/digi/pcimac/cm_state.c | 757 |
1 files changed, 757 insertions, 0 deletions
diff --git a/private/ntos/ndis/digi/pcimac/cm_state.c b/private/ntos/ndis/digi/pcimac/cm_state.c new file mode 100644 index 000000000..646feba1c --- /dev/null +++ b/private/ntos/ndis/digi/pcimac/cm_state.c @@ -0,0 +1,757 @@ +/* + * CM_STATE.C - q931 state managment code + */ + +#include <ndis.h> +#include <ndiswan.h> +#include <mytypes.h> +#include <mydefs.h> +#include <disp.h> +#include <util.h> +#include <opcodes.h> +#include <adapter.h> +#include <idd.h> +#include <mtl.h> +#include <cm.h> + +#include <ansihelp.h> + +/* (ans) process incoming connections */ +INT +cm__ans_est_ind(CM_CHAN *chan, IDD_MSG *msg, VOID *idd, USHORT lterm) +{ + USHORT bchan, type, cid; + INT RetCode; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__ans_est_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + cid = HIWORD(msg->bufid); + + /* must not have a channel at this time */ + if ( chan ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: on used channel, ignored!\n")); + + RetCode = CM_E_BADPARAM; + + // + // we need to let the adapter know that we are not processing + // this incoming call indication + // + ignored: + + /* answer channel */ + cm__est_ignore(idd, cid, lterm); + + return(RetCode); + } + + /* extract info out of message, must have bchan/type */ + if ( (cm__get_bchan(msg, &bchan) != CM_E_SUCC) || + (cm__get_type(msg, &type) != CM_E_SUCC) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: bchan or type missing, ignored!\n")); + + RetCode = CM_E_BADPARAM; + goto ignored; + } + + if ( !CM_BCHAN_ASSIGNED(bchan) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: bchan: %d, unassigned, ignored!\n",\ + bchan)); + RetCode = CM_E_BADPARAM; + goto ignored; + } + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: cid: 0x%x, bchan: %d, type: 0x%d\n",\ + cid, bchan, type)); + + /* channel will be answered only if a listening profile exists */ + if ( !cm__find_listen_conn("*", "*", "*", idd) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: not listening profile, ignored!\n")); + RetCode = CM_E_NOSUCH; + goto ignored; + } + + /* allocate a channel out of incoming channel poll */ + if ( !(chan = cm__chan_alloc()) ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: no channel slot, ignored!\n")); + RetCode = CM_E_NOSLOT; + goto ignored; + } + + /* fillup channel structure */ + NdisZeroMemory(chan, sizeof(*chan)); + chan->idd = idd; + chan->lterm = lterm; + chan->bchan = bchan; + chan->type = type; + chan->speed = cm__type2speed(type); + chan->ustate = CM_US_UNDEF; + chan->cid = cid; + chan->timeout = ut_time_now(); + + /* extract caller address, if present */ + if ( cm__get_addr(msg, chan->addr) != CM_E_SUCC ) + __strcpy(chan->addr, "<unknown>"); + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_est_ind: caller address is: %s\n", \ + chan->addr)); + + /* answer channel */ + cm__est_rsp(chan); + + /* return succ */ + return(CM_E_SUCC); +} + +/* (ans) process state indications */ +INT +cm__ans_state_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + D_LOG(D_ENTRY|DIGIQ931, ("cm__ans_state_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* log state change */ + chan->ustate = LOWORD(msg->bufid); + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_state_ind: ustate: %d\n", chan->ustate)); + + /* if changed to U0, has been released */ + if ( !chan->ustate ) + { + cm__bchan_ctrl(chan, 0); + cm__chan_free(chan); + return(CM_E_SUCC); + } + + /* if changed to U10, just got connected, open data path */ + if ( chan->ustate == 10 ) + { + cm__bchan_ctrl(chan, 1); + chan->timeout = ut_time_now(); + return(CM_E_SUCC); + } + + /* else ignore */ + return(CM_E_SUCC); +} + +/* (ans) process data indications */ +INT +cm__ans_data_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM_UUS *uus; + ULONG chan_num, n; + UCHAR cause; + CM *cm; + ULONG CompressionFlag = 0; + IDD_MSG msg1; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__ans_data_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* assign UUS pointer & do some basic checks */ + uus = (CM_UUS*)msg->bufptr; + if ( msg->buflen < CM_UUS_SIZE ) + return(CM_E_BADUUS); + + if ( (uus->pkt_type != CM_PKT_TYPE) || + (uus->prot_desc != CM_PROT_DESC) || + (cm__calc_chksum(uus, CM_UUS_SIZE) != 0) ) + return(CM_E_BADUUS); + + /* channel must be atleast connected */ + if ( chan->ustate < 10 ) + return(CM_E_BADSTATE); + + /* if channel already accepted assoc, accept again (other side lost) */ + if ( chan->ustate == CM_US_UUS_OKED ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: chan_num->ustate: %d\n", chan->ustate)); + accept: + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + cm__tx_uus_pkt(chan, CM_ASSOC_ACK, 0); + return(CM_E_SUCC); + } + + /* record information from uus */ + NdisMoveMemory (chan->DstAddr, uus->src_addr, 6); + + chan->remote_conn_index = uus->conn; + + // + // kill dead man timer for this channel + // + NdisZeroMemory(&msg1, sizeof(IDD_MSG)); + msg1.opcode = Q931_CAN_TU10_RQ; + msg1.bufptr = ut_get_buf(); + msg1.buflen = 0; + msg1.bufid = MAKELONG(0, chan->cid); + + /* send to idd */ + if (idd_send_msg(chan->idd, &msg1, (USHORT)CM_PORT(chan), (VOID*)cm__q931_cmpl_handler, NULL) != IDD_E_SUCC) + ut_free_buf(msg1.bufptr); + + + /* if not last channel, accept */ + chan_num = 0; + cm__chan_foreach(cm__inc_chan_num, chan, &chan_num); + if ( (UCHAR)chan_num < uus->channum ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: chan_num: %d, uus->channum: %d\n", chan_num, uus->channum)); + goto accept; + } + + + /* last channel, find matching connection/profile */ + if ( !(cm = cm__find_listen_conn(uus->lname, uus->rname, chan->addr, chan->idd)) ) + { + /* none found, reject */ + cause = CM_NO_PROF; + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: rejected, cause: %d\n", cause)); + cm__tx_uus_pkt(chan, CM_ASSOC_NACK, cause); + return(CM_E_NOSUCH); + } + + /* matching connection found!, fillin */ + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: matching connection: cm: 0x%lx\n", cm)); + + cm->state = CM_ST_IN_ANS; + cm->StateChangeFlag = TRUE; + cm->was_listen = TRUE; + cm->active_chan_num = chan_num; + cm->remote_conn_index = chan->remote_conn_index; + cm->ConnectionType = CM_DKF; + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + NdisMoveMemory (cm->remote_name, uus->rname, sizeof(cm->remote_name)); + + cm->timeout = cm->rx_last_frame_time = cm->tx_last_frame_time = + ut_time_now(); + + /* accept channel here */ + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + chan->cm = cm; + cm__tx_uus_pkt(chan, CM_ASSOC_ACK, 0); + + + /* collect channels info local vector */ + cm->dprof.chan_num = 0; + cm__chan_foreach(cm__add_chan, chan, cm); + + /* init channel fields */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++) + { + CM_CHAN *chan = cm->dprof.chan_tbl + n; + + chan->ustate = CM_US_CONN; + chan->timeout = ut_time_now(); + chan->num = (USHORT)n; + chan->cm = cm; + chan->active = TRUE; + } + + /* make connection active */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + + // Set compression Flag + if (cm->dprof.HWCompression && (uus->option_0 & UUS_0_COMPRESSION)) + CompressionFlag = 1; + else + CompressionFlag = 0; + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__ans_data_ind: Activating connection for cm: 0x%lx\n", cm)); + return(cm__activate_conn(cm, CompressionFlag)); +} + +/* (org) new cid indicated on outgoing channel */ +INT +cm__org_cid_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM *cm; + USHORT conn_num, chan_num, cid; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_cid_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* extract conn_num/chan_num out of param 3, get cid */ + conn_num = HIBYTE(LOWORD(msg->bufid)); + chan_num = LOBYTE(LOWORD(msg->bufid)); + cid = HIWORD(msg->bufid); + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_cid_ind: conn_num: %d, chan_num: %d, cid: 0x%x\n", conn_num, chan_num, cid)); + +// DbgPrint("cid_ind: conn_num: %d, chan_num: %d, cid: 0x%x\n", +// conn_num, chan_num, cid); + + /* get related connection */ + if ( !(cm = cm__get_conn(conn_num)) ) + { +// DbgPrint("cid_ind: cm__get_conn failed!\n"); + return(CM_E_BADPARAM); + } + + /* get related channel */ + if ( chan_num >= cm->dprof.chan_num ) + { +// DbgPrint("cid_ind: invalid chan_num!\n"); + return(CM_E_BADPARAM); + } + else + chan = cm->dprof.chan_tbl + chan_num; + + /* check channel ustate */ + if ( chan->ustate != CM_US_WAIT_CID ) + { +// DbgPrint("cid_ind: invalid ustate (%d)!\n", chan->ustate); + return(CM_E_BADSTATE); + } + + /* cid == 0, no free slots at idp, simulate state change to 0 */ + if ( !cid ) + { + cm->NoActiveLine = 1; + return(cm__org_state_ind(chan, NULL)); + } + + /* assign params */ + chan->ustate = CM_US_UNDEF; + chan->cid = cid; +// DbgPrint("cid_ind: ustate: %d, cid: 0x%x assigned\n", chan->ustate, chan->cid); + + return(CM_E_SUCC); +} + +/* (org) process state indications */ +INT +cm__org_state_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM *cm; + ULONG n; + USHORT gave_up_num, chan_num; + ULONG CompressionFlag; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_state_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* check for change of state at protocol level */ + if ( !chan ) + { + /* not used for now */ + return(CM_E_NOTIMPL); + } + + /* log change */ + cm = chan->cm; + + chan->ustate = msg ? LOWORD(msg->bufid) : 0; + + D_LOG(DIGIQ931,("cm__org_state_ind: cm 0x%lx, ustate: 0x%x\n", \ + cm, chan->ustate)); + + /* if changed to U0, has been released, may retry connection here */ + if ( !chan->ustate ) + { + /* turn off bchannel */ + cm__bchan_ctrl(chan, 0); + + /* if not in activation, this is a fatal error, disconnect */ + if ( cm->state != CM_ST_IN_ACT ) + { + disc_all: + + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->ustate > 0 ) + cm__disc_rq(chan1); + } + + /* deactivate connection */ + cm__deactivate_conn(cm, 0); + + return(CM_E_SUCC); + } + + /* attampt to retry */ + if ( !cm->dprof.fallback || + (cm->CauseValue == 0x11 || cm->SignalValue == 0x04) || + (cm__get_next_chan(chan) != CM_E_SUCC) ) + { + chan->ustate = CM_US_GAVE_UP; + chan->gave_up = 1; + } + else + { + /* if here, retrying */ + chan->cid = MAKEWORD(chan->num, cm->local_conn_index); + chan->ustate = CM_US_WAIT_CID; + chan->timeout = ut_time_now(); + + cm__est_rq(chan); + } + + /* find out how many channels gave up (or connected) */ + check_chan: + for ( n = gave_up_num = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( cm->dprof.chan_tbl[n].gave_up ) + gave_up_num++; + else if ( cm->dprof.chan_tbl[n].ustate != CM_US_WAIT_CONN ) + break; + + /* if broke out of loop before hitting chan_num, some channels + are still in progress */ + if ( n < cm->dprof.chan_num ) + return(CM_E_SUCC); + + /* if all gave up, give up conn */ + if ( gave_up_num >= cm->dprof.chan_num ) + { + cm__deactivate_conn(cm, 0); + return(CM_E_SUCC); + } + + /* if here, some channels connected and some gave up, continue */ + chan_num = cm->dprof.chan_num - gave_up_num; + + /* if fallback set to no, must match */ + if ( !cm->dprof.fallback && (chan_num != cm->dprof.chan_num) ) + goto disc_all; + + /* connection enters in_sync state */ + cm->state = CM_ST_IN_SYNC; + cm->StateChangeFlag = TRUE; + cm->timeout = ut_time_now(); + + /* compact channel table & renumber */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->gave_up ) + { + NdisMoveMemory(cm->dprof.chan_tbl + n, + cm->dprof.chan_tbl + n + 1, + sizeof(CM_CHAN) * (cm->dprof.chan_num - n - 1)); + cm->dprof.chan_num--; + n--; + } + } + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + cm->dprof.chan_tbl[n].num = (USHORT)n; + + if (cm->ConnectionType == CM_DKF) + { + // + // if this is a uus connnection tx uus frames + // + /* send initial uus_rq on all active channels */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->gave_up ) + continue; + + chan1->timeout = ut_time_now(); + chan1->ustate = CM_US_UUS_SEND; + + cm__tx_uus_pkt(chan1, CM_ASSOC_RQ, 0); + } + } + else + { + // + // if this is a ppp connection mark channels + // as being connected and activate the connection + // + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->gave_up ) + continue; + + chan1->ustate = CM_US_CONN; + chan1->timeout = ut_time_now(); + chan1->remote_conn_index = 1; + } + NdisZeroMemory(cm->DstAddr, sizeof(cm->DstAddr)); + NdisZeroMemory(cm->remote_name, sizeof(cm->remote_name)); + + /* make connection active now */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + CompressionFlag = 0; + + return (cm__activate_conn(cm, CompressionFlag)); + } + + return(CM_E_SUCC); + } + + /* if change state to U10 just connected */ + if ( chan->ustate == 10 ) + { + /* start data transfer on channel */ + cm__bchan_ctrl(chan, 1); + chan->ustate = CM_US_WAIT_CONN; + chan->timeout = ut_time_now(); + + /* see if all channels are connected, continue as a change to U0 */ + goto check_chan; + } +} + +/* (org) process data indications */ +INT +cm__org_data_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + CM_UUS *uus; + CM *cm = chan->cm; + ULONG n, first; + ULONG CompressionFlag; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_data_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + + /* assign UUS pointer & do some basic checks */ + uus = (CM_UUS*)msg->bufptr; + if ( msg->buflen < CM_UUS_SIZE ) + return(CM_E_BADUUS); + if ( (uus->pkt_type != CM_PKT_TYPE) || + (uus->prot_desc != CM_PROT_DESC) || + (cm__calc_chksum(uus, CM_UUS_SIZE) != 0) ) + return(CM_E_BADUUS); + + /* channel must be atleast connected */ + if ( chan->ustate < 10 ) + return(CM_E_BADSTATE); + + /* if is a request, channel is part of a listening conn */ + if ( uus->opcode == CM_ASSOC_RQ ) + { + cm__tx_uus_pkt(chan, CM_ASSOC_ACK, 0); + return(CM_E_SUCC); + } + + /* if nack detected, connection is torn down */ + if ( uus->opcode == CM_ASSOC_NACK ) + { +// disc_all: + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + { + CM_CHAN *chan1 = cm->dprof.chan_tbl + n; + + if ( chan1->ustate > 0 ) + cm__disc_rq(chan1); + } + + /* deactivate connection */ + cm__deactivate_conn(cm, 0); + + return(CM_E_SUCC); + } + + /* if here must be an ack */ + if ( uus->opcode != CM_ASSOC_ACK ) + return(CM_E_BADUUS); + + /* if channel already connected and uus ack'ed - ignore */ + if ( chan->ustate > CM_US_UUS_OKED ) + return(CM_E_SUCC); + + // + // if this flag is set then we originally had a PPP connection + // this means that all of the connection stuff is taken care of and + // we just need to satisfy the remote ends uus requirements. + // there should be only one channel in this case! + // + if (cm->PPPToDKF) + { + chan->ustate = CM_US_CONN; + NdisMoveMemory (chan->DstAddr, uus->src_addr, 6); + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + cm->remote_conn_index = cm->dprof.chan_tbl[0].remote_conn_index; + NdisMoveMemory(cm->remote_name, uus->lname, sizeof(cm->remote_name)); + cm->PPPToDKF = 0; + return(CM_E_SUCC); + } + + /* if here, it is an ack */ + chan->ustate = CM_US_UUS_OKED; + chan->timeout = ut_time_now(); + + NdisMoveMemory (chan->DstAddr, uus->src_addr, 6); + + chan->remote_conn_index = uus->conn; + + /* proceed only if all channels ok'ed */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( !cm->dprof.chan_tbl[n].gave_up && + (cm->dprof.chan_tbl[n].ustate != CM_US_UUS_OKED) ) + return(CM_E_SUCC); + + /* verify all channel got connected to the same eaddr/conn */ + for ( first = 0 ; first < cm->dprof.chan_num ; first++ ) + if ( !cm->dprof.chan_tbl[n].gave_up ) + break; + + /* move all channels to connected state */ + for ( n = 0 ; n < cm->dprof.chan_num ; n++ ) + if ( !cm->dprof.chan_tbl[n].gave_up ) + { + cm->dprof.chan_tbl[n].ustate = CM_US_CONN; + cm->dprof.chan_tbl[n].timeout = ut_time_now(); + } + +// Hack to get around no cm for all channels < the last channel received + NdisMoveMemory(cm->DstAddr, chan->DstAddr, 6); + + /* store some values on a connection level */ + cm->remote_conn_index = cm->dprof.chan_tbl[first].remote_conn_index; + NdisMoveMemory(cm->remote_name, uus->lname, sizeof(cm->remote_name)); + + /* make connection active now */ + cm->state = CM_ST_ACTIVE; + cm->StateChangeFlag = TRUE; + + // Set compression Flag + if (cm->dprof.HWCompression && (uus->option_0 & UUS_0_COMPRESSION)) + CompressionFlag = 1; + else + CompressionFlag = 0; + + return(cm__activate_conn(cm, CompressionFlag)); +} + +/* (org) process element indications */ +INT +cm__org_elem_ind(CM_CHAN *chan, IDD_MSG *msg) +{ + USHORT bchan; + int auto_disc = 0; + CHAR *elem; + + D_LOG(D_ENTRY|DIGIQ931, ("cm__org_elem_ind: entry, chan: 0x%lx, msg: 0x%lx\n", \ + chan, msg)); + + /* must have a valid channel to proceed */ + if ( !chan ) + return(CM_E_SUCC); + + /* check if bchannel reported */ + if ( cm__get_bchan(msg, &bchan) == CM_E_SUCC ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: bchan: %d\n", bchan)); + + if ( !CM_BCHAN_ASSIGNED(chan->bchan) ) + auto_disc |= 1; + else + chan->bchan = bchan; + } + + /* scan for cause */ + if ( (elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x08)) && + (elem[1] >= 2) && !(elem[2] & 0x78) ) + { + static CHAR disc_vals[] = { 0x01, 0x11, 0x12 }; + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: cause: 0x%x\n", elem[3] & 0x7F)); + + if ( __memchr((PUCHAR)disc_vals,(CHAR) elem[3] & 0x7F, (ULONG) sizeof(disc_vals)) ) + { + CM *cm = (CM*)chan->cm; + + cm->CauseValue = elem[3] & 0x7F; + auto_disc |= 2; + } + } + + /* scan for signal */ + if ( (elem = cm__q931_elem(msg->bufptr, msg->buflen, 0x34)) && + (elem[1] == 1) ) + { +// static CHAR signal_vals[] = { 0x00, 0x03, 0x04, 0x0C }; + static CHAR signal_vals[] = { 0x03, 0x04, 0x0C }; + + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: signal: 0x%x\n", elem[2])); + + if ( __memchr(signal_vals, elem[2], sizeof(signal_vals)) ) + { + CM *cm = (CM*)chan->cm; + + cm->SignalValue = elem[2]; + auto_disc |= 4; + } + } + + /* check if need to disconnect */ + if ( auto_disc ) + { + D_LOG(D_ALWAYS|DIGIQ931, ("cm__org_elem_ind: auto_disc: 0x%x\n", auto_disc)); + cm__disc_rq(chan); + } + + return(CM_E_SUCC); +} + +/* calc a checksum for a buffer */ +UCHAR +cm__calc_chksum(VOID *buf_1, INT len) +{ + UCHAR *buf = (UCHAR *)buf_1; + UCHAR sum; + + for ( sum = 0 ; len ; len-- ) + sum += *buf++; + + return(sum); +} + +/* increment a channel count */ +BOOL +cm__inc_chan_num(CM_CHAN *chan, CM_CHAN *ref_chan, ULONG *chan_num) +{ + /* find if this channel is part of same connection as ref_chan */ + if ( memcmp(chan->DstAddr, ref_chan->DstAddr, 6) || + (chan->remote_conn_index != ref_chan->remote_conn_index) ) + return(TRUE); + + /* inrement here */ + *chan_num += 1; + return(TRUE); +} + +/* add a channel to a connection */ +BOOL +cm__add_chan(CM_CHAN *chan, CM_CHAN *ref_chan, CM *cm) +{ + CM_CHAN *chan1; + + /* if connection already full, stop here */ + if ( cm->dprof.chan_num >= cm->active_chan_num ) + return(FALSE); + + /* find if this channel is part of same connection as ref_chan */ + if ( memcmp(chan->DstAddr, ref_chan->DstAddr, 6) || + (chan->remote_conn_index != ref_chan->remote_conn_index) ) + return(TRUE); + + /* add this channel */ + chan1 = &cm->dprof.chan_tbl[cm->dprof.chan_num++]; + *chan1 = *chan; + cm__chan_free(chan); + return(TRUE); +} + + + + |