ue_procedures.c 73.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*******************************************************************************

  Eurecom OpenAirInterface
  Copyright(c) 1999 - 2010 Eurecom

  This program is free software; you can redistribute it and/or modify it
  under the terms and conditions of the GNU General Public License,
  version 2, as published by the Free Software Foundation.

  This program is distributed in the hope it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.

  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc.,
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.

  The full GNU General Public License is included in this distribution in
  the file called "COPYING".

  Contact Information
  Openair Admin: openair_admin@eurecom.fr
  Openair Tech : openair_tech@eurecom.fr
  Forums       : http://forums.eurecom.fsr/openairinterface
  Address      : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France

gauthier's avatar
gauthier committed
28
 *******************************************************************************/
29
/*! \file ue_procedures.c
gauthier's avatar
gauthier committed
30
 * \brief procedures related to UE
31 32 33
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \version 1
gauthier's avatar
gauthier committed
34 35
 * \email: navid.nikaein@eurecom.fr
 * @ingroup _mac
36

gauthier's avatar
gauthier committed
37
 */
38

39 40 41 42
#ifdef EXMIMO
#include <pthread.h>
#endif

43 44
#include "extern.h"
#include "defs.h"
45
#include "proto.h"
46
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
47
# include "SIMULATION/PHY_EMULATION/impl_defs.h"
48
#else
Cedric Roux's avatar
Cedric Roux committed
49 50
# include "SCHED/defs.h"
# include "PHY/impl_defs_top.h"
51 52 53 54
#endif
#include "PHY_INTERFACE/defs.h"
#include "PHY_INTERFACE/extern.h"
#include "COMMON/mac_rrc_primitives.h"
Cedric Roux's avatar
Cedric Roux committed
55 56

#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
57 58 59
#include "RRC/LITE/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
Cedric Roux's avatar
Cedric Roux committed
60
#include "UTIL/OPT/opt.h"
61 62
#include "OCG.h"
#include "OCG_extern.h"
Cedric Roux's avatar
Cedric Roux committed
63

64
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
65
# include "SIMULATION/simulation_defs.h"
66
#endif
67
#include "pdcp.h"
68

69 70 71 72
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

73 74
#include "assertions.h"

75 76 77 78 79 80 81
#define DEBUG_HEADER_PARSING 1
#define ENABLE_MAC_PAYLOAD_DEBUG

/*
#ifndef USER_MODE
#define msg debug_msg
#endif
gauthier's avatar
gauthier committed
82
 */
83 84 85 86 87 88 89 90 91 92 93 94
mapping BSR_names[] = {
    {"NONE", 0},
    {"SHORT BSR", 1},
    {"TRUNCATED BSR", 2},
    {"LONG BSR", 3},
    {"PADDING BSR", 4},
    {NULL, -1}
};

extern inline unsigned int taus(void);


gauthier's avatar
gauthier committed
95
void ue_init_mac(module_id_t module_idP){
96
  int i;
gauthier's avatar
gauthier committed
97

98
  // default values as deined in 36.331 sec 9.2.2
gauthier's avatar
gauthier committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
  LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);

  //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity;
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1;
  UE_mac_inst[module_idP].PHR_state = MAC_MainConfig__phr_Config_PR_setup;
  UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
  UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
  UE_mac_inst[module_idP].scheduling_info.ttiBundling=0;
  UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  get_sf_periodicBSRTimer(UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer);
  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  get_sf_retxBSRTimer(UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer);
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db =  get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange);

121
  for (i=0; i < MAX_NUM_LCID; i++){
gauthier's avatar
gauthier committed
122 123 124 125 126 127 128 129
      LOG_D(MAC,"[UE%d] Applying default logical channel config for LCGID %d\n",module_idP,i);
      UE_mac_inst[module_idP].scheduling_info.Bj[i]=-1;
      UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1;
      if (i < DTCH) // initilize all control channels lcgid to 0
        UE_mac_inst[module_idP].scheduling_info.LCGID[i]=0;
      else // initialize all the data channels lcgid to 1
        UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
      UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=0;
130 131 132 133
  }
}

unsigned char *parse_header(unsigned char *mac_header,
gauthier's avatar
gauthier committed
134 135 136 137 138 139
    unsigned char *num_ce,
    unsigned char *num_sdu,
    unsigned char *rx_ces,
    unsigned char *rx_lcids,
    unsigned short *rx_lengths,
    unsigned short tb_length) {
140 141 142 143 144 145 146

  unsigned char not_done=1,num_ces=0,num_sdus=0,lcid, num_sdu_cnt;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length,ce_len=0;

  while (not_done==1) {

gauthier's avatar
gauthier committed
147 148 149
      if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
          //      printf("E=0\n");
          not_done = 0;
150
      }
gauthier's avatar
gauthier committed
151 152 153 154 155 156 157 158 159 160 161 162 163
      lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;
      if (lcid < UE_CONT_RES) {
          //printf("[MAC][UE] header %x.%x.%x\n",mac_header_ptr[0],mac_header_ptr[1],mac_header_ptr[2]);
          if (not_done==0) {// last MAC SDU, length is implicit
              mac_header_ptr++;
              length = tb_length-(mac_header_ptr-mac_header)-ce_len;
              for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++)
                length -= rx_lengths[num_sdu_cnt];
          }
          else {
              if (((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {
                  length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
                  mac_header_ptr += 3;
164
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
165
                  LOG_D(MAC,"[UE] parse long sdu, size %x \n",length);
166
#endif
gauthier's avatar
gauthier committed
167 168 169 170 171 172

              }  else {	//if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
                  length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
                  mac_header_ptr += 2;
              }
          }
173
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
174 175
          LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %d)\n",
              num_sdus,lcid,length,mac_header_ptr-mac_header);
176
#endif
gauthier's avatar
gauthier committed
177 178 179
          rx_lcids[num_sdus] = lcid;
          rx_lengths[num_sdus] = length;
          num_sdus++;
180
      }
gauthier's avatar
gauthier committed
181 182 183 184 185 186 187 188 189 190 191 192 193
      else {  // This is a control element subheader
          if (lcid == SHORT_PADDING) {
              mac_header_ptr++;
          }
          else {
              rx_ces[num_ces] = lcid;
              num_ces++;
              mac_header_ptr ++;
              if (lcid==TIMING_ADV_CMD)
                ce_len++;
              else if (lcid==UE_CONT_RES)
                ce_len+=6;
          }
194
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
195
          LOG_D(MAC,"[UE] ce %d lcid %d (offset now %d)\n",num_ces,lcid,mac_header_ptr-mac_header);
196
#endif
gauthier's avatar
gauthier committed
197
      }
198 199 200 201 202 203 204
  }
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
}

gauthier's avatar
gauthier committed
205
uint32_t ue_get_SR(module_id_t module_idP,frame_t frameP,uint8_t eNB_id,uint16_t rnti, sub_frame_t subframe) {
206 207 208

  // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
  //  int MGL=6;// measurement gap length in ms
gauthier's avatar
gauthier committed
209 210 211
  int MGRP       = 0; // measurement gap repetition period in ms
  int gapOffset  = -1;
  int T          = 0;
212

gauthier's avatar
gauthier committed
213
  DevCheck(module_idP < NB_UE_INST, module_idP, NB_UE_INST, 0);
214

215 216
  // determin the measurement gap
  LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
217
      module_idP,rnti,frameP,subframe,
gauthier's avatar
gauthier committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
      UE_mac_inst[module_idP].scheduling_info.SR_COUNTER,
      (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)),
      UE_mac_inst[module_idP].scheduling_info.SR_pending);

  if (UE_mac_inst[module_idP].measGapConfig !=NULL){
      if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0){
          MGRP= 40;
          gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp0;
      }else if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1){
          MGRP= 80;
          gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp1;
      }else{
          LOG_W(MAC, "Measurement GAP offset is unknown\n");
      }
      T=MGRP/10;
      //check the measurement gap and sr prohibit timer
234
      if ((subframe ==  gapOffset %10) && ((frameP %T) == (floor(gapOffset/10)))
gauthier's avatar
gauthier committed
235 236 237 238
          && (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running =0)){
          UE_mac_inst[module_idP].scheduling_info.SR_pending=1;
          return(0);
      }
239
  }
gauthier's avatar
gauthier committed
240 241 242 243 244 245 246 247 248 249 250 251
  if ((UE_mac_inst[module_idP].scheduling_info.SR_pending==1) &&
      (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER <
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)))
  ){
      UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++;
      // start the sr-prohibittimer : rel 9 and above
      if (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer > 0) { // timer configured
          UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer--;
          UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=1;
      } else
        UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
      LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d send SR_indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
252
          module_idP,rnti,frameP,subframe,
gauthier's avatar
gauthier committed
253 254 255 256 257 258 259
          UE_mac_inst[module_idP].scheduling_info.SR_COUNTER,
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)),
          UE_mac_inst[module_idP].scheduling_info.SR_pending);

      //UE_mac_inst[module_idP].ul_active =1;

      return(1); //instruct phy to signal SR
260 261
  }
  else{
gauthier's avatar
gauthier committed
262 263 264 265 266 267
      // notify RRC to relase PUCCH/SRS
      // clear any configured dl/ul
      // initiate RA
      UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
      UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
      return(0);
268 269 270
  }
}

gauthier's avatar
gauthier committed
271
void ue_send_sdu(module_id_t module_idP,frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index) {
272 273 274 275 276 277

  unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
  unsigned char rx_lcids[NB_RB_MAX];
  unsigned short rx_lengths[NB_RB_MAX];
  unsigned char *tx_sdu;

278
  start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
279 280 281 282 283 284
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);

  LOG_T(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]);

#if defined(USER_MODE) && defined(OAI_EMU)
  if (oai_emulation.info.opt_enabled) {
gauthier's avatar
gauthier committed
285 286
      trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
          UE_mac_inst[module_idP].subframe, 0, 0);
287 288 289 290 291 292
  }
#endif

  payload_ptr = parse_header(sdu,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_len);

#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
293
  LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP,
294
      frameP,eNB_index,num_ce,num_sdu);
295 296 297 298 299 300
#endif

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
  LOG_T(MAC,"[eNB %d] First 32 bytes of DLSCH : \n");
  for (i=0;i<32;i++)
    LOG_T(MAC,"%x.",sdu[i]);
301
  LOG_T(MAC,"\n");
302 303 304
#endif

  for (i=0;i<num_ce;i++) {
gauthier's avatar
gauthier committed
305
      //    printf("ce %d : %d\n",i,rx_ces[i]);
306 307 308
      switch (rx_ces[i]) {
      case UE_CONT_RES:

gauthier's avatar
gauthier committed
309
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n",
310
            module_idP,frameP,payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4],payload_ptr[5]);
gauthier's avatar
gauthier committed
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
        if (UE_mac_inst[module_idP].RA_active == 1) {
            LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n");
            UE_mac_inst[module_idP].RA_active=0;
            // check if RA procedure has finished completely (no contention)
            tx_sdu = &UE_mac_inst[module_idP].CCCH_pdu.payload[3];
            //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits)
            // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or SCH_SUBHEADER_SHORT)
            for (i=0;i<6;i++)
              if (tx_sdu[i] != payload_ptr[i]) {
                  LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP);
                  mac_xface->ra_failed(module_idP,eNB_index);
                  UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
                  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
                  return;
              }
            LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n");
            UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
            mac_xface->ra_succeeded(module_idP,eNB_index);
        }
        payload_ptr+=6;
        break;
332 333
      case TIMING_ADV_CMD:
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
334
        LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]);
335
#endif
gauthier's avatar
gauthier committed
336 337 338
        //mac_xface->process_timing_advance(module_idP,payload_ptr[0]);
        payload_ptr++;
        break;
339 340
      case DRX_CMD:
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
341
        LOG_D(MAC,"[UE] CE %d : UE DRX :",i);
342
#endif
gauthier's avatar
gauthier committed
343 344
        payload_ptr++;
        break;
345 346 347 348
      }
  }
  for (i=0;i<num_sdu;i++) {
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
349
      LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
350
#endif
gauthier's avatar
gauthier committed
351 352
      if (rx_lcids[i] == CCCH) {

353
          LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n",module_idP,frameP, eNB_index, rx_lengths[i]);
354 355

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
gauthier's avatar
gauthier committed
356 357
          int j;
          for (j=0;j<rx_lengths[i];j++)
gauthier's avatar
gauthier committed
358
            LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]);
gauthier's avatar
gauthier committed
359
          LOG_T(MAC,"\n");
360
#endif
gauthier's avatar
gauthier committed
361
          mac_rrc_data_ind(module_idP,
362
              frameP,
gauthier's avatar
gauthier committed
363
              CCCH,
gauthier's avatar
gauthier committed
364
              (uint8_t *)payload_ptr,rx_lengths[i],0,eNB_index,0);
365

gauthier's avatar
gauthier committed
366 367
      }
      else if (rx_lcids[i] == DCCH) {
368
          LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i],eNB_index,rx_lengths[i]);
gauthier's avatar
gauthier committed
369 370
          mac_rlc_data_ind(eNB_index,
              module_idP,
371
              frameP,
gauthier's avatar
gauthier committed
372 373
              ENB_FLAG_NO,
              MBMS_FLAG_NO,
gauthier's avatar
gauthier committed
374 375 376 377 378 379 380
              DCCH,
              (char *)payload_ptr,
              rx_lengths[i],
              1,
              NULL);
      }
      else if (rx_lcids[i] == DCCH1) {
381
          LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i], eNB_index,rx_lengths[i]);
gauthier's avatar
gauthier committed
382 383
          mac_rlc_data_ind(eNB_index,
              module_idP,
384
              frameP,
gauthier's avatar
gauthier committed
385 386
              ENB_FLAG_NO,
              MBMS_FLAG_NO,
gauthier's avatar
gauthier committed
387 388 389 390 391 392 393
              DCCH1,
              (char *)payload_ptr,
              rx_lengths[i],
              1,
              NULL);
      }
      else if (rx_lcids[i] == DTCH) {
394
          LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", module_idP, frameP,rx_lcids[i], eNB_index,rx_lengths[i]);
395 396

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
gauthier's avatar
gauthier committed
397 398 399 400
          int j;
          for (j=0;j<rx_lengths[i];j++)
            LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]);
          LOG_T(MAC,"\n");
401 402
#endif

gauthier's avatar
gauthier committed
403 404
          mac_rlc_data_ind(eNB_index,
              module_idP,
405
              frameP,
gauthier's avatar
gauthier committed
406 407
              ENB_FLAG_NO,
              MBMS_FLAG_NO,
gauthier's avatar
gauthier committed
408 409 410 411 412 413 414
              DTCH,
              (char *)payload_ptr,
              rx_lengths[i],
              1,
              NULL);
      }
      payload_ptr+= rx_lengths[i];
415 416
  }
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
417
  stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
418 419
}

gauthier's avatar
gauthier committed
420
void ue_decode_si(module_id_t module_idP,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len) {
421

422
  start_meas(&UE_mac_inst[module_idP].rx_si);
423 424
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);

425
  LOG_D(MAC,"[UE %d] Frame %d Sending SI to RRC (LCID Id %d,len %d)\n",module_idP,frameP,BCCH,len);
426

gauthier's avatar
gauthier committed
427
  mac_rrc_data_ind(module_idP,
428
      frameP,
gauthier's avatar
gauthier committed
429
      BCCH,
gauthier's avatar
gauthier committed
430
      (uint8_t *)pdu,
gauthier's avatar
gauthier committed
431 432 433 434
      len,
      0,
      eNB_index,
      0);
435
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
436
  stop_meas(&UE_mac_inst[module_idP].rx_si);
437 438 439 440
}

#ifdef Rel10
unsigned char *parse_mch_header(unsigned char *mac_header,
gauthier's avatar
gauthier committed
441 442 443 444
    unsigned char *num_sdu,
    unsigned char *rx_lcids,
    unsigned short *rx_lengths,
    unsigned short tb_length) {
445 446 447 448 449
  unsigned char not_done=1, num_sdus=0, lcid, i;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length;

  while (not_done == 1) {
gauthier's avatar
gauthier committed
450 451
      if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
          not_done = 0;
452
      }
gauthier's avatar
gauthier committed
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
      lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;
      if (lcid < SHORT_PADDING) {// subheader for MSI, MCCH or MTCH
          if (not_done == 0) { // last MAC SDU, length is implicit
              mac_header_ptr++;
              length = tb_length- (mac_header_ptr - mac_header);
              for (i=0; i<num_sdus; i++)
                length -= rx_lengths[i];
          }
          else { // not the last MAC SDU
              if ( ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {// subheader has length of 3octets
                  //	  length = ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L;
                  length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
                  mac_header_ptr += 3;
              }
              else {// subheader has length of 2octets
                  length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
                  mac_header_ptr += 2;
              }
          }
          rx_lcids[num_sdus] = lcid;
          rx_lengths[num_sdus] = length;
          num_sdus++;
      }
      else {// subheader for padding
          //     if (lcid == SHORT_PADDING)
          mac_header_ptr++;
479 480 481 482 483 484 485
      }
  }
  *num_sdu = num_sdus;
  return(mac_header_ptr);
}

// this function is for sending mch_sdu from phy to mac
gauthier's avatar
gauthier committed
486
void ue_send_mch_sdu(module_id_t module_idP, frame_t frameP, uint8_t *sdu, uint16_t sdu_len, uint8_t eNB_index, uint8_t sync_area) {
487 488

  unsigned char num_sdu, i, *payload_ptr;
489
  unsigned char rx_lcids[NB_RB_MAX];
490 491
  unsigned short rx_lengths[NB_RB_MAX];

492
  start_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
493
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN);
494

495
  LOG_D(MAC,"[UE %d] Frame %d : process the mch PDU for sync area %d \n",module_idP,frameP, sync_area);
gauthier's avatar
gauthier committed
496 497
  LOG_D(MAC,"[UE %d] sdu: %x.%x\n", module_idP,sdu[0], sdu[1]);
  LOG_D(MAC,"[UE %d] parse_mch_header, demultiplex\n",module_idP);
498 499

  payload_ptr = parse_mch_header(sdu, &num_sdu, rx_lcids, rx_lengths, sdu_len);
gauthier's avatar
gauthier committed
500
  LOG_D(MAC,"[UE %d] parse_mch_header, found %d sdus\n",module_idP,num_sdu);
501 502

  for (i=0; i<num_sdu; i++) {
gauthier's avatar
gauthier committed
503 504
      if (rx_lcids[i] == MCH_SCHDL_INFO) {
          if (UE_mac_inst[module_idP].mcch_status==1) {
505
              LOG_I(MAC,"[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]);
gauthier's avatar
gauthier committed
506 507 508 509 510
              // ??store necessary scheduling info to ue_mac_inst in order to
              // calculate exact position of interested service (for the complex case has >1 mtch)
              // set msi_status to 1
              UE_mac_inst[module_idP].msi_status = 1;
          }
511
      }
gauthier's avatar
gauthier committed
512
      else if (rx_lcids[i] == MCCH_LCHANID) {
513
          LOG_I(MAC,"[UE %d] Frame %d : SDU %d MCH->MCCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, i, sync_area, eNB_index, rx_lengths[i]);
gauthier's avatar
gauthier committed
514
          mac_rrc_data_ind(module_idP,
515
              frameP,
gauthier's avatar
gauthier committed
516 517
              MCCH,
              payload_ptr, rx_lengths[i], 0, eNB_index, sync_area);
518
      }
gauthier's avatar
gauthier committed
519 520
      else if (rx_lcids[i] == MTCH) {
          if (UE_mac_inst[module_idP].msi_status==1) {
521
              LOG_I(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]);
gauthier's avatar
gauthier committed
522 523

              mac_rlc_data_ind(
524
                  0,
gauthier's avatar
gauthier committed
525
                  module_idP,
526
                  frameP,
gauthier's avatar
gauthier committed
527 528
                  ENB_FLAG_NO,
                  MBMS_FLAG_YES,
529
                  MTCH, /*+ (maxDRB + 3),*/
gauthier's avatar
gauthier committed
530 531 532 533 534 535 536
                  (char *)payload_ptr,
                  rx_lengths[i],
                  1,
                  NULL);

          }
      } else {
537 538 539 540 541 542
          LOG_W(MAC,"[UE %d] Frame %d : unknown sdu %d rx_lcids[%d]=%d mcch status %d eNB %d \n",
              module_idP,
              frameP,
              rx_lengths[i],
              i,
              rx_lcids[i],
gauthier's avatar
gauthier committed
543 544 545 546
              UE_mac_inst[module_idP].mcch_status, eNB_index);
      }

      payload_ptr += rx_lengths[i];
547 548
  }

549
  vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT);
550
  stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
551 552
}

gauthier's avatar
gauthier committed
553
int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index){
gauthier's avatar
gauthier committed
554
  // currently there is one-to-one mapping between sf allocation pattern and sync area
555
  if (mbsfn_sync_area > MAX_MBSFN_AREA){
gauthier's avatar
gauthier committed
556 557
      LOG_W(MAC,"[UE %d] MBSFN synchronization area %d out of range for eNB %d\n ", module_idP, mbsfn_sync_area, eNB_index);
      return -1;
558
  }
gauthier's avatar
gauthier committed
559
  else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL)
560
    return mbsfn_sync_area;
561
  else {
gauthier's avatar
gauthier committed
562 563
      LOG_W(MAC,"[UE %d] MBSFN Subframe Config pattern %d not found \n ", module_idP, mbsfn_sync_area);
      return -1;
564 565
  }
}
566

567
int ue_query_mch(module_id_t module_idP, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active) {
568

winckel's avatar
winckel committed
569
  int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1;
570
  int mcch_flag=0, mtch_flag=0, msi_flag=0;
gauthier's avatar
gauthier committed
571 572
  int mbsfn_period = 0;// 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
  int mcch_period = 0;// 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
winckel's avatar
winckel committed
573
  int mch_scheduling_period = -1;
574 575 576

  start_meas(&UE_mac_inst[module_idP].ue_query_mch);

gauthier's avatar
gauthier committed
577 578
  if (UE_mac_inst[module_idP].pmch_Config[0])
    mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9);
579

580
  for (i=0;
gauthier's avatar
gauthier committed
581 582 583 584 585 586 587 588 589 590 591
      i< UE_mac_inst[module_idP].num_active_mbsfn_area;
      i++ ){
      // assume, that there is always a mapping
      if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1)
        return -1; // continue;
      ii=0;
      msi_pos=0;
      mbsfn_period = 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
      mcch_period = 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);

      LOG_D(MAC,"[UE %d] Frame %d subframe %d: Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d,mac sched period (%d,%d))\n",
592
          module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area,
gauthier's avatar
gauthier committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
          j,UE_mac_inst[module_idP].num_sf_allocation_pattern,mbsfn_period,mcch_period,
          mch_scheduling_period,UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset);

      // get the real MCS value
      switch (UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) {
      case 0:
        mcch_mcs = 2;
        break;
      case 1:
        mcch_mcs = 7;
        break;
      case 2:
        mcch_mcs = 13;
        break;
      case 3:
        mcch_mcs = 19;
        break;
610
      }
gauthier's avatar
gauthier committed
611

612 613
      if (frameP % mbsfn_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset){ // MBSFN frameP
          if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame){// one-frameP format
gauthier's avatar
gauthier committed
614 615 616

              if (UE_mac_inst[module_idP].pmch_Config[0]) {
                  //  Find the first subframe in this MCH to transmit MSI
617
                  if (frameP % mch_scheduling_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) {
gauthier's avatar
gauthier committed
618 619 620 621 622 623 624 625 626 627 628 629 630 631
                      while (ii == 0) {
                          ii = UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos);
                          msi_pos++;
                      }
                  }
              }

              // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
              switch (subframe) {
              case 1:
                if (mac_xface->lte_frame_parms->frame_type == FDD) {
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) {
                        if (msi_pos == 1)
                          msi_flag = 1;
632
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
633 634 635 636 637 638 639 640 641 642 643 644
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 2:
                if (mac_xface->lte_frame_parms->frame_type == FDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) {
                        if (msi_pos == 2)
                          msi_flag = 1;
645
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
646 647 648 649 650 651 652 653 654 655 656 657
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 3:
                if (mac_xface->lte_frame_parms->frame_type == TDD){// TDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) {
                        if (msi_pos == 1)
                          msi_flag = 1;
658
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
659 660 661 662 663 664 665 666 667
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                else {// FDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) {
                        if (msi_pos == 3)
                          msi_flag = 1;
668
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
669 670 671 672 673 674 675 676 677 678 679 680
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 4:
                if (mac_xface->lte_frame_parms->frame_type == TDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) {
                        if (msi_pos == 2)
                          msi_flag = 1;
681
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
682 683 684 685 686 687 688 689 690 691 692 693
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 6:
                if (mac_xface->lte_frame_parms->frame_type == FDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) {
                        if (msi_pos == 4)
                          msi_flag = 1;
694
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
695 696 697 698 699 700 701 702 703 704 705 706
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 7:
                if (mac_xface->lte_frame_parms->frame_type == TDD){ // TDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) {
                        if (msi_pos == 3)
                          msi_flag = 1;
707
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
708 709 710 711 712 713 714 715 716
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                else {// FDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) {
                        if (msi_pos == 5)
                          msi_flag = 1;
717
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
718 719 720 721 722 723 724 725 726 727 728 729
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 8:
                if (mac_xface->lte_frame_parms->frame_type == TDD){ //TDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) {
                        if (msi_pos == 4)
                          msi_flag = 1;
730
                        if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
731 732 733 734 735 736 737 738 739
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                else{ // FDD
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) {
                        if (msi_pos == 6)
                          msi_flag = 1;
740
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
741 742 743 744 745 746 747 748 749 750 751 752
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;

              case 9:
                if (mac_xface->lte_frame_parms->frame_type == TDD){
                    if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) {
                        if (msi_pos == 5)
                          msi_flag = 1;
753
                        if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
gauthier's avatar
gauthier committed
754 755 756 757 758 759 760 761 762 763
                            ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) )
                          mcch_flag = 1;
                        mtch_flag = 1;
                    }
                }
                break;
              }// end switch
              // sf allocation is non-overlapping
              if ((msi_flag==1) || (mcch_flag==1) || (mtch_flag==1)){
                  LOG_D(MAC,"[UE %d] Frame %d Subframe %d: sync area %d SF alloc %d: msi flag %d, mcch flag %d, mtch flag %d\n",
764
                      module_idP, frameP, subframe,i,j,msi_flag,mcch_flag,mtch_flag);
gauthier's avatar
gauthier committed
765 766 767 768 769

                  *sync_area=i;
                  break;
              }
          }
770
          else {// four-frameP format
gauthier's avatar
gauthier committed
771
          }
772 773
      }
  } // end of for
gauthier's avatar
gauthier committed
774

775
  stop_meas(&UE_mac_inst[module_idP].ue_query_mch);
776

777 778 779
  if ( (mcch_flag==1))// || (msi_flag==1))
    *mcch_active=1;

gauthier's avatar
gauthier committed
780 781 782 783
  if ( (mcch_flag==1) || ((msi_flag==1) && (UE_mac_inst[module_idP].mcch_status==1)) ){
      return mcch_mcs;
  } else if ((mtch_flag==1) && (UE_mac_inst[module_idP].msi_status==1))
    return UE_mac_inst[module_idP].pmch_Config[0]->dataMCS_r9;
784
  else
785 786 787 788 789
    return -1;
}

#endif

gauthier's avatar
gauthier committed
790 791 792 793 794
unsigned char generate_ulsch_header(uint8_t *mac_header,
    uint8_t num_sdus,
    uint8_t short_padding,
    uint16_t *sdu_lengths,
    uint8_t *sdu_lcids,
gauthier's avatar
gauthier committed
795
    POWER_HEADROOM_CMD *power_headroom,
gauthier's avatar
gauthier committed
796
    uint16_t *crnti,
gauthier's avatar
gauthier committed
797 798 799 800
    BSR_SHORT *truncated_bsr,
    BSR_SHORT *short_bsr,
    BSR_LONG *long_bsr,
    unsigned short post_padding) {
801 802 803 804 805 806 807 808 809 810 811 812 813 814

  SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header;
  unsigned char first_element=0,last_size=0,i;
  unsigned char mac_header_control_elements[16],*ce_ptr;

  LOG_D(MAC,"[UE] Generate ULSCH : num_sdus %d\n",num_sdus);
#ifdef DEBUG_HEADER_PARSING
  for (i=0;i<num_sdus;i++)
    LOG_T(MAC,"[UE] sdu %d : lcid %d length %d",i,sdu_lcids[i],sdu_lengths[i]);
  LOG_T(MAC,"\n");
#endif
  ce_ptr = &mac_header_control_elements[0];

  if ((short_padding == 1) || (short_padding == 2)) {
gauthier's avatar
gauthier committed
815 816 817 818 819
      mac_header_ptr->R    = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = SHORT_PADDING;
      first_element=1;
      last_size=1;
820 821
  }
  if (short_padding == 2) {
gauthier's avatar
gauthier committed
822 823 824 825 826 827
      mac_header_ptr->E = 1;
      mac_header_ptr++;
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = SHORT_PADDING;
      last_size=1;
828 829 830
  }

  if (power_headroom) {
gauthier's avatar
gauthier committed
831 832 833 834 835 836 837 838 839 840 841 842 843 844
      if (first_element>0) {
          mac_header_ptr->E = 1;
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = POWER_HEADROOM;
      last_size=1;
      *((POWER_HEADROOM_CMD *)ce_ptr)=(*power_headroom);
      ce_ptr+=sizeof(POWER_HEADROOM_CMD);
      LOG_D(MAC, "phr header size %d\n",sizeof(POWER_HEADROOM_CMD));
845 846 847 848
  }

  if (crnti) {
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
849
      LOG_D(MAC,"[UE] CRNTI : %x (first_element %d)\n",*crnti,first_element);
850
#endif
gauthier's avatar
gauthier committed
851 852 853 854 855 856 857 858 859 860 861
      if (first_element>0) {
          mac_header_ptr->E = 1;
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
      mac_header_ptr->R    = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = CRNTI;
      last_size=1;
gauthier's avatar
gauthier committed
862 863
      *((uint16_t *)ce_ptr)=(*crnti);
      ce_ptr+=sizeof(uint16_t);
gauthier's avatar
gauthier committed
864
      //    printf("offset %d\n",ce_ptr-mac_header_control_elements);
865 866 867
  }

  if (truncated_bsr) {
gauthier's avatar
gauthier committed
868 869 870
      if (first_element>0) {
          mac_header_ptr->E = 1;
          /*
871 872 873 874
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
gauthier's avatar
gauthier committed
875 876 877 878 879 880
           */
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
881
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
882
      LOG_D(MAC,"[UE] Scheduler Truncated BSR Header\n");
883
#endif
gauthier's avatar
gauthier committed
884 885 886 887 888 889 890 891
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = TRUNCATED_BSR;
      last_size=1;
      *((BSR_TRUNCATED *)ce_ptr)=(*truncated_bsr);
      ce_ptr+=sizeof(BSR_TRUNCATED);

      //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
892 893
  }
  else if (short_bsr) {
gauthier's avatar
gauthier committed
894 895 896
      if (first_element>0) {
          mac_header_ptr->E = 1;
          /*
897 898 899 900
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
gauthier's avatar
gauthier committed
901 902 903 904 905 906
           */
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
907
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
908
      LOG_D(MAC,"[UE] Scheduler SHORT BSR Header\n");
909
#endif
gauthier's avatar
gauthier committed
910 911 912 913 914 915 916 917
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = SHORT_BSR;
      last_size=1;
      *((BSR_SHORT *)ce_ptr)=(*short_bsr);
      ce_ptr+=sizeof(BSR_SHORT);

      //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
918 919
  }
  else if (long_bsr) {
gauthier's avatar
gauthier committed
920 921 922
      if (first_element>0) {
          mac_header_ptr->E = 1;
          /*
923 924 925 926
      printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
	     ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
gauthier's avatar
gauthier committed
927 928 929 930 931 932
           */
          mac_header_ptr++;
      }
      else {
          first_element=1;
      }
933
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
934
      LOG_D(MAC,"[UE] Scheduler Long BSR Header\n");
935
#endif
gauthier's avatar
gauthier committed
936 937 938 939 940 941 942 943 944 945 946 947 948
      mac_header_ptr->R = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = LONG_BSR;
      last_size=1;

      *(ce_ptr)     = (long_bsr->Buffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4);
      *(ce_ptr + 1) = ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr->Buffer_size2 & 0x3C) >> 2);
      *(ce_ptr + 2) = ((long_bsr->Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F);
      /* Padding */
      *(ce_ptr + 3) = 0;
      ce_ptr += BSR_LONG_SIZE;

      //    printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements);
949 950 951 952 953
  }
  //  printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);

  for (i=0;i<num_sdus;i++) {
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
954
      LOG_T(MAC,"[UE] sdu subheader %d (lcid %d, %d bytes)\n",i,sdu_lcids[i],sdu_lengths[i]);
955
#endif
gauthier's avatar
gauthier committed
956 957
      if ((first_element>0)) {
          mac_header_ptr->E = 1;
958
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
959 960 961 962
          LOG_D(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr,
              ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R,
              ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E,
              ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID);
963
#endif
gauthier's avatar
gauthier committed
964 965 966 967 968
          mac_header_ptr+=last_size;
          //      printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr);
      }
      else {
          first_element=1;
969

gauthier's avatar
gauthier committed
970 971 972 973 974 975 976 977
      }
      if (sdu_lengths[i] < 128) {
          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0; // 3
          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E    = 0;
          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F    = 0;
          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
          ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = (unsigned char)sdu_lengths[i];
          last_size=2;
978
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
979 980
          LOG_D(MAC,"[UE] short sdu\n");
          LOG_T(MAC,"[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n",
gauthier's avatar
gauthier committed
981
              ((uint16_t*)mac_header_ptr)[0],
gauthier's avatar
gauthier committed
982 983 984 985 986
              ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R,
              ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E,
              ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID,
              ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F,
              ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L);
987
#endif
gauthier's avatar
gauthier committed
988 989 990 991 992 993 994 995 996 997
      }
      else {
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB    = ((unsigned short) sdu_lengths[i]>>8)&0x7f;
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB    = (unsigned short) sdu_lengths[i]&0xff;
          ((SCH_SUBHEADER_LONG *)mac_header_ptr)->padding  = 0x00;
          last_size=3;
998
#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
999
          LOG_D(MAC,"[UE] long sdu\n");
1000
#endif
gauthier's avatar
gauthier committed
1001
      }
1002 1003
  }
  if (post_padding>0) {// we have lots of padding at the end of the packet
gauthier's avatar
gauthier committed
1004 1005 1006 1007 1008 1009 1010
      mac_header_ptr->E = 1;
      mac_header_ptr+=last_size;
      // add a padding element
      mac_header_ptr->R    = 0;
      mac_header_ptr->E    = 0;
      mac_header_ptr->LCID = SHORT_PADDING;
      mac_header_ptr++;
1011 1012
  }
  else { // no end of packet padding
gauthier's avatar
gauthier committed
1013 1014 1015
      // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
      mac_header_ptr++;
      //mac_header_ptr=last_size; // FIXME: should be ++
1016
  }
gauthier's avatar
gauthier committed
1017

1018
  if ((ce_ptr-mac_header_control_elements) > 0) {
gauthier's avatar
gauthier committed
1019 1020
      memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements);
      mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements);
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
  }
#ifdef DEBUG_HEADER_PARSING
  LOG_T(MAC," [UE %d] header : ", crnti);
  for (i=0;i<((unsigned char*)mac_header_ptr - mac_header);i++)
    LOG_T(MAC,"%2x.",mac_header[i]);
  LOG_T(MAC,"\n");
#endif
  return((unsigned char*)mac_header_ptr - mac_header);

}

gauthier's avatar
gauthier committed
1032
void ue_get_sdu(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint8_t *ulsch_buffer,uint16_t buflen, uint8_t *access_mode) {
1033 1034

  mac_rlc_status_resp_t rlc_status;
gauthier's avatar
gauthier committed
1035 1036
  uint8_t dcch_header_len=0,dcch1_header_len=0,dtch_header_len=0;
  uint8_t dcch_header_len_tmp=0, dtch_header_len_tmp=0;
1037
  uint8_t bsr_header_len=0, bsr_ce_len=0, bsr_len=0;
gauthier's avatar
gauthier committed
1038 1039 1040 1041 1042 1043
  uint8_t phr_header_len=0, phr_ce_len=0,phr_len=0;
  uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uint8_t sdu_lcids[8]    = { 0, 0, 0, 0, 0, 0, 0, 0 };
  uint8_t payload_offset=0,num_sdus=0;
  uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
  uint16_t sdu_length_total=0;
1044 1045 1046 1047 1048 1049 1050
  BSR_SHORT bsr_short;
  BSR_LONG bsr_long;
  BSR_SHORT *bsr_s=&bsr_short;
  BSR_LONG  *bsr_l=&bsr_long;
  POWER_HEADROOM_CMD phr;
  POWER_HEADROOM_CMD *phr_p=&phr;
  unsigned short short_padding=0, post_padding=0;