FreeCalypso > hg > fc-magnetite
view src/g23m-fad/l2r/l2r_dnf.c @ 636:57e67ca2e1cb
pcmdata.c: default +CGMI to "FreeCalypso" and +CGMM to model
The present change has no effect whatsoever on Falconia-made and Openmoko-made
devices on which /pcm/CGMI and /pcm/CGMM files have been programmed in FFS
with sensible ID strings by the respective factories, but what should AT+CGMI
and AT+CGMM queries return when the device is a Huawei GTM900 or Tango modem
that has been converted to FreeCalypso with a firmware change? Before the
present change they would return compiled-in defaults of "<manufacturer>" and
"<model>", respectively; with the present change the firmware will self-identify
as "FreeCalypso GTM900-FC" or "FreeCalypso Tango" on the two respective targets.
This firmware identification will become important if someone incorporates an
FC-converted GTM900 or Tango modem into a ZeroPhone-style smartphone where some
high-level software like ofono will be talking to the modem and will need to
properly identify this modem as FreeCalypso, as opposed to some other AT command
modem flavor with different quirks.
In technical terms, the compiled-in default for the AT+CGMI query (which will
always be overridden by the /pcm/CGMI file in FFS if one is present) is now
"FreeCalypso" in all configs on all targets; the compiled-in default for the
AT+CGMM query (likewise always overridden by /pcm/CGMM if present) is
"GTM900-FC" if CONFIG_TARGET_GTM900 or "Tango" if CONFIG_TARGET_TANGO or the
original default of "<model>" otherwise.
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sun, 19 Jan 2020 20:14:58 +0000 |
| parents | 90eb61ecd093 |
| children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : CSD (8411) | Modul : L2r_dnf.c +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This Modul defines the procedures and functions for | the component L2R of the base station +----------------------------------------------------------------------------- */ #ifndef L2R_DNF_C #define L2R_DNF_C #endif #define ENTITY_L2R /*==== INCLUDES ===================================================*/ #include <string.h> #include "typedefs.h" #include "pconst.cdg" #include "vsi.h" #include "macdef.h" #include "custom.h" #include "gsm.h" #include "cus_l2r.h" #include "cnf_l2r.h" #include "mon_l2r.h" #include "prim.h" #include "pei.h" #include "tok.h" #include "dti.h" /* functionality of the dti library */ #include "cl_ribu.h" #include "l2r.h" /*==== CONST =======================================================*/ /*==== TYPES =======================================================*/ /*==== VAR EXPORT ==================================================*/ /*==== VAR LOCAL ===================================================*/ /*==== FUNCTIONS ===================================================*/ /* +------------------------------------------------------------------------------ | Function : dn_init +------------------------------------------------------------------------------ | Description : initialise the l2r data for the downlink process | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_init(T_DN *ddn) { TRACE_FUNCTION ("dn_init()"); ddn->FlowCtrlUsed = FALSE; ddn->DnFlow = FL_INACTIVE; ddn->UpFlow = FL_INACTIVE; #ifdef L2R_TRACE_FLOW ddn->LastSentFlow = FL_INVALID; #endif ddn->FlowThresh = MAX_DPRIM_RIBU_SIZE / 2; ddn->LastState = 0 << SO_SA_BIT | 0 << SO_SB_BIT; ddn->RiBu.idx.depth = MAX_DPRIM_RIBU_SIZE; INIT_STATE (DN_LL, IW_IDLE); INIT_STATE (DN_UL, IW_IDLE); INIT_STATE (DN, DN_DISCONNECTED); } /* +------------------------------------------------------------------------------ | Function : dn_check_flow +------------------------------------------------------------------------------ | Description : checks flow control staus | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_check_flow(void) { T_DN *ddn = &l2r_data->dn; TRACE_FUNCTION ("dn_check_flow()"); if (!ddn->FlowCtrlUsed) { return; } if (ddn->RiBu.idx.filled >= ddn->FlowThresh) { switch (ddn->DnFlow) { case FL_ACTIVE: return; case FL_INACTIVE: ddn->DnFlow = FL_ACTIVE; break; } } else { switch (ddn->DnFlow) { case FL_ACTIVE: ddn->DnFlow = FL_INACTIVE; break; case FL_INACTIVE: return; } } sig_dn_up_flow (ddn->DnFlow); } /* +------------------------------------------------------------------------------ | Function : dn_next_frame +------------------------------------------------------------------------------ | Description : Local function, which is used by up_copy_data_from_l2r | to advance to the next frame in the primitive. | The variable primDesc of the calling function is updated. | | Parameters : primDesc - | | Return : 1 - | 0 - +------------------------------------------------------------------------------ */ LOCAL UBYTE dn_next_frame(T_P_DPRIM_DESCRIPTOR *primDesc) { T_DN *ddn = &l2r_data->dn; #ifdef _SIMULATION_ TRACE_FUNCTION ("dn_next_frame()"); #endif (*primDesc)->index++; /* next frame */ if ((*primDesc)->index >= (*primDesc)->nFr) { #ifdef _SIMULATION_ TRACE_EVENT ("next primitive"); #endif cl_ribu_read_index(&ddn->RiBu.idx); /* point to next primitive */ if (!ddn->RiBu.idx.filled) /* no primitive is ready */ { #ifdef _SIMULATION_ TRACE_EVENT ("no primitive is ready"); #endif return (0); } *primDesc = ddn->RiBu._primDesc[ddn->RiBu.idx.ri]; /* point to next primitive descriptor */ (*primDesc)->index = 0; } return (1); } /* +------------------------------------------------------------------------------ | Function : dn_copy_data_from_l2r +------------------------------------------------------------------------------ | Description : Copies data from l2r into ring buffer. || Moreover the return value of the calling function | bytesCopied are set | Parameters : buf - | len - | sa - | sb - | flow - | bytesCopied - | | Return : - +------------------------------------------------------------------------------ */ LOCAL U16 dn_copy_data_from_l2r(U8 *buf, U16 len, U8 *sa, U8 *sb, U8 *flow) { T_DN *ddn = &l2r_data->dn; T_P_DPRIM_DESCRIPTOR primDesc; T_P_L2R_FRAME frame; register T_P_UBYTE pFrame; register T_P_UBYTE pBuf; register T_P_UBYTE pStat; USHORT bytesToCopy; USHORT blocklen; UBYTE frameCount; UBYTE statOct; #ifdef _SIMULATION_ TRACE_EVENT ("dn_copy_data_from_l2r()"); #endif ddn->ReportMrgFlow = FALSE; if (!ddn->RiBu.idx.filled) /* don't copy into buffer if no primitive is ready */ { #ifdef _SIMULATION_ TRACE_EVENT ("no primitive ready"); #endif switch (ddn->MrgFlow) { case FL_ACTIVE: *flow = DTI_FLOW_OFF; break; case FL_INACTIVE: *flow = DTI_FLOW_ON; break; } *sa = GET_SO_SA_BIT(ddn->LastState); *sb = GET_SO_SB_BIT(ddn->LastState); return 0; } if (ddn->ULFlow EQ FL_ACTIVE) { len = 0; /* upper layer has raised flow control; don't send data */ } bytesToCopy = len; primDesc = ddn->RiBu._primDesc[ddn->RiBu.idx.ri]; /* point to current primitive descriptor */ if (primDesc->nFr EQ 0) /* skip empty primitive */ { #ifdef _SIMULATION_ TRACE_EVENT ("empty primitive"); #endif switch (ddn->MrgFlow) { case FL_ACTIVE: *flow = DTI_FLOW_OFF; break; case FL_INACTIVE: *flow = DTI_FLOW_ON; break; } *sa = GET_SO_SA_BIT(ddn->LastState); *sb = GET_SO_SB_BIT(ddn->LastState); return 0; } #ifdef _TARGET_ if (primDesc->prim->data_size > DATA_SIZE_SHORT) { frameCount = 1; } else { frameCount = 2; } #else { frameCount = 100; } #endif frame = (*primDesc->dadr)[primDesc->index]; /* dn_copy_data_from_l2r: point to current l2r frame in primitive */ pBuf = buf; /* point to destination buffer */ pFrame = &((*frame)[primDesc->offset]); pStat = &((*frame)[primDesc->off_status]); if (pFrame EQ pStat) { /* current byte is status octet */ ddn->LastState = *pFrame & SO_STATUS_BITS_MASK; } /* merge flow control conditions */ switch (ddn->MrgFlow) { case FL_ACTIVE: *flow = DTI_FLOW_OFF; break; case FL_INACTIVE: *flow = DTI_FLOW_ON; break; } *sa = GET_SO_SA_BIT(ddn->LastState); *sb = GET_SO_SB_BIT(ddn->LastState); /************************************************************************************ * loop until either * - no more data are available or * - status in L2R frame changes or * - buffer for data is full ************************************************************************************/ for (;;) { blocklen = pStat - pFrame; if (blocklen EQ 0) { /* * current byte is status octet; * only in the first pass of the loop, there may be no status octet */ /***************************** * evaluate status bits *****************************/ statOct = *pFrame; if (ddn->LastState NEQ (statOct & SO_STATUS_BITS_MASK)) { /* * Status has changed. * We have to stop, * since only one state can be transmitted to the upper layer. */ primDesc->offset = primDesc->off_status = pFrame - (T_P_UBYTE)frame; #ifdef _SIMULATION_ TRACE_EVENT ("return because of status change"); #endif return len - bytesToCopy; } pFrame++; /************************************ * evaluate address bits ************************************/ statOct &= SO_ADR_MASK; switch (statOct) { case SO_BREAK_ACK: case SO_BREAK_REQ: case SO_END_EMPTY: /* * no more data in this frame */ if (dn_next_frame(&primDesc) EQ 0) /* no more data available */ { primDesc->offset = 0; primDesc->off_status = 0; #ifdef _SIMULATION_ TRACE_EVENT ("return because no more data available"); #endif return len - bytesToCopy; /* this much data could be copied */ } frameCount--; if (frameCount EQ 0) { primDesc->offset = 0; primDesc->off_status = 0; #ifdef _SIMULATION_ TRACE_EVENT ("return because number of frames reached"); #endif return len - bytesToCopy; /* this much data could be copied */ } frame = (*primDesc->dadr)[primDesc->index]; /* dn_copy_data_from_l2r */ pFrame = (T_P_UBYTE)frame; pStat = (T_P_UBYTE)frame; continue; /* continue with next frame */ case SO_END_FULL: pStat = &((*frame)[primDesc->prim->data_size]); blocklen = pStat - pFrame; break; case SO_TWO_OCTET: blocklen = *pFrame++ & SO_ADR_MASK_TWO_OCT; pStat = pFrame + blocklen; break; default: blocklen = statOct; pStat = pFrame + blocklen; break; } } if (bytesToCopy < blocklen) { /*************************************** * There is not enough space in the * buffer to copy the complete block ***************************************/ T_P_UBYTE pEnd = pFrame + bytesToCopy; /* save end mark */ while (pFrame < pEnd) { *pBuf++ = *pFrame++; } if (pFrame >= &((*frame)[primDesc->prim->data_size])) { /* * end of frame reached * actually this case can never occur, * since bytesToCopy < blocklen */ dn_next_frame(&primDesc); primDesc->offset = 0; primDesc->off_status = 0; } else { primDesc->offset = pFrame - (T_P_UBYTE)frame; primDesc->off_status = pStat - (T_P_UBYTE)frame; } #ifdef _SIMULATION_ TRACE_EVENT ("return because buffer is full"); #endif return len; /* this much data could be copied */ } else /* bytesToCopy >= blocklen */ { /*************************************** * Copy the complete block ***************************************/ bytesToCopy -= blocklen; while (pFrame < pStat) { *pBuf++ = *pFrame++; } if (pFrame >= &((*frame)[primDesc->prim->data_size])) /* end of frame reached */ { if (dn_next_frame(&primDesc) EQ 0) /* no more data available */ { #ifdef _SIMULATION_ TRACE_EVENT ("return because no more data available"); #endif return len - bytesToCopy; /* this much data could be copied */ } frameCount--; if (frameCount EQ 0) { primDesc->offset = 0; primDesc->off_status = 0; #ifdef _SIMULATION_ TRACE_EVENT ("return because number of frames reached"); #endif return len - bytesToCopy; /* this much data could be copied */ } frame = (*primDesc->dadr)[primDesc->index]; /* dn_copy_data_from_l2r */ pFrame = (T_P_UBYTE)frame; pStat = (T_P_UBYTE)frame; } if (bytesToCopy EQ 0) { primDesc->offset = pFrame - (T_P_UBYTE)frame; primDesc->off_status = pStat - (T_P_UBYTE)frame; #ifdef _SIMULATION_ TRACE_EVENT ("return because all data are copied"); #endif return len; /* this much data could be copied */ } } /* bytesToCopy >= blocklen */ } /* for (;;) */ } /* +------------------------------------------------------------------------------ | Function : dn_send_data_ind +------------------------------------------------------------------------------ | Description : This procedure copies data from the downlink ring buffer | into a DTI_DATA_IND primitive | and sends this primitive to the relay entity. | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_send_data_ind(void) { T_DN *ddn = &l2r_data->dn; TRACE_FUNCTION ("dn_send_data_ind()"); if (ddn->DtiConnected EQ FALSE) { TRACE_EVENT("DTI not connected, but dn_send_data_ind() called"); return; } { USHORT len = L2R_FRAMES_PER_PRIM_MAX * (RLP_FRAME_SIZE_SHORT - HT_LEN - 1); UBYTE sa; UBYTE sb; UBYTE flow; T_desc2* desc; PALLOC (dti_data_ind, DTI2_DATA_IND); MALLOC (desc, (USHORT)(sizeof(T_desc2) - 1 + len)); desc->len = dn_copy_data_from_l2r ((U8*)&desc->buffer[0], len, &sa, &sb, &flow); desc->size = desc->len; desc->offset = 0; desc->next = 0; dti_data_ind->desc_list2.first = (ULONG)desc; dti_data_ind->desc_list2.list_len = desc->len; dti_data_ind->parameters.st_lines.st_line_sa = sa; dti_data_ind->parameters.st_lines.st_line_sb = sb; dti_data_ind->parameters.st_lines.st_flow = flow; dti_data_ind->parameters.st_lines.st_break_len = DTI_BREAK_OFF; dti_data_ind->parameters.p_id = DTI_PID_UOS; dti_data_ind->link_id = ddn->link_id; #ifdef L2R_TRACE_FLOW if (ddn->LastSentFlow NEQ dti_data_ind->parameters.st_lines.st_flow) { switch (dti_data_ind->parameters.st_lines.st_flow) { case FL_ACTIVE: TRACE_EVENT("DTI downlink: FL_ACTIVE"); break; case FL_INACTIVE: TRACE_EVENT("DTI downlink: FL_INACTIVE"); break; } ddn->LastSentFlow = dti_data_ind->parameters.st_lines.st_flow; } #endif dti_send_data ( l2r_hDTI, L2R_DTI_UP_DEF_INSTANCE, L2R_DTI_UP_INTERFACE, L2R_DTI_UP_CHANNEL, dti_data_ind ); } } /* +------------------------------------------------------------------------------ | Function : dn_scan_break_req +------------------------------------------------------------------------------ | Description : This procedure scans a rlp_data_ind primitive for L2R BREAK | status octets. It returnes the index of the frame following | the last BREAK status octet in the primitive. | Moreover the total number of frames in the primitive | as well as the status bits of the last BREAK are returned. | In addition the x bit of the last status octet is returned. | It is important to search the last BREAK in the primitive, | because the data following a break signal | are used in the case of no data compression. | | Parameters : data_ind - | found | index | frames | emptyfr | sa | sb | flow_brk | flow_gen | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_scan_break_req ( T_P_RLP_DATA_IND data_ind, BOOL *found, T_PRIM_INDEX *index, T_PRIM_INDEX *frames, T_PRIM_INDEX *emptyfr, T_BIT *sa, T_BIT *sb, T_FLOW *flow_brk, T_FLOW *flow_gen ) { T_PRIM_INDEX ind; UBYTE off; UBYTE statOct; UBYTE brkStatOct = (UBYTE)(0 << SO_SA_BIT | 0 << SO_SB_BIT | 0 << SO_X_BIT); UBYTE genStatOct = (UBYTE)(0 << SO_SA_BIT | 0 << SO_SB_BIT | 0 << SO_X_BIT); T_P_L2R_FRAME frame; TRACE_FUNCTION ("dn_scan_break_req()"); *found = FALSE; *frames = data_ind->sdu.l_buf / (8 * data_ind->data_size + HT_LEN); *emptyfr = 0; frame = (T_P_L2R_FRAME)(data_ind->sdu.buf + (data_ind->sdu.o_buf>>3) + HEADER_LEN); off = 0; ind = 0; while (ind < *frames) { statOct = (*frame)[off]; switch (statOct & SO_ADR_MASK) { case SO_BREAK_REQ: *found = TRUE; *index = ind + 1; brkStatOct = statOct; genStatOct = statOct; ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + data_ind->data_size + HT_LEN); off = 0; break; case SO_END_EMPTY: if (off EQ 0) { (*emptyfr)++; } /* fall through!!! */ case SO_BREAK_ACK: case SO_END_FULL: genStatOct = statOct; ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + data_ind->data_size + HT_LEN); off = 0; break; case SO_TWO_OCTET: genStatOct = statOct; off += ((*frame)[off] & SO_ADR_MASK_TWO_OCT) + 2; if (off >= data_ind->data_size) { ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + data_ind->data_size + HT_LEN); off = 0; } break; default: genStatOct = statOct; off += (statOct & SO_ADR_MASK) + 1; if (off >= data_ind->data_size) { ind++; frame = (T_P_L2R_FRAME)((UBYTE*)frame + data_ind->data_size + HT_LEN); off = 0; } break; } } if (*found) { *sa = GET_SO_SA_BIT(brkStatOct); *sb = GET_SO_SB_BIT(brkStatOct); } else { *sa = GET_SO_SA_BIT(genStatOct); *sb = GET_SO_SB_BIT(genStatOct); } if (l2r_data->dn.FlowCtrlUsed) { if (GET_SO_X_BIT (brkStatOct) EQ 0) { *flow_brk = FL_INACTIVE; } else { *flow_brk = FL_ACTIVE; } if (GET_SO_X_BIT (genStatOct) EQ 0) { *flow_gen = FL_INACTIVE; } else { *flow_gen = FL_ACTIVE; } } else { *flow_brk = FL_INACTIVE; *flow_gen = FL_INACTIVE; } } /* +------------------------------------------------------------------------------ | Function : dn_free_prim +------------------------------------------------------------------------------ | Description : | | Parameters : primDesc - | | | Return : +------------------------------------------------------------------------------ */ LOCAL void dn_free_prim(T_P_DPRIM_DESCRIPTOR primDesc) { TRACE_FUNCTION ("dn_free_prim()"); if (primDesc->prim NEQ NULL) { PFREE (primDesc->prim); primDesc->prim = NULL; primDesc->nFr = 0; primDesc->index = 0; primDesc->offset = 0; primDesc->off_status = 0; } } /* +------------------------------------------------------------------------------ | Function : dn_free_all_prims +------------------------------------------------------------------------------ | Description : frees all primititives | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_free_all_prims(void) { T_DN *ddn = &l2r_data->dn; T_PRIM_DESC_RIBU_INDEX n; TRACE_FUNCTION ("dn_free_all_prims()"); for (n = 0; n < ddn->RiBu.idx.depth; n++) { dn_free_prim (ddn->RiBu._primDesc[n]); } } /* +------------------------------------------------------------------------------ | Function : dn_cond_free_prims +------------------------------------------------------------------------------ | Description : frees all primitive if r | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_cond_free_prims(void) { T_DN *ddn = &l2r_data->dn; TRACE_FUNCTION ("dn_cond_free_prims()"); while (ddn->RiBu.free NEQ ddn->RiBu.idx.ri) { dn_free_prim (ddn->RiBu._primDesc[ddn->RiBu.free]); ddn->RiBu.free++; if (ddn->RiBu.free EQ ddn->RiBu.idx.depth) { ddn->RiBu.free = 0; } } } /* +------------------------------------------------------------------------------ | Function : dn_store_prim +------------------------------------------------------------------------------ | Description : | | Parameters : data_ind - | index - | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_store_prim(T_P_RLP_DATA_IND data_ind, T_PRIM_INDEX index) { T_DN *ddn = &l2r_data->dn; T_PRIM_INDEX m; T_P_DPRIM_DESCRIPTOR primDesc; T_PRIM_INDEX frames = data_ind->sdu.l_buf / (8 * data_ind->data_size + HT_LEN); UBYTE *pos = data_ind->sdu.buf + (data_ind->sdu.o_buf>>3) + HEADER_LEN; TRACE_FUNCTION ("dn_store_prim()"); primDesc = ddn->RiBu._primDesc[cl_ribu_write_index(&ddn->RiBu.idx)]; primDesc->prim = data_ind; primDesc->index = index; /* if BREAK then not equal 0 */ primDesc->offset = 0; primDesc->off_status = 0; primDesc->nFr = frames; for (m = 0; m < frames; m++) { (*primDesc->dadr)[m] = (T_P_L2R_FRAME)(pos + m * (data_ind->data_size + HT_LEN)); } dn_check_flow(); if (GET_STATE (DN_UL) EQ IW_WAIT AND ddn->ULFlow EQ FL_INACTIVE AND ddn->DtiConnected) /*jk: data send only when DTI connected*/ { dn_send_data_ind(); SET_STATE (DN_UL, IW_IDLE); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : L2R_DNF | | STATE : code ROUTINE : dn_init_ribu | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void dn_init_ribu(void) { T_DN *ddn = &l2r_data->dn; T_PRIM_DESC_RIBU_INDEX n; T_PRIM_INDEX m; TRACE_FUNCTION ("dn_init_ribu()"); cl_ribu_init(&ddn->RiBu.idx, ddn->RiBu.idx.depth); ddn->RiBu.free = 0; for (n = 0; n < ddn->RiBu.idx.depth; n++) { ddn->RiBu._primDesc[n] = &(ddn->PrimDesc[n]); ddn->PrimDesc[n].nFr = 0; ddn->PrimDesc[n].dadr = (T_P_ADR_VECTOR)&(ddn->AdrVec[n]); /* dn_init_ribu */ ddn->PrimDesc[n].index = 0; ddn->PrimDesc[n].offset = 0; ddn->PrimDesc[n].off_status = 0; ddn->PrimDesc[n].prim = NULL; for (m = 0; m < L2R_FRAMES_PER_PRIM_MAX; m++) { ddn->AdrVec[n][m] = NULL; } } } /* +------------------------------------------------------------------------------ | Function : dn_cond_req_data +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_cond_req_data(void) { T_DN *ddn = &l2r_data->dn; TRACE_FUNCTION ("dn_cond_req_data()"); /* ring buffer full? */ if ((ddn->RiBu.idx.wi + 1) % ddn->RiBu.idx.depth EQ ddn->RiBu.free) { SET_STATE (DN_LL, IW_IDLE); } else { PALLOC (rlp_getdata_req, RLP_GETDATA_REQ); PSENDX (RLP, rlp_getdata_req); SET_STATE (DN_LL, IW_WAIT); } } /* +------------------------------------------------------------------------------ | Function : dn_store_status +------------------------------------------------------------------------------ | Description : | | Parameters : flow - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_store_status(T_FLOW flow) { T_DN *ddn = &l2r_data->dn; TRACE_FUNCTION ("dn_store_status()"); if (flow EQ ddn->LLFlow) { return; } ddn->LLFlow = flow; dn_merge_flow(); sig_dn_up_ll_flow(ddn->LLFlow); } /* +------------------------------------------------------------------------------ | Function : dn_merge_flow +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_merge_flow(void) { T_DN *ddn = &l2r_data->dn; TRACE_FUNCTION ("dn_merge_flow()"); if (ddn->FlowCtrlUsed AND (ddn->UpFlow EQ FL_ACTIVE OR ddn->LLFlow EQ FL_ACTIVE) ) { if (ddn->MrgFlow EQ FL_INACTIVE) { ddn->ReportMrgFlow = TRUE; /* TRACE_EVENT("DN: Merged flow set active"); */ } ddn->MrgFlow = FL_ACTIVE; } else { if (ddn->MrgFlow EQ FL_ACTIVE) { ddn->ReportMrgFlow = TRUE; /* TRACE_EVENT("DN: Merged flow set inactive"); */ } ddn->MrgFlow = FL_INACTIVE; } } /* +------------------------------------------------------------------------------ | Function : dn_cond_report_status +------------------------------------------------------------------------------ | Description : | | Parameters : - | | | Return : - +------------------------------------------------------------------------------ */ GLOBAL void dn_cond_report_status(void) { TRACE_FUNCTION ("dn_cond_report_status()"); if (l2r_data->dn.ReportMrgFlow AND GET_STATE (DN_UL) EQ IW_WAIT) { if (l2r_data->dn.DtiConnected) /*jk: data send only when DTI connected*/ { dn_send_data_ind(); SET_STATE (DN_UL, IW_IDLE); } } }
