mirror of https://github.com/pvnis/srsRAN_4G.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
13684 lines
519 KiB
C++
13684 lines
519 KiB
C++
/*******************************************************************************
|
|
|
|
Copyright 2012-2014 Ben Wojtowicz
|
|
Copyright 2014 Andrew Murphy (SIB13 unpack)
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*******************************************************************************
|
|
|
|
File: liblte_rrc.cc
|
|
|
|
Description: Contains all the implementations for the LTE Radio Resource
|
|
Control Layer library.
|
|
|
|
Revision History
|
|
---------- ------------- --------------------------------------------
|
|
03/24/2012 Ben Wojtowicz Created file.
|
|
04/25/2012 Ben Wojtowicz Added SIB1 parameters, IEs, and messages
|
|
06/02/2012 Ben Wojtowicz Added message and IE packing
|
|
06/09/2012 Ben Wojtowicz Added the number of bits used to SIB1 pack
|
|
08/19/2012 Ben Wojtowicz Added functionality to support SIB2, SIB3,
|
|
SIB4, and SIB8 packing and unpacking
|
|
10/06/2012 Ben Wojtowicz Added more decoding/encoding.
|
|
11/10/2012 Ben Wojtowicz Filled in the N_bits for SI messages
|
|
03/03/2013 Ben Wojtowicz Added carrier_freqs_geran, SIB5, SIB6, SIB7
|
|
and paging packing and unpacking.
|
|
07/21/2013 Ben Wojtowicz Fixed several bugs and moved to the common
|
|
message struct.
|
|
09/16/2013 Ben Wojtowicz Added error checking on sizes passed to
|
|
memcpy.
|
|
03/26/2014 Ben Wojtowicz Added support for RRC Connection Request,
|
|
RRC Connection Reestablishment Request,
|
|
and UL CCCH Messages.
|
|
05/04/2014 Ben Wojtowicz Added support for DL CCCH Messages.
|
|
06/15/2014 Ben Wojtowicz Added support for UL DCCH Messages.
|
|
08/03/2014 Ben Wojtowicz Added more decoding/encoding and using the
|
|
common value_2_bits and bits_2_value
|
|
functions.
|
|
09/19/2014 Andrew Murphy Added SIB13 unpack.
|
|
11/01/2014 Ben Wojtowicz Added more decoding/encoding.
|
|
11/09/2014 Ben Wojtowicz Added SIB13 pack.
|
|
11/29/2014 Ben Wojtowicz Fixed a bug in RRC connection reestablishment
|
|
UE identity.
|
|
|
|
*******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
INCLUDES
|
|
*******************************************************************************/
|
|
|
|
#include "srslte/asn1/liblte_rrc.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
/*******************************************************************************
|
|
DEFINES
|
|
*******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
TYPEDEFS
|
|
*******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
GLOBAL VARIABLES
|
|
*******************************************************************************/
|
|
|
|
LIBLTE_BIT_MSG_STRUCT global_msg;
|
|
|
|
/*******************************************************************************
|
|
HELPERS
|
|
*******************************************************************************/
|
|
|
|
/*********************************************************************
|
|
Functions for external logging
|
|
*********************************************************************/
|
|
static log_handler_t log_handler;
|
|
static void *callback_ctx = NULL;
|
|
|
|
void liblte_rrc_log_register_handler(void *ctx, log_handler_t handler) {
|
|
log_handler = handler;
|
|
callback_ctx = ctx;
|
|
}
|
|
|
|
static void liblte_rrc_log_print(const char *format, ...) {
|
|
va_list args;
|
|
va_start(args, format);
|
|
if (log_handler) {
|
|
char *args_msg = NULL;
|
|
if(vasprintf(&args_msg, format, args) > 0) {
|
|
log_handler(callback_ctx, args_msg);
|
|
}
|
|
if (args_msg) {
|
|
free(args_msg);
|
|
}
|
|
} else {
|
|
vprintf(format, args);
|
|
}
|
|
va_end(args);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Description: Simply consume non-critical extensions for rel > r8
|
|
*********************************************************************/
|
|
void liblte_rrc_consume_noncrit_extension(bool ext, const char *func_name, uint8 **ie_ptr)
|
|
{
|
|
uint32 i=0;
|
|
uint32 elem_flags=0;
|
|
uint32 elem_len=0;
|
|
|
|
if (ext) {
|
|
uint8 n_elems = liblte_bits_2_value(ie_ptr, 7) + 1;
|
|
for(i=0; i<n_elems; i++)
|
|
{
|
|
elem_flags |= (liblte_bits_2_value(ie_ptr, 1) << i);
|
|
}
|
|
for(i=0; i<n_elems; i++)
|
|
{
|
|
if(elem_flags & 0x1)
|
|
{
|
|
if(0 == liblte_bits_2_value(ie_ptr, 1))
|
|
{
|
|
elem_len = liblte_bits_2_value(ie_ptr, 7);
|
|
}else{
|
|
if(0 == liblte_bits_2_value(ie_ptr, 1))
|
|
{
|
|
elem_len = liblte_bits_2_value(ie_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
elem_len = 0;
|
|
}
|
|
}
|
|
liblte_bits_2_value(ie_ptr, 8*elem_len);
|
|
}
|
|
elem_flags = elem_flags >> 1;
|
|
}
|
|
if (func_name) {
|
|
liblte_rrc_log_print("Detected an extension in RRC function: %s\n", func_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
void liblte_rrc_warning_not_handled(bool opt, const char *func_name)
|
|
{
|
|
if (opt) {
|
|
liblte_rrc_log_print("Unhandled feature in RRC function: %s\n\n", func_name?func_name:"Unknown");
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
INFORMATION ELEMENT FUNCTIONS
|
|
*******************************************************************************/
|
|
|
|
/*********************************************************************
|
|
IE Name: MBSFN Notification Config
|
|
|
|
Description: Specifies the MBMS notification related configuration
|
|
parameters, that are applicable for all MBSFN areas
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_notification_config_ie(LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT *mbsfn_notification_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(mbsfn_notification_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(mbsfn_notification_cnfg->repetition_coeff, ie_ptr, 1);
|
|
liblte_value_2_bits(mbsfn_notification_cnfg->offset, ie_ptr, 4);
|
|
liblte_value_2_bits(mbsfn_notification_cnfg->sf_index - 1, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_notification_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MBSFN_NOTIFICATION_CONFIG_STRUCT *mbsfn_notification_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mbsfn_notification_cnfg != NULL)
|
|
{
|
|
mbsfn_notification_cnfg->repetition_coeff = (LIBLTE_RRC_NOTIFICATION_REPETITION_COEFF_R9_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
mbsfn_notification_cnfg->offset = liblte_bits_2_value(ie_ptr, 4);
|
|
mbsfn_notification_cnfg->sf_index = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: MBSFN Area Info List
|
|
|
|
Description: Contains the information required to acquire the MBMS
|
|
control information associated with one or more MBSFN
|
|
areas
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_area_info_ie(LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *mbsfn_area_info,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(mbsfn_area_info != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(mbsfn_area_info->mbsfn_area_id_r9, ie_ptr, 8);
|
|
liblte_value_2_bits(mbsfn_area_info->non_mbsfn_region_length, ie_ptr, 1);
|
|
liblte_value_2_bits(mbsfn_area_info->notification_indicator_r9, ie_ptr, 3);
|
|
liblte_value_2_bits(mbsfn_area_info->mcch_repetition_period_r9, ie_ptr, 2);
|
|
liblte_value_2_bits(mbsfn_area_info->mcch_offset_r9, ie_ptr, 4);
|
|
liblte_value_2_bits(mbsfn_area_info->mcch_modification_period_r9, ie_ptr, 1);
|
|
liblte_value_2_bits(mbsfn_area_info->sf_alloc_info_r9, ie_ptr, 6);
|
|
liblte_value_2_bits(mbsfn_area_info->signalling_mcs_r9, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_area_info_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MBSFN_AREA_INFO_STRUCT *mbsfn_area_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mbsfn_area_info != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
mbsfn_area_info->mbsfn_area_id_r9 = liblte_bits_2_value(ie_ptr, 8);
|
|
mbsfn_area_info->non_mbsfn_region_length = (LIBLTE_RRC_NON_MBSFN_REGION_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
mbsfn_area_info->notification_indicator_r9 = liblte_bits_2_value(ie_ptr, 3);
|
|
mbsfn_area_info->mcch_repetition_period_r9 = (LIBLTE_RRC_MCCH_REPETITION_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
mbsfn_area_info->mcch_offset_r9 = liblte_bits_2_value(ie_ptr, 4);
|
|
mbsfn_area_info->mcch_modification_period_r9 = (LIBLTE_RRC_MCCH_MODIFICATION_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
mbsfn_area_info->sf_alloc_info_r9 = liblte_bits_2_value(ie_ptr, 6);
|
|
mbsfn_area_info->signalling_mcs_r9 = (LIBLTE_RRC_MCCH_SIGNALLING_MCS_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: MBSFN Subframe Config
|
|
|
|
Description: Defines subframes that are reserved for MBSFN in
|
|
downlink
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.7
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mbsfn_subframe_config_ie(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *mbsfn_subfr_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(mbsfn_subfr_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(mbsfn_subfr_cnfg->radio_fr_alloc_period, ie_ptr, 3);
|
|
liblte_value_2_bits(mbsfn_subfr_cnfg->radio_fr_alloc_offset, ie_ptr, 3);
|
|
liblte_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc_num_frames, ie_ptr, 1);
|
|
if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == mbsfn_subfr_cnfg->subfr_alloc_num_frames)
|
|
{
|
|
liblte_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc, ie_ptr, 6);
|
|
}else{
|
|
liblte_value_2_bits(mbsfn_subfr_cnfg->subfr_alloc, ie_ptr, 24);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mbsfn_subframe_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT *mbsfn_subfr_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mbsfn_subfr_cnfg != NULL)
|
|
{
|
|
mbsfn_subfr_cnfg->radio_fr_alloc_period = (LIBLTE_RRC_RADIO_FRAME_ALLOCATION_PERIOD_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
mbsfn_subfr_cnfg->radio_fr_alloc_offset = liblte_bits_2_value(ie_ptr, 3);
|
|
mbsfn_subfr_cnfg->subfr_alloc_num_frames = (LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_SUBFRAME_ALLOCATION_NUM_FRAMES_ONE == mbsfn_subfr_cnfg->subfr_alloc_num_frames)
|
|
{
|
|
mbsfn_subfr_cnfg->subfr_alloc = liblte_bits_2_value(ie_ptr, 6);
|
|
}else{
|
|
mbsfn_subfr_cnfg->subfr_alloc = liblte_bits_2_value(ie_ptr, 24);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PMCH Info List
|
|
|
|
Description: Specifies configuration of all PMCHs of an MBSFN area
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.7
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: C-RNTI
|
|
|
|
Description: Identifies a UE having a RRC connection within a cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_c_rnti_ie(uint16 rnti,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(rnti, ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_c_rnti_ie(uint8 **ie_ptr,
|
|
uint16 *rnti)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rnti != NULL)
|
|
{
|
|
*rnti = liblte_bits_2_value(ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Dedicated Info CDMA2000
|
|
|
|
Description: Transfers UE specific CDMA2000 information between
|
|
the network and the UE
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_cdma2000_ie(LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_cdma2000,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ded_info_cdma2000 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
if(ded_info_cdma2000->N_bytes < 128)
|
|
{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
liblte_value_2_bits(ded_info_cdma2000->N_bytes, ie_ptr, 7);
|
|
}else if(ded_info_cdma2000->N_bytes < 16383){
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
liblte_value_2_bits(ded_info_cdma2000->N_bytes, ie_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
}
|
|
|
|
for(i=0; i<ded_info_cdma2000->N_bytes; i++)
|
|
{
|
|
liblte_value_2_bits(ded_info_cdma2000->msg[i], ie_ptr, 8);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_cdma2000_ie(uint8 **ie_ptr,
|
|
LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_cdma2000)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
ded_info_cdma2000 != NULL)
|
|
{
|
|
if(0 == liblte_bits_2_value(ie_ptr, 1))
|
|
{
|
|
ded_info_cdma2000->N_bytes = liblte_bits_2_value(ie_ptr, 7);
|
|
}else{
|
|
if(0 == liblte_bits_2_value(ie_ptr, 1))
|
|
{
|
|
ded_info_cdma2000->N_bytes = liblte_bits_2_value(ie_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
ded_info_cdma2000->N_bytes = 0;
|
|
}
|
|
}
|
|
|
|
for(i=0; i<ded_info_cdma2000->N_bytes; i++)
|
|
{
|
|
ded_info_cdma2000->msg[i] = liblte_bits_2_value(ie_ptr, 8);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Dedicated Info NAS
|
|
|
|
Description: Transfers UE specific NAS layer information between
|
|
the network and the UE
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_dedicated_info_nas_ie(LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_nas,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ded_info_nas != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
if(ded_info_nas->N_bytes < 128)
|
|
{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
liblte_value_2_bits(ded_info_nas->N_bytes, ie_ptr, 7);
|
|
}else if(ded_info_nas->N_bytes < 16383){
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
liblte_value_2_bits(ded_info_nas->N_bytes, ie_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
}
|
|
|
|
for(i=0; i<ded_info_nas->N_bytes; i++)
|
|
{
|
|
liblte_value_2_bits(ded_info_nas->msg[i], ie_ptr, 8);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_dedicated_info_nas_ie(uint8 **ie_ptr,
|
|
LIBLTE_SIMPLE_BYTE_MSG_STRUCT *ded_info_nas)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
ded_info_nas != NULL)
|
|
{
|
|
if(0 == liblte_bits_2_value(ie_ptr, 1))
|
|
{
|
|
ded_info_nas->N_bytes = liblte_bits_2_value(ie_ptr, 7);
|
|
}else{
|
|
if(0 == liblte_bits_2_value(ie_ptr, 1))
|
|
{
|
|
ded_info_nas->N_bytes = liblte_bits_2_value(ie_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
ded_info_nas->N_bytes = 0;
|
|
}
|
|
}
|
|
|
|
for(i=0; i<ded_info_nas->N_bytes; i++)
|
|
{
|
|
ded_info_nas->msg[i] = liblte_bits_2_value(ie_ptr, 8);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Filter Coefficient
|
|
|
|
Description: Specifies the measurement filtering coefficient
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_filter_coefficient_ie(LIBLTE_RRC_FILTER_COEFFICIENT_ENUM filter_coeff,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(filter_coeff, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_filter_coefficient_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_FILTER_COEFFICIENT_ENUM *filter_coeff)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
filter_coeff != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
*filter_coeff = (LIBLTE_RRC_FILTER_COEFFICIENT_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: MMEC
|
|
|
|
Description: Identifies an MME within the scope of an MME group
|
|
within a PLMN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mmec_ie(uint8 mmec,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(mmec, ie_ptr, 8);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mmec_ie(uint8 **ie_ptr,
|
|
uint8 *mmec)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mmec != NULL)
|
|
{
|
|
*mmec = liblte_bits_2_value(ie_ptr, 8);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Neigh Cell Config
|
|
|
|
Description: Provides the information related to MBSFN and TDD
|
|
UL/DL configuration of neighbor cells
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_neigh_cell_config_ie(uint8 neigh_cell_config,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(neigh_cell_config, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_neigh_cell_config_ie(uint8 **ie_ptr,
|
|
uint8 *neigh_cell_config)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
neigh_cell_config != NULL)
|
|
{
|
|
*neigh_cell_config = liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Other Config
|
|
|
|
Description: Contains configuration related to other configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_other_config_ie(LIBLTE_RRC_OTHER_CONFIG_R9_STRUCT *other_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(other_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(other_cnfg->report_proximity_cnfg_present, ie_ptr, 1);
|
|
|
|
if(true == other_cnfg->report_proximity_cnfg_present)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present, ie_ptr, 1);
|
|
liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present, ie_ptr, 1);
|
|
|
|
if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present)
|
|
{
|
|
liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra, ie_ptr, 1);
|
|
}
|
|
|
|
if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present)
|
|
{
|
|
liblte_value_2_bits(other_cnfg->report_proximity_cnfg.report_proximity_ind_utra, ie_ptr, 1);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_other_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_OTHER_CONFIG_R9_STRUCT *other_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
other_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
other_cnfg->report_proximity_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == other_cnfg->report_proximity_cnfg_present)
|
|
{
|
|
// Optional indicators
|
|
other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present = liblte_bits_2_value(ie_ptr, 1);
|
|
other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra_present)
|
|
{
|
|
other_cnfg->report_proximity_cnfg.report_proximity_ind_eutra = (LIBLTE_RRC_REPORT_PROXIMITY_INDICATION_EUTRA_R9_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
if(true == other_cnfg->report_proximity_cnfg.report_proximity_ind_utra_present)
|
|
{
|
|
other_cnfg->report_proximity_cnfg.report_proximity_ind_utra = (LIBLTE_RRC_REPORT_PROXIMITY_INDICATION_UTRA_R9_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RAND CDMA2000 (1xRTT)
|
|
|
|
Description: Contains a random value, generated by the eNB, to be
|
|
passed to the CDMA2000 upper layers
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rand_cdma2000_1xrtt_ie(uint32 rand,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(rand, ie_ptr, 32);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rand_cdma2000_1xrtt_ie(uint8 **ie_ptr,
|
|
uint32 *rand)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rand != NULL)
|
|
{
|
|
*rand = liblte_bits_2_value(ie_ptr, 32);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RAT Type
|
|
|
|
Description: Indicates the radio access technology (RAT),
|
|
including E-UTRA, of the requested/transferred UE
|
|
capabilities
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rat_type_ie(LIBLTE_RRC_RAT_TYPE_ENUM rat_type,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(rat_type, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rat_type_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RAT_TYPE_ENUM *rat_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rat_type != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
*rat_type = (LIBLTE_RRC_RAT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RRC Transaction Identifier
|
|
|
|
Description: Identifies an RRC procedure along with the message
|
|
type
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_transaction_identifier_ie(uint8 rrc_transaction_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(rrc_transaction_id, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_transaction_identifier_ie(uint8 **ie_ptr,
|
|
uint8 *rrc_transaction_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rrc_transaction_id != NULL)
|
|
{
|
|
*rrc_transaction_id = liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: S-TMSI
|
|
|
|
Description: Contains an S-Temporary Mobile Subscriber Identity,
|
|
a temporary UE identity provided by the EPC which
|
|
uniquely identifies the UE within the tracking area
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_s_tmsi_ie(LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(s_tmsi != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_mmec_ie(s_tmsi->mmec, ie_ptr);
|
|
liblte_value_2_bits(s_tmsi->m_tmsi, ie_ptr, 32);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_s_tmsi_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_S_TMSI_STRUCT *s_tmsi)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
s_tmsi != NULL)
|
|
{
|
|
liblte_rrc_unpack_mmec_ie(ie_ptr, &s_tmsi->mmec);
|
|
s_tmsi->m_tmsi = liblte_bits_2_value(ie_ptr, 32);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: UE Capability RAT Container List
|
|
|
|
Description: Contains list of containers, one for each RAT for
|
|
which UE capabilities are transferred
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: UE EUTRA Capability
|
|
|
|
Description: Conveys the E-UTRA UE Radio Access Capability
|
|
Parameters
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pdcp_params_ie(LIBLTE_RRC_PDCP_PARAMS_STRUCT *pdcp_params,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(pdcp_params != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Max ROHC CTXTS default?
|
|
liblte_value_2_bits(pdcp_params->max_rohc_ctxts_present, ie_ptr, 1);
|
|
|
|
// Supported ROHC Profiles
|
|
for(i=0; i<9; i++)
|
|
{
|
|
liblte_value_2_bits(pdcp_params->supported_rohc_profiles[i], ie_ptr, 1);
|
|
}
|
|
|
|
if(pdcp_params->max_rohc_ctxts_present)
|
|
{
|
|
liblte_value_2_bits(pdcp_params->max_rohc_ctxts, ie_ptr, 4);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdcp_params_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PDCP_PARAMS_STRUCT *pdcp_params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pdcp_params != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Max ROHC CTXTS default?
|
|
pdcp_params->max_rohc_ctxts_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Supported ROHC Profiles
|
|
for(i=0; i<9; i++)
|
|
{
|
|
pdcp_params->supported_rohc_profiles[i] = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
if(pdcp_params->max_rohc_ctxts_present)
|
|
{
|
|
pdcp_params->max_rohc_ctxts = (LIBLTE_RRC_MAX_ROHC_CTXTS_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phy_layer_params_ie(LIBLTE_RRC_PHY_LAYER_PARAMS_STRUCT *params,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(params != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(params->tx_antenna_selection_supported, ie_ptr, 1);
|
|
liblte_value_2_bits(params->specific_ref_sigs_supported, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phy_layer_params_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PHY_LAYER_PARAMS_STRUCT *params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
params != NULL)
|
|
{
|
|
params->tx_antenna_selection_supported = liblte_bits_2_value(ie_ptr, 1);
|
|
params->specific_ref_sigs_supported = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rf_params_ie(LIBLTE_RRC_RF_PARAMS_STRUCT *params,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(params != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(params->N_supported_band_eutras-1, ie_ptr, 6);
|
|
for(i=0; i<params->N_supported_band_eutras; i++)
|
|
{
|
|
liblte_value_2_bits(params->supported_band_eutra[i].band_eutra-1, ie_ptr, 6);
|
|
liblte_value_2_bits(params->supported_band_eutra[i].half_duplex, ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rf_params_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RF_PARAMS_STRUCT *params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
params != NULL)
|
|
{
|
|
params->N_supported_band_eutras = liblte_bits_2_value(ie_ptr, 6) + 1;
|
|
for(i=0; i<params->N_supported_band_eutras; i++)
|
|
{
|
|
params->supported_band_eutra[i].band_eutra = liblte_bits_2_value(ie_ptr, 6) + 1;
|
|
params->supported_band_eutra[i].half_duplex = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_band_info_eutra_ie(LIBLTE_RRC_BAND_INFO_EUTRA_STRUCT *info,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(info != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Option indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(info->N_inter_freq_need_for_gaps-1, ie_ptr, 6);
|
|
for(i=0; i<info->N_inter_freq_need_for_gaps; i++)
|
|
{
|
|
liblte_value_2_bits(info->inter_freq_need_for_gaps[i], ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_info_eutra_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_BAND_INFO_EUTRA_STRUCT *info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
info != NULL)
|
|
{
|
|
// Option indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
info->N_inter_freq_need_for_gaps = liblte_bits_2_value(ie_ptr, 6) + 1;
|
|
for(i=0; i<info->N_inter_freq_need_for_gaps; i++)
|
|
{
|
|
info->inter_freq_need_for_gaps[i] = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_params_ie(LIBLTE_RRC_MEAS_PARAMS_STRUCT *params,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(params != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(params->N_band_list_eutra-1, ie_ptr, 6);
|
|
for(i=0; i<params->N_band_list_eutra; i++)
|
|
{
|
|
liblte_rrc_pack_band_info_eutra_ie(¶ms->band_list_eutra[i], ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_params_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_PARAMS_STRUCT *params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
params != NULL)
|
|
{
|
|
params->N_band_list_eutra = liblte_bits_2_value(ie_ptr, 6) + 1;
|
|
for(i=0; i<params->N_band_list_eutra; i++)
|
|
{
|
|
liblte_rrc_unpack_band_info_eutra_ie(ie_ptr, ¶ms->band_list_eutra[i]);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_inter_rat_params_ie(LIBLTE_RRC_INTER_RAT_PARAMS_STRUCT *params,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(params != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// WARNING: Hardcoding all options to not present
|
|
liblte_value_2_bits(0, ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_inter_rat_params_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_INTER_RAT_PARAMS_STRUCT *params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
params != NULL)
|
|
{
|
|
// WARNING: Hardcoding all options to not present
|
|
params->utra_fdd_present = false;
|
|
params->utra_tdd128_present = false;
|
|
params->utra_tdd384_present = false;
|
|
params->utra_tdd768_present = false;
|
|
params->geran_present = false;
|
|
params->cdma2000_hrpd_present = false;
|
|
params->cdma2000_1xrtt_present = false;
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_eutra_capability_ie(LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *ue_eutra_capability,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(ue_eutra_capability != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Option indicator - featureGroupIndicators
|
|
liblte_value_2_bits(ue_eutra_capability->feature_group_indicator_present, &msg_ptr, 1);
|
|
|
|
// Option indicator - nonCriticalExtension
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Option indicator - access stratum release enum
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
liblte_value_2_bits(ue_eutra_capability->access_stratum_release, &msg_ptr, 3);
|
|
|
|
liblte_value_2_bits(ue_eutra_capability->ue_category - 1, &msg_ptr, 3);
|
|
liblte_rrc_pack_pdcp_params_ie(&ue_eutra_capability->pdcp_params, &msg_ptr);
|
|
liblte_rrc_pack_phy_layer_params_ie(&ue_eutra_capability->phy_params, &msg_ptr);
|
|
liblte_rrc_pack_rf_params_ie(&ue_eutra_capability->rf_params, &msg_ptr);
|
|
liblte_rrc_pack_meas_params_ie(&ue_eutra_capability->meas_params, &msg_ptr);
|
|
if(ue_eutra_capability->feature_group_indicator_present)
|
|
liblte_value_2_bits(ue_eutra_capability->feature_group_indicator, &msg_ptr, 32);
|
|
liblte_rrc_pack_inter_rat_params_ie(&ue_eutra_capability->inter_rat_params, &msg_ptr);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_eutra_capability_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_UE_EUTRA_CAPABILITY_STRUCT *ue_eutra_capability)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ue_eutra_capability != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Option indicator - featureGroupIndicators
|
|
ue_eutra_capability->feature_group_indicator_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Option indicator - nonCriticalExtension
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Option indicator - access stratum release enum
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
ue_eutra_capability->access_stratum_release = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
ue_eutra_capability->ue_category = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
liblte_rrc_unpack_pdcp_params_ie(ie_ptr, &ue_eutra_capability->pdcp_params);
|
|
liblte_rrc_unpack_phy_layer_params_ie(ie_ptr, &ue_eutra_capability->phy_params);
|
|
liblte_rrc_unpack_rf_params_ie(ie_ptr, &ue_eutra_capability->rf_params);
|
|
liblte_rrc_unpack_meas_params_ie(ie_ptr, &ue_eutra_capability->meas_params);
|
|
if(ue_eutra_capability->feature_group_indicator_present)
|
|
ue_eutra_capability->feature_group_indicator = liblte_bits_2_value(ie_ptr, 32);
|
|
liblte_rrc_unpack_inter_rat_params_ie(ie_ptr, &ue_eutra_capability->inter_rat_params);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
IE Name: UE Timers and Constants
|
|
|
|
Description: Contains timers and constants used by the UE in
|
|
either RRC_CONNECTED or RRC_IDLE
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.6
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_timers_and_constants_ie(LIBLTE_RRC_UE_TIMERS_AND_CONSTANTS_STRUCT *ue_timers_and_constants,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ue_timers_and_constants != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(ue_timers_and_constants->t300, ie_ptr, 3);
|
|
liblte_value_2_bits(ue_timers_and_constants->t301, ie_ptr, 3);
|
|
liblte_value_2_bits(ue_timers_and_constants->t310, ie_ptr, 3);
|
|
liblte_value_2_bits(ue_timers_and_constants->n310, ie_ptr, 3);
|
|
liblte_value_2_bits(ue_timers_and_constants->t311, ie_ptr, 3);
|
|
liblte_value_2_bits(ue_timers_and_constants->n311, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_timers_and_constants_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_UE_TIMERS_AND_CONSTANTS_STRUCT *ue_timers_and_constants)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
ue_timers_and_constants != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
ue_timers_and_constants->t300 = (LIBLTE_RRC_T300_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ue_timers_and_constants->t301 = (LIBLTE_RRC_T301_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ue_timers_and_constants->t310 = (LIBLTE_RRC_T310_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ue_timers_and_constants->n310 = (LIBLTE_RRC_N310_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ue_timers_and_constants->t311 = (LIBLTE_RRC_T311_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ue_timers_and_constants->n311 = (LIBLTE_RRC_N311_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Allowed Meas Bandwidth
|
|
|
|
Description: Indicates the maximum allowed measurement bandwidth
|
|
on a carrier frequency as defined by the parameter
|
|
Transmission Bandwidth Configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_allowed_meas_bandwidth_ie(LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM allowed_meas_bw,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(allowed_meas_bw, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_allowed_meas_bandwidth_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM *allowed_meas_bw)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
allowed_meas_bw != NULL)
|
|
{
|
|
*allowed_meas_bw = (LIBLTE_RRC_ALLOWED_MEAS_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Hysteresis
|
|
|
|
Description: Used within the entry and leave condition of an
|
|
event triggered reporting condition
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_hysteresis_ie(uint8 hysteresis,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
// FIXME: Convert from actual value
|
|
liblte_value_2_bits(hysteresis, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_hysteresis_ie(uint8 **ie_ptr,
|
|
uint8 *hysteresis)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
hysteresis != NULL)
|
|
{
|
|
// FIXME: Convert to actual value
|
|
*hysteresis = liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Location Info
|
|
|
|
Description: Transfers location information available at the UE to
|
|
correlate measurements and UE position information
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Config
|
|
|
|
Description: Specifies measurements to be performed by the UE,
|
|
and covers intra-frequency, inter-frequency and
|
|
inter-RAT mobility as well as configuration of
|
|
measurement gaps
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_config_ie(LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(meas_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
if(meas_cnfg->N_meas_obj_to_remove)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(meas_cnfg->meas_obj_to_add_mod_list_present, ie_ptr, 1);
|
|
if(meas_cnfg->N_rep_cnfg_to_remove)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(meas_cnfg->rep_cnfg_to_add_mod_list_present, ie_ptr, 1);
|
|
if(meas_cnfg->N_meas_id_to_remove)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(meas_cnfg->meas_id_to_add_mod_list_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_cnfg->quantity_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_cnfg->meas_gap_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_cnfg->s_meas_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_cnfg->pre_reg_info_hrpd_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_cnfg->speed_state_params_present, ie_ptr, 1);
|
|
|
|
// Meas Object To Remove List
|
|
if(0 != meas_cnfg->N_meas_obj_to_remove)
|
|
{
|
|
liblte_value_2_bits(meas_cnfg->N_meas_obj_to_remove - 1, ie_ptr, 5);
|
|
}
|
|
for(i=0; i<meas_cnfg->N_meas_obj_to_remove; i++)
|
|
{
|
|
liblte_rrc_pack_meas_object_id_ie(meas_cnfg->meas_obj_to_remove_list[i], ie_ptr);
|
|
}
|
|
|
|
// Meas Object To Add Mod List
|
|
if(meas_cnfg->meas_obj_to_add_mod_list_present)
|
|
{
|
|
liblte_rrc_pack_meas_object_to_add_mod_list_ie(&meas_cnfg->meas_obj_to_add_mod_list, ie_ptr);
|
|
}
|
|
|
|
// Report Config To Remove List
|
|
if(0 != meas_cnfg->N_rep_cnfg_to_remove)
|
|
{
|
|
liblte_value_2_bits(meas_cnfg->N_rep_cnfg_to_remove - 1, ie_ptr, 5);
|
|
}
|
|
for(i=0; i<meas_cnfg->N_rep_cnfg_to_remove; i++)
|
|
{
|
|
liblte_rrc_pack_report_config_id_ie(meas_cnfg->rep_cnfg_to_remove_list[i], ie_ptr);
|
|
}
|
|
|
|
// Report Config To Add Mod List
|
|
if(meas_cnfg->rep_cnfg_to_add_mod_list_present)
|
|
{
|
|
liblte_rrc_pack_report_config_to_add_mod_list_ie(&meas_cnfg->rep_cnfg_to_add_mod_list, ie_ptr);
|
|
}
|
|
|
|
// Meas ID To Remove List
|
|
if(0 != meas_cnfg->N_meas_id_to_remove)
|
|
{
|
|
liblte_value_2_bits(meas_cnfg->N_meas_id_to_remove - 1, ie_ptr, 5);
|
|
}
|
|
for(i=0; i<meas_cnfg->N_meas_id_to_remove; i++)
|
|
{
|
|
liblte_rrc_pack_meas_id_ie(meas_cnfg->meas_id_to_remove_list[i], ie_ptr);
|
|
}
|
|
|
|
// Meas ID To Add Mod List
|
|
if(meas_cnfg->meas_id_to_add_mod_list_present)
|
|
{
|
|
liblte_rrc_pack_meas_id_to_add_mod_list_ie(&meas_cnfg->meas_id_to_add_mod_list, ie_ptr);
|
|
}
|
|
|
|
// Quantity Config
|
|
if(meas_cnfg->quantity_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_quantity_config_ie(&meas_cnfg->quantity_cnfg, ie_ptr);
|
|
}
|
|
|
|
// Meas Gap Config
|
|
if(meas_cnfg->meas_gap_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_meas_gap_config_ie(&meas_cnfg->meas_gap_cnfg, ie_ptr);
|
|
}
|
|
|
|
// S Measure
|
|
if(meas_cnfg->s_meas_present)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(meas_cnfg->s_meas, ie_ptr);
|
|
}
|
|
|
|
// Pre Registration Info HRPD
|
|
if(meas_cnfg->pre_reg_info_hrpd_present)
|
|
{
|
|
liblte_rrc_pack_pre_registration_info_hrpd_ie(&meas_cnfg->pre_reg_info_hrpd, ie_ptr);
|
|
}
|
|
|
|
// Speed State Pars
|
|
if(meas_cnfg->speed_state_params_present)
|
|
{
|
|
// Release choice
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
|
|
// Mobility State Parameters
|
|
liblte_rrc_pack_mobility_state_parameters_ie(&meas_cnfg->speed_state_params.mob_state_params, ie_ptr);
|
|
|
|
// Time To Trigger SF
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&meas_cnfg->speed_state_params.time_to_trig_sf, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_CONFIG_STRUCT *meas_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool meas_obj_to_remove_present;
|
|
bool rep_cnfg_to_remove_present;
|
|
bool meas_id_to_remove_present;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
meas_obj_to_remove_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->meas_obj_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rep_cnfg_to_remove_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->rep_cnfg_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_id_to_remove_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->meas_id_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->quantity_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->meas_gap_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->s_meas_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->pre_reg_info_hrpd_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_cnfg->speed_state_params_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Meas Object To Remove List
|
|
if(meas_obj_to_remove_present)
|
|
{
|
|
meas_cnfg->N_meas_obj_to_remove = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_cnfg->N_meas_obj_to_remove; i++)
|
|
{
|
|
liblte_rrc_unpack_meas_object_id_ie(ie_ptr, &meas_cnfg->meas_obj_to_remove_list[i]);
|
|
}
|
|
}else{
|
|
meas_cnfg->N_meas_obj_to_remove = 0;
|
|
}
|
|
|
|
// Meas Object To Add Mod List
|
|
if(meas_cnfg->meas_obj_to_add_mod_list_present)
|
|
{
|
|
liblte_rrc_unpack_meas_object_to_add_mod_list_ie(ie_ptr, &meas_cnfg->meas_obj_to_add_mod_list);
|
|
}
|
|
|
|
// Report Config To Remove List
|
|
if(rep_cnfg_to_remove_present)
|
|
{
|
|
meas_cnfg->N_rep_cnfg_to_remove = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_cnfg->N_rep_cnfg_to_remove; i++)
|
|
{
|
|
liblte_rrc_unpack_report_config_id_ie(ie_ptr, &meas_cnfg->rep_cnfg_to_remove_list[i]);
|
|
}
|
|
}else{
|
|
meas_cnfg->N_rep_cnfg_to_remove = 0;
|
|
}
|
|
|
|
// Report Config To Add Mod List
|
|
if(meas_cnfg->rep_cnfg_to_add_mod_list_present)
|
|
{
|
|
liblte_rrc_unpack_report_config_to_add_mod_list_ie(ie_ptr, &meas_cnfg->rep_cnfg_to_add_mod_list);
|
|
}
|
|
|
|
// Meas ID To Remove List
|
|
if(meas_id_to_remove_present)
|
|
{
|
|
meas_cnfg->N_meas_id_to_remove = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_cnfg->N_meas_id_to_remove; i++)
|
|
{
|
|
liblte_rrc_unpack_meas_id_ie(ie_ptr, &meas_cnfg->meas_id_to_remove_list[i]);
|
|
}
|
|
}else{
|
|
meas_cnfg->N_meas_id_to_remove = 0;
|
|
}
|
|
|
|
// Meas ID To Add Mod List
|
|
if(meas_cnfg->meas_id_to_add_mod_list_present)
|
|
{
|
|
liblte_rrc_unpack_meas_id_to_add_mod_list_ie(ie_ptr, &meas_cnfg->meas_id_to_add_mod_list);
|
|
}
|
|
|
|
// Quantity Config
|
|
if(meas_cnfg->quantity_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_quantity_config_ie(ie_ptr, &meas_cnfg->quantity_cnfg);
|
|
}
|
|
|
|
// Meas Gap Config
|
|
if(meas_cnfg->meas_gap_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_meas_gap_config_ie(ie_ptr, &meas_cnfg->meas_gap_cnfg);
|
|
}
|
|
|
|
// S Measure
|
|
if(meas_cnfg->s_meas_present)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &meas_cnfg->s_meas);
|
|
}
|
|
|
|
// Pre Registration Info HRPD
|
|
if(meas_cnfg->pre_reg_info_hrpd_present)
|
|
{
|
|
liblte_rrc_unpack_pre_registration_info_hrpd_ie(ie_ptr, &meas_cnfg->pre_reg_info_hrpd);
|
|
}
|
|
|
|
// Speed State Pars
|
|
if(meas_cnfg->speed_state_params_present)
|
|
{
|
|
// Release choice
|
|
meas_cnfg->speed_state_params_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(meas_cnfg->speed_state_params_present)
|
|
{
|
|
// Mobility State Parameters
|
|
liblte_rrc_unpack_mobility_state_parameters_ie(ie_ptr, &meas_cnfg->speed_state_params.mob_state_params);
|
|
|
|
// Time To Trigger SF
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &meas_cnfg->speed_state_params.time_to_trig_sf);
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Gap Config
|
|
|
|
Description: Specifies the measurement gap configuration and
|
|
controls setup/release of measurement gaps
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_gap_config_ie(LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT *meas_gap_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(meas_gap_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Release choice
|
|
liblte_value_2_bits(meas_gap_cnfg->setup_present, ie_ptr, 1);
|
|
|
|
if(meas_gap_cnfg->setup_present)
|
|
{
|
|
// Gap Offset Type
|
|
liblte_value_2_bits(meas_gap_cnfg->gap_offset_type, ie_ptr, 1);
|
|
|
|
// Gap Offset
|
|
if(LIBLTE_RRC_GAP_OFFSET_TYPE_GP0 == meas_gap_cnfg->gap_offset_type)
|
|
{
|
|
liblte_value_2_bits(meas_gap_cnfg->gap_offset, ie_ptr, 6);
|
|
}else{
|
|
liblte_value_2_bits(meas_gap_cnfg->gap_offset, ie_ptr, 7);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_gap_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_GAP_CONFIG_STRUCT *meas_gap_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_gap_cnfg != NULL)
|
|
{
|
|
// Release choice
|
|
meas_gap_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(meas_gap_cnfg->setup_present)
|
|
{
|
|
// Gap Offset Type
|
|
meas_gap_cnfg->gap_offset_type = (LIBLTE_RRC_GAP_OFFSET_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Gap Offset
|
|
if(LIBLTE_RRC_GAP_OFFSET_TYPE_GP0 == meas_gap_cnfg->gap_offset_type)
|
|
{
|
|
meas_gap_cnfg->gap_offset = liblte_bits_2_value(ie_ptr, 6);
|
|
}else{
|
|
meas_gap_cnfg->gap_offset = liblte_bits_2_value(ie_ptr, 7);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas ID
|
|
|
|
Description: Identifies a measurement configuration, i.e. linking
|
|
of a measurement object and a reporting configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_ie(uint8 meas_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(meas_id - 1, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_ie(uint8 **ie_ptr,
|
|
uint8 *meas_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_id != NULL)
|
|
{
|
|
*meas_id = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Id To Add Mod List
|
|
|
|
Description: Concerns a list of measurement identities to add or
|
|
modify, with for each entry the meas ID, the
|
|
associated meas object ID and the associated report
|
|
config ID
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_id_to_add_mod_list_ie(LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT *list,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(list != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// List Size
|
|
liblte_value_2_bits(list->N_meas_id - 1, ie_ptr, 5);
|
|
|
|
for(i=0; i<list->N_meas_id; i++)
|
|
{
|
|
// Meas ID
|
|
liblte_rrc_pack_meas_id_ie(list->meas_id_list[i].meas_id, ie_ptr);
|
|
|
|
// Meas Object ID
|
|
liblte_rrc_pack_meas_object_id_ie(list->meas_id_list[i].meas_obj_id, ie_ptr);
|
|
|
|
// Report Config ID
|
|
liblte_rrc_pack_report_config_id_ie(list->meas_id_list[i].rep_cnfg_id, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_id_to_add_mod_list_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_LIST_STRUCT *list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
list != NULL)
|
|
{
|
|
// List Size
|
|
list->N_meas_id = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
for(i=0; i<list->N_meas_id; i++)
|
|
{
|
|
// Meas ID
|
|
liblte_rrc_unpack_meas_id_ie(ie_ptr, &list->meas_id_list[i].meas_id);
|
|
|
|
// Meas Object ID
|
|
liblte_rrc_unpack_meas_object_id_ie(ie_ptr, &list->meas_id_list[i].meas_obj_id);
|
|
|
|
// Report Config ID
|
|
liblte_rrc_unpack_report_config_id_ie(ie_ptr, &list->meas_id_list[i].rep_cnfg_id);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Object CDMA2000
|
|
|
|
Description: Specifies information applicable for inter-RAT
|
|
CDMA2000 neighboring cells
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_cdma2000_ie(LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT *meas_obj_cdma2000,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(meas_obj_cdma2000 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(meas_obj_cdma2000->search_win_size_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_obj_cdma2000->cells_to_remove_list_present, ie_ptr, 1);
|
|
if(0 != meas_obj_cdma2000->N_cells_to_add_mod)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present, ie_ptr, 1);
|
|
|
|
// CDMA2000 Type
|
|
liblte_rrc_pack_cdma2000_type_ie(meas_obj_cdma2000->cdma2000_type, ie_ptr);
|
|
|
|
// Carrier Freq
|
|
liblte_rrc_pack_carrier_freq_cdma2000_ie(&meas_obj_cdma2000->carrier_freq, ie_ptr);
|
|
|
|
// Search Window Size
|
|
if(meas_obj_cdma2000->search_win_size_present)
|
|
{
|
|
liblte_value_2_bits(meas_obj_cdma2000->search_win_size, ie_ptr, 4);
|
|
}
|
|
|
|
// Offset Freq
|
|
liblte_rrc_pack_q_offset_range_inter_rat_ie(meas_obj_cdma2000->offset_freq, ie_ptr);
|
|
|
|
// Cells To Remove List
|
|
if(meas_obj_cdma2000->cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_pack_cell_index_list_ie(&meas_obj_cdma2000->cells_to_remove_list, ie_ptr);
|
|
}
|
|
|
|
// Cells To Add Mod List
|
|
if(0 != meas_obj_cdma2000->N_cells_to_add_mod)
|
|
{
|
|
liblte_value_2_bits(meas_obj_cdma2000->N_cells_to_add_mod - 1, ie_ptr, 5);
|
|
}
|
|
for(i=0; i<meas_obj_cdma2000->N_cells_to_add_mod; i++)
|
|
{
|
|
// Cell Index
|
|
liblte_value_2_bits(meas_obj_cdma2000->cells_to_add_mod_list[i].cell_idx - 1, ie_ptr, 5);
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_cdma2000_ie(meas_obj_cdma2000->cells_to_add_mod_list[i].pci, ie_ptr);
|
|
}
|
|
|
|
// Cell For Which To Report CGI
|
|
if(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_cdma2000_ie(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_cdma2000_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_OBJECT_CDMA2000_STRUCT *meas_obj_cdma2000)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool cells_to_add_mod_present;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_obj_cdma2000 != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
meas_obj_cdma2000->search_win_size_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_cdma2000->cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
cells_to_add_mod_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_cdma2000->cell_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// CDMA2000 Type
|
|
liblte_rrc_unpack_cdma2000_type_ie(ie_ptr, &meas_obj_cdma2000->cdma2000_type);
|
|
|
|
// Carrier Freq
|
|
liblte_rrc_unpack_carrier_freq_cdma2000_ie(ie_ptr, &meas_obj_cdma2000->carrier_freq);
|
|
|
|
// Search Window Size
|
|
if(meas_obj_cdma2000->search_win_size_present)
|
|
{
|
|
meas_obj_cdma2000->search_win_size = liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
// Offset Freq
|
|
liblte_rrc_unpack_q_offset_range_inter_rat_ie(ie_ptr, &meas_obj_cdma2000->offset_freq);
|
|
|
|
// Cells To Remove List
|
|
if(meas_obj_cdma2000->cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_cdma2000->cells_to_remove_list);
|
|
}
|
|
|
|
// Cells To Add Mod List
|
|
if(cells_to_add_mod_present)
|
|
{
|
|
meas_obj_cdma2000->N_cells_to_add_mod = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_obj_cdma2000->N_cells_to_add_mod; i++)
|
|
{
|
|
// Cell Index
|
|
meas_obj_cdma2000->cells_to_add_mod_list[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &meas_obj_cdma2000->cells_to_add_mod_list[i].pci);
|
|
}
|
|
}else{
|
|
meas_obj_cdma2000->N_cells_to_add_mod = 0;
|
|
}
|
|
|
|
// Cell For Which To Report CGI
|
|
if(meas_obj_cdma2000->cell_for_which_to_rep_cgi_present)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &meas_obj_cdma2000->cell_for_which_to_rep_cgi);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Object EUTRA
|
|
|
|
Description: Specifies information applicable for intra-frequency
|
|
or inter-frequency E-UTRA cells
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_eutra_ie(LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *meas_obj_eutra,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(meas_obj_eutra != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(meas_obj_eutra->offset_freq_not_default, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_obj_eutra->cells_to_remove_list_present, ie_ptr, 1);
|
|
if(0 != meas_obj_eutra->N_cells_to_add_mod)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(meas_obj_eutra->black_cells_to_remove_list_present, ie_ptr, 1);
|
|
if(0 != meas_obj_eutra->N_black_cells_to_add_mod)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(meas_obj_eutra->cell_for_which_to_rep_cgi_present, ie_ptr, 1);
|
|
|
|
// Carrier Freq
|
|
liblte_rrc_pack_arfcn_value_eutra_ie(meas_obj_eutra->carrier_freq, ie_ptr);
|
|
|
|
// Allowed Meas Bandwidth
|
|
liblte_rrc_pack_allowed_meas_bandwidth_ie(meas_obj_eutra->allowed_meas_bw, ie_ptr);
|
|
|
|
// Presence Antenna Port 1
|
|
liblte_rrc_pack_presence_antenna_port_1_ie(meas_obj_eutra->presence_ant_port_1, ie_ptr);
|
|
|
|
// Neigh Cell Config
|
|
liblte_rrc_pack_neigh_cell_config_ie(meas_obj_eutra->neigh_cell_cnfg, ie_ptr);
|
|
|
|
// Offset Freq
|
|
if(meas_obj_eutra->offset_freq_not_default)
|
|
{
|
|
liblte_rrc_pack_q_offset_range_ie(meas_obj_eutra->offset_freq, ie_ptr);
|
|
}
|
|
|
|
// Cells To Remove List
|
|
if(meas_obj_eutra->cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_pack_cell_index_list_ie(&meas_obj_eutra->cells_to_remove_list, ie_ptr);
|
|
}
|
|
|
|
// Cells To Add Mod List
|
|
if(0 != meas_obj_eutra->N_cells_to_add_mod)
|
|
{
|
|
liblte_value_2_bits(meas_obj_eutra->N_cells_to_add_mod - 1, ie_ptr, 5);
|
|
}
|
|
for(i=0; i<meas_obj_eutra->N_cells_to_add_mod; i++)
|
|
{
|
|
// Cell Index
|
|
liblte_value_2_bits(meas_obj_eutra->cells_to_add_mod_list[i].cell_idx - 1, ie_ptr, 5);
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_ie(meas_obj_eutra->cells_to_add_mod_list[i].pci, ie_ptr);
|
|
|
|
// Cell Individual Offset
|
|
liblte_rrc_pack_q_offset_range_ie(meas_obj_eutra->cells_to_add_mod_list[i].cell_offset, ie_ptr);
|
|
}
|
|
|
|
// Black Cells To Remove List
|
|
if(meas_obj_eutra->black_cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_pack_cell_index_list_ie(&meas_obj_eutra->black_cells_to_remove_list, ie_ptr);
|
|
}
|
|
|
|
// Black Cells To Add Mod List
|
|
if(0 != meas_obj_eutra->N_black_cells_to_add_mod)
|
|
{
|
|
liblte_value_2_bits(meas_obj_eutra->N_black_cells_to_add_mod - 1, ie_ptr, 5);
|
|
}
|
|
for(i=0; i<meas_obj_eutra->N_black_cells_to_add_mod; i++)
|
|
{
|
|
// Cell Index
|
|
liblte_value_2_bits(meas_obj_eutra->black_cells_to_add_mod_list[i].cell_idx - 1, ie_ptr, 5);
|
|
|
|
// Phys Cell ID Range
|
|
liblte_rrc_pack_phys_cell_id_range_ie(&meas_obj_eutra->black_cells_to_add_mod_list[i].pci_range, ie_ptr);
|
|
}
|
|
|
|
// Cell For Which To Report CGI
|
|
if(meas_obj_eutra->cell_for_which_to_rep_cgi_present)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_ie(meas_obj_eutra->cell_for_which_to_rep_cgi, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_eutra_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_OBJECT_EUTRA_STRUCT *meas_obj_eutra)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool cells_to_add_mod_list_present;
|
|
bool black_cells_to_add_mod_list_present;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_obj_eutra != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
meas_obj_eutra->offset_freq_not_default = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_eutra->cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
cells_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_eutra->black_cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
black_cells_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_eutra->cell_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Carrier Freq
|
|
liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &meas_obj_eutra->carrier_freq);
|
|
|
|
// Allowed Meas Bandwidth
|
|
liblte_rrc_unpack_allowed_meas_bandwidth_ie(ie_ptr, &meas_obj_eutra->allowed_meas_bw);
|
|
|
|
// Presence Antenna Port 1
|
|
liblte_rrc_unpack_presence_antenna_port_1_ie(ie_ptr, &meas_obj_eutra->presence_ant_port_1);
|
|
|
|
// Neigh Cell Config
|
|
liblte_rrc_unpack_neigh_cell_config_ie(ie_ptr, &meas_obj_eutra->neigh_cell_cnfg);
|
|
|
|
// Offset Freq
|
|
if(meas_obj_eutra->offset_freq_not_default)
|
|
{
|
|
liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &meas_obj_eutra->offset_freq);
|
|
}
|
|
|
|
// Cells To Remove List
|
|
if(meas_obj_eutra->cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_eutra->cells_to_remove_list);
|
|
}
|
|
|
|
// Cells To Add Mod List
|
|
if(cells_to_add_mod_list_present)
|
|
{
|
|
meas_obj_eutra->N_cells_to_add_mod = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_obj_eutra->N_cells_to_add_mod; i++)
|
|
{
|
|
// Cell Index
|
|
meas_obj_eutra->cells_to_add_mod_list[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_obj_eutra->cells_to_add_mod_list[i].pci);
|
|
|
|
// Cell Individual Offset
|
|
liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &meas_obj_eutra->cells_to_add_mod_list[i].cell_offset);
|
|
}
|
|
}else{
|
|
meas_obj_eutra->N_cells_to_add_mod = 0;
|
|
}
|
|
|
|
// Black Cells To Remove List
|
|
if(meas_obj_eutra->black_cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_eutra->black_cells_to_remove_list);
|
|
}
|
|
|
|
// Black Cells To Add Mod List
|
|
if(black_cells_to_add_mod_list_present)
|
|
{
|
|
meas_obj_eutra->N_black_cells_to_add_mod = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_obj_eutra->N_black_cells_to_add_mod; i++)
|
|
{
|
|
// Cell Index
|
|
meas_obj_eutra->black_cells_to_add_mod_list[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
// Phys Cell ID Range
|
|
liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &meas_obj_eutra->black_cells_to_add_mod_list[i].pci_range);
|
|
}
|
|
}else{
|
|
meas_obj_eutra->N_black_cells_to_add_mod = 0;
|
|
}
|
|
|
|
// Cell For Which To Report CGI
|
|
if(meas_obj_eutra->cell_for_which_to_rep_cgi_present)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_obj_eutra->cell_for_which_to_rep_cgi);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Object GERAN
|
|
|
|
Description: Specifies information applicable for inter-RAT
|
|
GERAN neighboring frequencies
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_geran_ie(LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT *meas_obj_geran,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(meas_obj_geran != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(meas_obj_geran->cell_for_which_to_rep_cgi_present, ie_ptr, 1);
|
|
|
|
// Carrier Freqs
|
|
liblte_rrc_pack_carrier_freqs_geran_ie(&meas_obj_geran->carrier_freqs, ie_ptr);
|
|
|
|
// Offset Freq
|
|
liblte_rrc_pack_q_offset_range_inter_rat_ie(meas_obj_geran->offset_freq, ie_ptr);
|
|
|
|
// NCC Permitted
|
|
liblte_value_2_bits(meas_obj_geran->ncc_permitted, ie_ptr, 8);
|
|
|
|
// Cell For Which To Report CGI
|
|
if(meas_obj_geran->cell_for_which_to_rep_cgi_present)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_geran_ie(&meas_obj_geran->cell_for_which_to_rep_cgi, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_geran_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_OBJECT_GERAN_STRUCT *meas_obj_geran)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_obj_geran != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
meas_obj_geran->cell_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Carrier Freqs
|
|
liblte_rrc_unpack_carrier_freqs_geran_ie(ie_ptr, &meas_obj_geran->carrier_freqs);
|
|
|
|
// Offset Freq
|
|
liblte_rrc_unpack_q_offset_range_inter_rat_ie(ie_ptr, &meas_obj_geran->offset_freq);
|
|
|
|
// NCC Permitted
|
|
meas_obj_geran->ncc_permitted = liblte_bits_2_value(ie_ptr, 8);
|
|
|
|
// Cell For Which To Report CGI
|
|
if(meas_obj_geran->cell_for_which_to_rep_cgi_present)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_geran_ie(ie_ptr, &meas_obj_geran->cell_for_which_to_rep_cgi);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Object ID
|
|
|
|
Description: Identifies a measurement object configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_id_ie(uint8 meas_object_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(meas_object_id - 1, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_id_ie(uint8 **ie_ptr,
|
|
uint8 *meas_object_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_object_id != NULL)
|
|
{
|
|
*meas_object_id = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Object To Add Mod List
|
|
|
|
Description: Concerns a list of measurement objects to add or
|
|
modify
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_to_add_mod_list_ie(LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT *list,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(list != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// List Size
|
|
liblte_value_2_bits(list->N_meas_obj - 1, ie_ptr, 5);
|
|
|
|
for(i=0; i<list->N_meas_obj; i++)
|
|
{
|
|
// Meas Object ID
|
|
liblte_rrc_pack_meas_object_id_ie(list->meas_obj_list[i].meas_obj_id, ie_ptr);
|
|
|
|
// Meas Object Choice Extension
|
|
liblte_value_2_bits(0, ie_ptr, 1); // Choice from before extension marker
|
|
|
|
// Meas Object Choice
|
|
liblte_value_2_bits(list->meas_obj_list[i].meas_obj_type, ie_ptr, 2);
|
|
|
|
// Meas Object
|
|
if(LIBLTE_RRC_MEAS_OBJECT_TYPE_EUTRA == list->meas_obj_list[i].meas_obj_type)
|
|
{
|
|
liblte_rrc_pack_meas_object_eutra_ie(&list->meas_obj_list[i].meas_obj_eutra, ie_ptr);
|
|
}else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_UTRA == list->meas_obj_list[i].meas_obj_type){
|
|
liblte_rrc_pack_meas_object_utra_ie(&list->meas_obj_list[i].meas_obj_utra, ie_ptr);
|
|
}else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_GERAN == list->meas_obj_list[i].meas_obj_type){
|
|
liblte_rrc_pack_meas_object_geran_ie(&list->meas_obj_list[i].meas_obj_geran, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_meas_object_cdma2000_ie(&list->meas_obj_list[i].meas_obj_cdma2000, ie_ptr);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_to_add_mod_list_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_OBJECT_TO_ADD_MOD_LIST_STRUCT *list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
list != NULL)
|
|
{
|
|
// List Size
|
|
list->N_meas_obj = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
for(i=0; i<list->N_meas_obj; i++)
|
|
{
|
|
// Meas Object ID
|
|
liblte_rrc_unpack_meas_object_id_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_id);
|
|
|
|
// Meas Object Choice Extension
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Meas Object Choice
|
|
list->meas_obj_list[i].meas_obj_type = (LIBLTE_RRC_MEAS_OBJECT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
// Meas Object
|
|
if(LIBLTE_RRC_MEAS_OBJECT_TYPE_EUTRA == list->meas_obj_list[i].meas_obj_type)
|
|
{
|
|
liblte_rrc_unpack_meas_object_eutra_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_eutra);
|
|
}else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_UTRA == list->meas_obj_list[i].meas_obj_type){
|
|
liblte_rrc_unpack_meas_object_utra_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_utra);
|
|
}else if(LIBLTE_RRC_MEAS_OBJECT_TYPE_GERAN == list->meas_obj_list[i].meas_obj_type){
|
|
liblte_rrc_unpack_meas_object_geran_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_geran);
|
|
}else{
|
|
liblte_rrc_unpack_meas_object_cdma2000_ie(ie_ptr, &list->meas_obj_list[i].meas_obj_cdma2000);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Object UTRA
|
|
|
|
Description: Specifies information applicable for inter-RAT UTRA
|
|
neighboring cells
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_object_utra_ie(LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT *meas_obj_utra,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(meas_obj_utra != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(meas_obj_utra->cells_to_remove_list_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list_present, ie_ptr, 1);
|
|
liblte_value_2_bits(meas_obj_utra->cells_for_which_to_rep_cgi_present, ie_ptr, 1);
|
|
|
|
// Carrier Freq
|
|
liblte_rrc_pack_arfcn_value_utra_ie(meas_obj_utra->carrier_freq, ie_ptr);
|
|
|
|
// Offset Freq
|
|
liblte_rrc_pack_q_offset_range_inter_rat_ie(meas_obj_utra->offset_freq, ie_ptr);
|
|
|
|
// Cells To Remove List
|
|
if(meas_obj_utra->cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_pack_cell_index_list_ie(&meas_obj_utra->cells_to_remove_list, ie_ptr);
|
|
}
|
|
|
|
// Cells To Add Mod List
|
|
if(meas_obj_utra->cells_to_add_mod_list_present)
|
|
{
|
|
// UTRA System Type
|
|
liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.type, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.N_cells - 1, ie_ptr, 5);
|
|
for(i=0; i<meas_obj_utra->cells_to_add_mod_list.N_cells; i++)
|
|
{
|
|
if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_to_add_mod_list.type)
|
|
{
|
|
// Cell Index
|
|
liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].cell_idx - 1, ie_ptr, 5);
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_utra_fdd_ie(meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].pci, ie_ptr);
|
|
}else{
|
|
// Cell Index
|
|
liblte_value_2_bits(meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].cell_idx - 1, ie_ptr, 5);
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_utra_tdd_ie(meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].pci, ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cells For Which To Report CGI
|
|
if(meas_obj_utra->cells_for_which_to_rep_cgi_present)
|
|
{
|
|
// UTRA System Type
|
|
liblte_value_2_bits(meas_obj_utra->cells_for_which_to_rep_cgi.type, ie_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_for_which_to_rep_cgi.type)
|
|
{
|
|
// Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_utra_fdd_ie(meas_obj_utra->cells_for_which_to_rep_cgi.pci_fdd, ie_ptr);
|
|
}else{
|
|
// Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_utra_tdd_ie(meas_obj_utra->cells_for_which_to_rep_cgi.pci_tdd, ie_ptr);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_object_utra_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MEAS_OBJECT_UTRA_STRUCT *meas_obj_utra)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
meas_obj_utra != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
meas_obj_utra->cells_to_remove_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_utra->cells_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
meas_obj_utra->cells_for_which_to_rep_cgi_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Carrier Freq
|
|
liblte_rrc_unpack_arfcn_value_utra_ie(ie_ptr, &meas_obj_utra->carrier_freq);
|
|
|
|
// Offset Freq
|
|
liblte_rrc_unpack_q_offset_range_inter_rat_ie(ie_ptr, &meas_obj_utra->offset_freq);
|
|
|
|
// Cells To Remove List
|
|
if(meas_obj_utra->cells_to_remove_list_present)
|
|
{
|
|
liblte_rrc_unpack_cell_index_list_ie(ie_ptr, &meas_obj_utra->cells_to_remove_list);
|
|
}
|
|
|
|
// Cells To Add Mod List
|
|
if(meas_obj_utra->cells_to_add_mod_list_present)
|
|
{
|
|
// UTRA System Type
|
|
meas_obj_utra->cells_to_add_mod_list.type = (LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
meas_obj_utra->cells_to_add_mod_list.N_cells = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<meas_obj_utra->cells_to_add_mod_list.N_cells; i++)
|
|
{
|
|
if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_to_add_mod_list.type)
|
|
{
|
|
// Cell Index
|
|
meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(ie_ptr, &meas_obj_utra->cells_to_add_mod_list.cells_fdd[i].pci);
|
|
}else{
|
|
// Cell Index
|
|
meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
// Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_utra_tdd_ie(ie_ptr, &meas_obj_utra->cells_to_add_mod_list.cells_tdd[i].pci);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Cells For Which To Report CGI
|
|
if(meas_obj_utra->cells_for_which_to_rep_cgi_present)
|
|
{
|
|
// UTRA System Type
|
|
meas_obj_utra->cells_for_which_to_rep_cgi.type = (LIBLTE_RRC_UTRA_SYSTEM_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_UTRA_SYSTEM_TYPE_FDD == meas_obj_utra->cells_for_which_to_rep_cgi.type)
|
|
{
|
|
// Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(ie_ptr, &meas_obj_utra->cells_for_which_to_rep_cgi.pci_fdd);
|
|
}else{
|
|
// Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_utra_tdd_ie(ie_ptr, &meas_obj_utra->cells_for_which_to_rep_cgi.pci_tdd);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Meas Results
|
|
|
|
Description: Covers measured results for intra-frequency,
|
|
inter-frequency and inter-RAT mobility
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: Quantity Config
|
|
|
|
Description: Specifies the measurement quantities and layer 3
|
|
filtering coefficients for E-UTRA and inter-RAT
|
|
measurements
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_quantity_config_ie(LIBLTE_RRC_QUANTITY_CONFIG_STRUCT *qc,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(qc != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(qc->qc_eutra_present, ie_ptr, 1);
|
|
liblte_value_2_bits(qc->qc_utra_present, ie_ptr, 1);
|
|
liblte_value_2_bits(qc->qc_geran_present, ie_ptr, 1);
|
|
liblte_value_2_bits(qc->qc_cdma2000_present, ie_ptr, 1);
|
|
|
|
// Quality Config EUTRA
|
|
if(qc->qc_eutra_present)
|
|
{
|
|
liblte_rrc_pack_filter_coefficient_ie(qc->qc_eutra.fc_rsrp, ie_ptr);
|
|
liblte_rrc_pack_filter_coefficient_ie(qc->qc_eutra.fc_rsrq, ie_ptr);
|
|
}
|
|
|
|
// Quality Config UTRA
|
|
if(qc->qc_utra_present)
|
|
{
|
|
liblte_value_2_bits(qc->qc_utra.mq_fdd, ie_ptr, 1);
|
|
liblte_value_2_bits(qc->qc_utra.mq_tdd, ie_ptr, 1);
|
|
liblte_rrc_pack_filter_coefficient_ie(qc->qc_utra.fc, ie_ptr);
|
|
}
|
|
|
|
// Quality Config GERAN
|
|
if(qc->qc_geran_present)
|
|
{
|
|
liblte_value_2_bits(qc->qc_geran.mq, ie_ptr, 1);
|
|
liblte_rrc_pack_filter_coefficient_ie(qc->qc_geran.fc, ie_ptr);
|
|
}
|
|
|
|
// Quality Config CDMA2000
|
|
if(qc->qc_cdma2000_present)
|
|
{
|
|
liblte_value_2_bits(qc->qc_cdma2000.mq, ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_quantity_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_QUANTITY_CONFIG_STRUCT *qc)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
qc != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
qc->qc_eutra_present = liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_utra_present = liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_geran_present = liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_cdma2000_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Quantity Config EUTRA
|
|
if(qc->qc_eutra_present)
|
|
{
|
|
qc->qc_eutra.fc_rsrp_not_default = liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_eutra.fc_rsrq_not_default = liblte_bits_2_value(ie_ptr, 1);
|
|
if(qc->qc_eutra.fc_rsrp_not_default) {
|
|
liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_eutra.fc_rsrp);
|
|
}
|
|
if(qc->qc_eutra.fc_rsrq_not_default) {
|
|
liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_eutra.fc_rsrq);
|
|
}
|
|
}
|
|
|
|
// Quantity Config UTRA
|
|
if(qc->qc_utra_present)
|
|
{
|
|
qc->qc_utra.fc_not_default = liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_utra.mq_fdd = (LIBLTE_RRC_MEAS_QUANTITY_UTRA_FDD_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_utra.mq_tdd = LIBLTE_RRC_MEAS_QUANTITY_UTRA_TDD_PCCPCH_RSCP;
|
|
if(qc->qc_utra.fc_not_default) {
|
|
liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_utra.fc);
|
|
}
|
|
}
|
|
|
|
// Quantity Config GERAN
|
|
if(qc->qc_geran_present)
|
|
{
|
|
qc->qc_geran.fc_not_default = liblte_bits_2_value(ie_ptr, 1);
|
|
qc->qc_geran.mq = LIBLTE_RRC_MEAS_QUANTITY_GERAN_RSSI;
|
|
if(qc->qc_geran.fc_not_default) {
|
|
liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &qc->qc_geran.fc);
|
|
}
|
|
}
|
|
|
|
// Quality Config CDMA2000
|
|
if(qc->qc_cdma2000_present)
|
|
{
|
|
qc->qc_cdma2000.mq = (LIBLTE_RRC_MEAS_QUANTITY_CDMA2000_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Report Config EUTRA
|
|
|
|
Description: Specifies criteria for triggering of an E-UTRA
|
|
measurement reporting event
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_eutra_ie(LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *rep_cnfg_eutra,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rep_cnfg_eutra != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Trigger Type
|
|
liblte_value_2_bits(rep_cnfg_eutra->trigger_type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT == rep_cnfg_eutra->trigger_type)
|
|
{
|
|
// Event ID
|
|
// FIXME: Handle extension properly
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_id, ie_ptr, 3);
|
|
if(LIBLTE_RRC_EVENT_ID_EUTRA_A1 == rep_cnfg_eutra->event.event_id)
|
|
{
|
|
// Threshold Type
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a1.eutra.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a1.eutra.type)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a1.eutra.range, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a1.eutra.range, ie_ptr);
|
|
}
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A2 == rep_cnfg_eutra->event.event_id){
|
|
// Threshold Type
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a2.eutra.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a2.eutra.type)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a2.eutra.range, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a2.eutra.range, ie_ptr);
|
|
}
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A3 == rep_cnfg_eutra->event.event_id){
|
|
// Offset
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a3.offset + 30, ie_ptr, 6);
|
|
|
|
// Report On Leave
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a3.report_on_leave, ie_ptr, 1);
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A4 == rep_cnfg_eutra->event.event_id){
|
|
// Threshold Type
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a4.eutra.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a4.eutra.type)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a4.eutra.range, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a4.eutra.range, ie_ptr);
|
|
}
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A5 == rep_cnfg_eutra->event.event_id){
|
|
// Threshold1 Type
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a5.eutra1.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra1.type)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a5.eutra1.range, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a5.eutra1.range, ie_ptr);
|
|
}
|
|
|
|
// Threshold2 Type
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a5.eutra2.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra2.type)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(rep_cnfg_eutra->event.event_a5.eutra2.range, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_rsrq_range_ie(rep_cnfg_eutra->event.event_a5.eutra2.range, ie_ptr);
|
|
}
|
|
}else{
|
|
// Offset
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a6.offset + 30, ie_ptr, 6);
|
|
|
|
// Report On Leave
|
|
liblte_value_2_bits(rep_cnfg_eutra->event.event_a6.report_on_leave, ie_ptr, 1);
|
|
}
|
|
|
|
// Hysteresis
|
|
liblte_rrc_pack_hysteresis_ie(rep_cnfg_eutra->event.hysteresis, ie_ptr);
|
|
|
|
// Time To Trigger
|
|
liblte_rrc_pack_time_to_trigger_ie(rep_cnfg_eutra->event.time_to_trigger, ie_ptr);
|
|
}else{
|
|
// Purpose
|
|
liblte_value_2_bits(rep_cnfg_eutra->periodical.purpose, ie_ptr, 1);
|
|
}
|
|
|
|
// Trigger Quantity
|
|
liblte_value_2_bits(rep_cnfg_eutra->trigger_quantity, ie_ptr, 1);
|
|
|
|
// Report Quantity
|
|
liblte_value_2_bits(rep_cnfg_eutra->report_quantity, ie_ptr, 1);
|
|
|
|
// Max Report Cells
|
|
liblte_value_2_bits(rep_cnfg_eutra->max_report_cells - 1, ie_ptr, 3);
|
|
|
|
// Report Interval
|
|
liblte_rrc_pack_report_interval_ie(rep_cnfg_eutra->report_interval, ie_ptr);
|
|
|
|
// Report Amount
|
|
liblte_value_2_bits(rep_cnfg_eutra->report_amount, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_eutra_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_REPORT_CONFIG_EUTRA_STRUCT *rep_cnfg_eutra)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rep_cnfg_eutra != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Trigger Type
|
|
rep_cnfg_eutra->trigger_type = (LIBLTE_RRC_TRIGGER_TYPE_EUTRA_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_TRIGGER_TYPE_EUTRA_EVENT == rep_cnfg_eutra->trigger_type)
|
|
{
|
|
// Event ID choice extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Event ID
|
|
rep_cnfg_eutra->event.event_id = (LIBLTE_RRC_EVENT_ID_EUTRA_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
if(LIBLTE_RRC_EVENT_ID_EUTRA_A1 == rep_cnfg_eutra->event.event_id)
|
|
{
|
|
// Threshold Type
|
|
rep_cnfg_eutra->event.event_a1.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a1.eutra.type)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a1.eutra.range);
|
|
}else{
|
|
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a1.eutra.range);
|
|
}
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A2 == rep_cnfg_eutra->event.event_id){
|
|
// Threshold Type
|
|
rep_cnfg_eutra->event.event_a2.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a2.eutra.type)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a2.eutra.range);
|
|
}else{
|
|
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a2.eutra.range);
|
|
}
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A3 == rep_cnfg_eutra->event.event_id){
|
|
// Offset
|
|
rep_cnfg_eutra->event.event_a3.offset = liblte_bits_2_value(ie_ptr, 6) - 30;
|
|
|
|
// Report On Leave
|
|
rep_cnfg_eutra->event.event_a3.report_on_leave = liblte_bits_2_value(ie_ptr, 1);
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A4 == rep_cnfg_eutra->event.event_id){
|
|
// Threshold Type
|
|
rep_cnfg_eutra->event.event_a4.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a4.eutra.type)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a4.eutra.range);
|
|
}else{
|
|
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a4.eutra.range);
|
|
}
|
|
}else if(LIBLTE_RRC_EVENT_ID_EUTRA_A5 == rep_cnfg_eutra->event.event_id){
|
|
// Threshold1 Type
|
|
rep_cnfg_eutra->event.event_a5.eutra1.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra1.type)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra1.range);
|
|
}else{
|
|
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra1.range);
|
|
}
|
|
|
|
// Threshold2 Type
|
|
rep_cnfg_eutra->event.event_a5.eutra2.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_eutra->event.event_a5.eutra2.type)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra2.range);
|
|
}else{
|
|
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_eutra->event.event_a5.eutra2.range);
|
|
}
|
|
}else{
|
|
// Offset
|
|
rep_cnfg_eutra->event.event_a6.offset = liblte_bits_2_value(ie_ptr, 6) - 30;
|
|
|
|
// Report On Leave
|
|
rep_cnfg_eutra->event.event_a6.report_on_leave = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
// Hysteresis
|
|
liblte_rrc_unpack_hysteresis_ie(ie_ptr, &rep_cnfg_eutra->event.hysteresis);
|
|
|
|
// Time To Trigger
|
|
liblte_rrc_unpack_time_to_trigger_ie(ie_ptr, &rep_cnfg_eutra->event.time_to_trigger);
|
|
}else{
|
|
// Purpose
|
|
rep_cnfg_eutra->periodical.purpose = (LIBLTE_RRC_PURPOSE_EUTRA_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
// Trigger Quantity
|
|
rep_cnfg_eutra->trigger_quantity = (LIBLTE_RRC_TRIGGER_QUANTITY_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Report Quantity
|
|
rep_cnfg_eutra->report_quantity = (LIBLTE_RRC_REPORT_QUANTITY_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Max Report Cells
|
|
rep_cnfg_eutra->max_report_cells = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
|
|
// Report Interval
|
|
liblte_rrc_unpack_report_interval_ie(ie_ptr, &rep_cnfg_eutra->report_interval);
|
|
|
|
// Report Amount
|
|
rep_cnfg_eutra->report_amount = (LIBLTE_RRC_REPORT_AMOUNT_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Report Config ID
|
|
|
|
Description: Identifies a measurement reporting configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_id_ie(uint8 report_cnfg_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(report_cnfg_id - 1, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_id_ie(uint8 **ie_ptr,
|
|
uint8 *report_cnfg_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
report_cnfg_id != NULL)
|
|
{
|
|
*report_cnfg_id = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Report Config Inter RAT
|
|
|
|
Description: Specifies criteria for triggering of an inter-RAT
|
|
measurement reporting event
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_inter_rat_ie(LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT *rep_cnfg_inter_rat,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rep_cnfg_inter_rat != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Trigger Type
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->trigger_type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_EVENT == rep_cnfg_inter_rat->trigger_type)
|
|
{
|
|
// Event ID
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_id, ie_ptr, 1);
|
|
if(LIBLTE_RRC_EVENT_ID_INTER_RAT_B1 == rep_cnfg_inter_rat->event.event_id)
|
|
{
|
|
// Threshold Type
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.type, ie_ptr, 2);
|
|
if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b1.type)
|
|
{
|
|
// Type
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.utra.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b1.utra.type)
|
|
{
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.utra.value + 5, ie_ptr, 7);
|
|
}else{
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.utra.value, ie_ptr, 6);
|
|
}
|
|
}else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b1.type){
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.geran, ie_ptr, 6);
|
|
}else{
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b1.cdma2000, ie_ptr, 6);
|
|
}
|
|
}else{
|
|
// Threshold1 Type
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.eutra.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_inter_rat->event.event_b2.eutra.type)
|
|
{
|
|
liblte_rrc_pack_rsrp_range_ie(rep_cnfg_inter_rat->event.event_b2.eutra.range, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_rsrq_range_ie(rep_cnfg_inter_rat->event.event_b2.eutra.range, ie_ptr);
|
|
}
|
|
|
|
// Threshold2 Type
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.type2, ie_ptr, 2);
|
|
if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b2.type2)
|
|
{
|
|
// Type
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.utra.type, ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b2.utra.type)
|
|
{
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.utra.value + 5, ie_ptr, 7);
|
|
}else{
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.utra.value, ie_ptr, 6);
|
|
}
|
|
}else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b2.type2){
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.geran, ie_ptr, 6);
|
|
}else{
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->event.event_b2.cdma2000, ie_ptr, 6);
|
|
}
|
|
}
|
|
|
|
// Hysteresis
|
|
liblte_rrc_pack_hysteresis_ie(rep_cnfg_inter_rat->event.hysteresis, ie_ptr);
|
|
|
|
// Time To Trigger
|
|
liblte_rrc_pack_time_to_trigger_ie(rep_cnfg_inter_rat->event.time_to_trigger, ie_ptr);
|
|
}else{
|
|
// Purpose
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->periodical.purpose, ie_ptr, 2);
|
|
}
|
|
|
|
// Max Report Cells
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->max_report_cells - 1, ie_ptr, 3);
|
|
|
|
// Report Interval
|
|
liblte_rrc_pack_report_interval_ie(rep_cnfg_inter_rat->report_interval, ie_ptr);
|
|
|
|
// Report Amount
|
|
liblte_value_2_bits(rep_cnfg_inter_rat->report_amount, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_inter_rat_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_REPORT_CONFIG_INTER_RAT_STRUCT *rep_cnfg_inter_rat)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rep_cnfg_inter_rat != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Trigger Type
|
|
rep_cnfg_inter_rat->trigger_type = (LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_TRIGGER_TYPE_INTER_RAT_EVENT == rep_cnfg_inter_rat->trigger_type)
|
|
{
|
|
// Event ID
|
|
rep_cnfg_inter_rat->event.event_id = (LIBLTE_RRC_EVENT_ID_INTER_RAT_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_EVENT_ID_INTER_RAT_B1 == rep_cnfg_inter_rat->event.event_id)
|
|
{
|
|
// Threshold Type
|
|
rep_cnfg_inter_rat->event.event_b1.type = (LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b1.type)
|
|
{
|
|
// Type
|
|
rep_cnfg_inter_rat->event.event_b1.utra.type = (LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b1.utra.type)
|
|
{
|
|
rep_cnfg_inter_rat->event.event_b1.utra.value = liblte_bits_2_value(ie_ptr, 7) - 5;
|
|
}else{
|
|
rep_cnfg_inter_rat->event.event_b1.utra.value = liblte_bits_2_value(ie_ptr, 6);
|
|
}
|
|
}else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b1.type){
|
|
rep_cnfg_inter_rat->event.event_b1.geran = liblte_bits_2_value(ie_ptr, 6);
|
|
}else{
|
|
rep_cnfg_inter_rat->event.event_b1.cdma2000 = liblte_bits_2_value(ie_ptr, 6);
|
|
}
|
|
}else{
|
|
// Threshold1 Type
|
|
rep_cnfg_inter_rat->event.event_b2.eutra.type = (LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_EUTRA_TYPE_RSRP == rep_cnfg_inter_rat->event.event_b2.eutra.type)
|
|
{
|
|
liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &rep_cnfg_inter_rat->event.event_b2.eutra.range);
|
|
}else{
|
|
liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &rep_cnfg_inter_rat->event.event_b2.eutra.range);
|
|
}
|
|
|
|
// Threshold2 Type
|
|
rep_cnfg_inter_rat->event.event_b2.type2 = (LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_UTRA == rep_cnfg_inter_rat->event.event_b2.type2)
|
|
{
|
|
// Type
|
|
rep_cnfg_inter_rat->event.event_b2.utra.type = (LIBLTE_RRC_THRESHOLD_UTRA_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_THRESHOLD_UTRA_TYPE_RSCP == rep_cnfg_inter_rat->event.event_b2.utra.type)
|
|
{
|
|
rep_cnfg_inter_rat->event.event_b2.utra.value = liblte_bits_2_value(ie_ptr, 7) - 5;
|
|
}else{
|
|
rep_cnfg_inter_rat->event.event_b2.utra.value = liblte_bits_2_value(ie_ptr, 6);
|
|
}
|
|
}else if(LIBLTE_RRC_THRESHOLD_INTER_RAT_TYPE_GERAN == rep_cnfg_inter_rat->event.event_b2.type2){
|
|
rep_cnfg_inter_rat->event.event_b2.geran = liblte_bits_2_value(ie_ptr, 6);
|
|
}else{
|
|
rep_cnfg_inter_rat->event.event_b2.cdma2000 = liblte_bits_2_value(ie_ptr, 6);
|
|
}
|
|
}
|
|
|
|
// Hysteresis
|
|
liblte_rrc_unpack_hysteresis_ie(ie_ptr, &rep_cnfg_inter_rat->event.hysteresis);
|
|
|
|
// Time To Trigger
|
|
liblte_rrc_unpack_time_to_trigger_ie(ie_ptr, &rep_cnfg_inter_rat->event.time_to_trigger);
|
|
}else{
|
|
// Purpose
|
|
rep_cnfg_inter_rat->periodical.purpose = (LIBLTE_RRC_PURPOSE_INTER_RAT_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
}
|
|
|
|
// Max Report Cells
|
|
rep_cnfg_inter_rat->max_report_cells = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
|
|
// Report Interval
|
|
liblte_rrc_unpack_report_interval_ie(ie_ptr, &rep_cnfg_inter_rat->report_interval);
|
|
|
|
// Report Amount
|
|
rep_cnfg_inter_rat->report_amount = (LIBLTE_RRC_REPORT_AMOUNT_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Report Config To Add Mod List
|
|
|
|
Description: Concerns a list of reporting configurations to add
|
|
or modify
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_report_config_to_add_mod_list_ie(LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT *list,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(list != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// List Size
|
|
liblte_value_2_bits(list->N_rep_cnfg - 1, ie_ptr, 5);
|
|
|
|
for(i=0; i<list->N_rep_cnfg; i++)
|
|
{
|
|
// Report Config ID
|
|
liblte_rrc_pack_report_config_id_ie(list->rep_cnfg_list[i].rep_cnfg_id, ie_ptr);
|
|
|
|
// Report Config Choice
|
|
liblte_value_2_bits(list->rep_cnfg_list[i].rep_cnfg_type, ie_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_REPORT_CONFIG_TYPE_EUTRA == list->rep_cnfg_list[i].rep_cnfg_type)
|
|
{
|
|
liblte_rrc_pack_report_config_eutra_ie(&list->rep_cnfg_list[i].rep_cnfg_eutra, ie_ptr);
|
|
}else{
|
|
liblte_rrc_pack_report_config_inter_rat_ie(&list->rep_cnfg_list[i].rep_cnfg_inter_rat, ie_ptr);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_config_to_add_mod_list_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_REPORT_CONFIG_TO_ADD_MOD_LIST_STRUCT *list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
list != NULL)
|
|
{
|
|
// List Size
|
|
list->N_rep_cnfg = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
for(i=0; i<list->N_rep_cnfg; i++)
|
|
{
|
|
// Report Config ID
|
|
liblte_rrc_unpack_report_config_id_ie(ie_ptr, &list->rep_cnfg_list[i].rep_cnfg_id);
|
|
|
|
// Report Config Choice
|
|
list->rep_cnfg_list[i].rep_cnfg_type = (LIBLTE_RRC_REPORT_CONFIG_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_REPORT_CONFIG_TYPE_EUTRA == list->rep_cnfg_list[i].rep_cnfg_type)
|
|
{
|
|
liblte_rrc_unpack_report_config_eutra_ie(ie_ptr, &list->rep_cnfg_list[i].rep_cnfg_eutra);
|
|
}else{
|
|
liblte_rrc_unpack_report_config_inter_rat_ie(ie_ptr, &list->rep_cnfg_list[i].rep_cnfg_inter_rat);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Report Interval
|
|
|
|
Description: Indicates the interval between periodic reports
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_report_interval_ie(LIBLTE_RRC_REPORT_INTERVAL_ENUM report_int,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(report_int, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_report_interval_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_REPORT_INTERVAL_ENUM *report_int)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
report_int != NULL)
|
|
{
|
|
*report_int = (LIBLTE_RRC_REPORT_INTERVAL_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RSRP Range
|
|
|
|
Description: Specifies the value range used in RSRP measurements
|
|
and thresholds
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrp_range_ie(uint8 rsrp_range,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(rsrp_range, ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrp_range_ie(uint8 **ie_ptr,
|
|
uint8 *rsrp_range)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rsrp_range != NULL)
|
|
{
|
|
*rsrp_range = liblte_bits_2_value(ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RSRQ Range
|
|
|
|
Description: Specifies the value range used in RSRQ measurements
|
|
and thresholds
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rsrq_range_ie(uint8 rsrq_range,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(rsrq_range, ie_ptr, 6);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rsrq_range_ie(uint8 **ie_ptr,
|
|
uint8 *rsrq_range)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rsrq_range != NULL)
|
|
{
|
|
*rsrq_range = liblte_bits_2_value(ie_ptr, 6);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Time To Trigger
|
|
|
|
Description: Specifies the value range used for the time to
|
|
trigger parameter, which concerns the time during
|
|
which specific criteria for the event needs to be
|
|
met in order to trigger a measurement report
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.5
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_time_to_trigger_ie(LIBLTE_RRC_TIME_TO_TRIGGER_ENUM time_to_trigger,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(time_to_trigger, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_time_to_trigger_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_TIME_TO_TRIGGER_ENUM *time_to_trigger)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
time_to_trigger != NULL)
|
|
{
|
|
*time_to_trigger = (LIBLTE_RRC_TIME_TO_TRIGGER_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Additional Spectrum Emission
|
|
|
|
Description: FIXME
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_additional_spectrum_emission_ie(uint8 add_spect_em,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(add_spect_em - 1, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_additional_spectrum_emission_ie(uint8 **ie_ptr,
|
|
uint8 *add_spect_em)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
add_spect_em != NULL)
|
|
{
|
|
*add_spect_em = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ARFCN value CDMA2000
|
|
|
|
Description: Indicates the CDMA2000 carrier frequency within
|
|
a CDMA2000 band
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_cdma2000_ie(uint16 arfcn,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(arfcn, ie_ptr, 11);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_cdma2000_ie(uint8 **ie_ptr,
|
|
uint16 *arfcn)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
arfcn != NULL)
|
|
{
|
|
*arfcn = liblte_bits_2_value(ie_ptr, 11);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ARFCN value EUTRA
|
|
|
|
Description: Indicates the ARFCN applicable for a downlink,
|
|
uplink, or bi-directional (TDD) E-UTRA carrier
|
|
frequency
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_eutra_ie(uint16 arfcn,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(arfcn, ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_eutra_ie(uint8 **ie_ptr,
|
|
uint16 *arfcn)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
arfcn != NULL)
|
|
{
|
|
*arfcn = liblte_bits_2_value(ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ARFCN value GERAN
|
|
|
|
Description: Specifies the ARFCN value applicable for a GERAN
|
|
BCCH carrier frequency
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_geran_ie(uint16 arfcn,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(arfcn, ie_ptr, 10);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_geran_ie(uint8 **ie_ptr,
|
|
uint16 *arfcn)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
arfcn != NULL)
|
|
{
|
|
*arfcn = liblte_bits_2_value(ie_ptr, 10);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: ARFCN value UTRA
|
|
|
|
Description: Indicates the ARFCN applicable for a downlink (Nd,
|
|
FDD) or bi-directional (Nt, TDD) UTRA carrier
|
|
frequency
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_arfcn_value_utra_ie(uint16 arfcn,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(arfcn, ie_ptr, 14);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_arfcn_value_utra_ie(uint8 **ie_ptr,
|
|
uint16 *arfcn)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
arfcn != NULL)
|
|
{
|
|
*arfcn = liblte_bits_2_value(ie_ptr, 14);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Band Class CDMA2000
|
|
|
|
Description: Defines the CDMA2000 band in which the CDMA2000
|
|
carrier frequency can be found
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_band_class_cdma2000_ie(LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM bc_cdma2000,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(bc_cdma2000, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_class_cdma2000_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM *bc_cdma2000)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
bc_cdma2000 != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
*bc_cdma2000 = (LIBLTE_RRC_BAND_CLASS_CDMA2000_ENUM)liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Band Indicator GERAN
|
|
|
|
Description: Indicates how to interpret an associated GERAN
|
|
carrier ARFCN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_band_indicator_geran_ie(LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM bi_geran,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(bi_geran, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_band_indicator_geran_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM *bi_geran)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
bi_geran != NULL)
|
|
{
|
|
*bi_geran = (LIBLTE_RRC_BAND_INDICATOR_GERAN_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Carrier Freq CDMA2000
|
|
|
|
Description: Provides the CDMA2000 carrier information
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freq_cdma2000_ie(LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT *carrier_freq,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(carrier_freq != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_band_class_cdma2000_ie(carrier_freq->bandclass, ie_ptr);
|
|
liblte_rrc_pack_arfcn_value_cdma2000_ie(carrier_freq->arfcn, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freq_cdma2000_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CARRIER_FREQ_CDMA2000_STRUCT *carrier_freq)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
carrier_freq != NULL)
|
|
{
|
|
liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &carrier_freq->bandclass);
|
|
liblte_rrc_unpack_arfcn_value_cdma2000_ie(ie_ptr, &carrier_freq->arfcn);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Carrier Freq GERAN
|
|
|
|
Description: Provides an unambiguous carrier frequency description
|
|
of a GERAN cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freq_geran_ie(LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT *carrier_freq,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(carrier_freq != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_geran_ie(carrier_freq->arfcn, ie_ptr);
|
|
liblte_rrc_pack_band_indicator_geran_ie(carrier_freq->band_indicator, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freq_geran_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CARRIER_FREQ_GERAN_STRUCT *carrier_freq)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
carrier_freq != NULL)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_geran_ie(ie_ptr, &carrier_freq->arfcn);
|
|
liblte_rrc_unpack_band_indicator_geran_ie(ie_ptr, &carrier_freq->band_indicator);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Carrier Freqs GERAN
|
|
|
|
Description: Provides one or more GERAN ARFCN values, which
|
|
represent a list of GERAN BCCH carrier frequencies
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_carrier_freqs_geran_ie(LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT *carrier_freqs,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(carrier_freqs != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_geran_ie(carrier_freqs->starting_arfcn, ie_ptr);
|
|
liblte_rrc_pack_band_indicator_geran_ie(carrier_freqs->band_indicator, ie_ptr);
|
|
liblte_value_2_bits(carrier_freqs->following_arfcns, ie_ptr, 2);
|
|
if(LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST == carrier_freqs->following_arfcns)
|
|
{
|
|
liblte_value_2_bits(carrier_freqs->explicit_list_of_arfcns_size, ie_ptr, 5);
|
|
for(i=0; i<carrier_freqs->explicit_list_of_arfcns_size; i++)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_geran_ie(carrier_freqs->explicit_list_of_arfcns[i], ie_ptr);
|
|
}
|
|
}else if(LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED == carrier_freqs->following_arfcns){
|
|
liblte_value_2_bits(carrier_freqs->equally_spaced_arfcns.arfcn_spacing - 1, ie_ptr, 3);
|
|
liblte_value_2_bits(carrier_freqs->equally_spaced_arfcns.number_of_arfcns, ie_ptr, 5);
|
|
}else{ // LIBLTE_RRC_FOLLOWING_ARFCNS_VARIABLE_BIT_MAP == carrier_freqs->following_arfcns
|
|
liblte_value_2_bits(carrier_freqs->variable_bit_map_of_arfcns, ie_ptr, 16);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_carrier_freqs_geran_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CARRIER_FREQS_GERAN_STRUCT *carrier_freqs)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
carrier_freqs != NULL)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_geran_ie(ie_ptr, &carrier_freqs->starting_arfcn);
|
|
liblte_rrc_unpack_band_indicator_geran_ie(ie_ptr, &carrier_freqs->band_indicator);
|
|
carrier_freqs->following_arfcns = (LIBLTE_RRC_FOLLOWING_ARFCNS_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
if(LIBLTE_RRC_FOLLOWING_ARFCNS_EXPLICIT_LIST == carrier_freqs->following_arfcns)
|
|
{
|
|
carrier_freqs->explicit_list_of_arfcns_size = liblte_bits_2_value(ie_ptr, 5);
|
|
for(i=0; i<carrier_freqs->explicit_list_of_arfcns_size; i++)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_geran_ie(ie_ptr, &carrier_freqs->explicit_list_of_arfcns[i]);
|
|
}
|
|
}else if(LIBLTE_RRC_FOLLOWING_ARFCNS_EQUALLY_SPACED == carrier_freqs->following_arfcns){
|
|
carrier_freqs->equally_spaced_arfcns.arfcn_spacing = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
carrier_freqs->equally_spaced_arfcns.number_of_arfcns = liblte_bits_2_value(ie_ptr, 5);
|
|
}else{ // LIBLTE_RRC_FOLLOWING_ARFCNS_VARIABLE_BIT_MAP == carrier_freqs->following_arfcns
|
|
carrier_freqs->variable_bit_map_of_arfcns = liblte_bits_2_value(ie_ptr, 16);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: CDMA2000 Type
|
|
|
|
Description: Describes the type of CDMA2000 network
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cdma2000_type_ie(LIBLTE_RRC_CDMA2000_TYPE_ENUM cdma2000_type,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(cdma2000_type, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cdma2000_type_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CDMA2000_TYPE_ENUM *cdma2000_type)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cdma2000_type != NULL)
|
|
{
|
|
*cdma2000_type = (LIBLTE_RRC_CDMA2000_TYPE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Identity
|
|
|
|
Description: Unambiguously identifies a cell within a PLMN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_identity_ie(uint32 cell_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(cell_id, ie_ptr, 28);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_identity_ie(uint8 **ie_ptr,
|
|
uint32 *cell_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_id != NULL)
|
|
{
|
|
*cell_id = liblte_bits_2_value(ie_ptr, 28);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Index List
|
|
|
|
Description: Concerns a list of cell indecies, which may be used
|
|
for different purposes
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_index_list_ie(LIBLTE_RRC_CELL_INDEX_LIST_STRUCT *cell_idx_list,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(cell_idx_list != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// List Size
|
|
liblte_value_2_bits(cell_idx_list->N_cell_idx - 1, ie_ptr, 5);
|
|
|
|
for(i=0; i<cell_idx_list->N_cell_idx; i++)
|
|
{
|
|
// Cell Index
|
|
liblte_value_2_bits(cell_idx_list->cell_idx[i] - 1, ie_ptr, 5);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_index_list_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CELL_INDEX_LIST_STRUCT *cell_idx_list)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_idx_list != NULL)
|
|
{
|
|
// List Size
|
|
cell_idx_list->N_cell_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
for(i=0; i<cell_idx_list->N_cell_idx; i++)
|
|
{
|
|
// Cell Index
|
|
cell_idx_list->cell_idx[i] = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Reselection Priority
|
|
|
|
Description: Contains the absolute priority of the concerned
|
|
carrier frequency/set of frequencies (GERAN)/
|
|
bandclass (CDMA2000), as used by the cell
|
|
reselection procedure
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_reselection_priority_ie(uint8 cell_resel_prio,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(cell_resel_prio, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_reselection_priority_ie(uint8 **ie_ptr,
|
|
uint8 *cell_resel_prio)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_resel_prio != NULL)
|
|
{
|
|
*cell_resel_prio = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: CSFB Registration Param 1xRTT
|
|
|
|
Description: Indicates whether or not the UE shall perform a
|
|
CDMA2000 1xRTT pre-registration if the UE does not
|
|
have a valid/current pre-registration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_ie(LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT *csfb_reg_param,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(csfb_reg_param != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(csfb_reg_param->sid, ie_ptr, 15);
|
|
liblte_value_2_bits(csfb_reg_param->nid, ie_ptr, 16);
|
|
liblte_value_2_bits(csfb_reg_param->multiple_sid, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->multiple_nid, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->home_reg, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->foreign_sid_reg, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->foreign_nid_reg, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->param_reg, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->power_up_reg, ie_ptr, 1);
|
|
liblte_value_2_bits(csfb_reg_param->reg_period, ie_ptr, 7);
|
|
liblte_value_2_bits(csfb_reg_param->reg_zone, ie_ptr, 12);
|
|
liblte_value_2_bits(csfb_reg_param->total_zone, ie_ptr, 3);
|
|
liblte_value_2_bits(csfb_reg_param->zone_timer, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_STRUCT *csfb_reg_param)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
csfb_reg_param != NULL)
|
|
{
|
|
csfb_reg_param->sid = liblte_bits_2_value(ie_ptr, 15);
|
|
csfb_reg_param->nid = liblte_bits_2_value(ie_ptr, 16);
|
|
csfb_reg_param->multiple_sid = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->multiple_nid = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->home_reg = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->foreign_sid_reg = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->foreign_nid_reg = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->param_reg = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->power_up_reg = liblte_bits_2_value(ie_ptr, 1);
|
|
csfb_reg_param->reg_period = liblte_bits_2_value(ie_ptr, 7);
|
|
csfb_reg_param->reg_zone = liblte_bits_2_value(ie_ptr, 12);
|
|
csfb_reg_param->total_zone = liblte_bits_2_value(ie_ptr, 3);
|
|
csfb_reg_param->zone_timer = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_registration_param_1xrtt_v920_ie(LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT *csfb_reg_param,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(csfb_reg_param != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(csfb_reg_param->power_down_reg, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_registration_param_1xrtt_v920_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CSFB_REGISTRATION_PARAM_1XRTT_V920_STRUCT *csfb_reg_param)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
csfb_reg_param != NULL)
|
|
{
|
|
csfb_reg_param->power_down_reg = (LIBLTE_RRC_POWER_DOWN_REG_R9_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Global ID EUTRA
|
|
|
|
Description: Specifies the Evolved Cell Global Identifier (ECGI),
|
|
the globally unique identity of a cell in E-UTRA
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_eutra_ie(LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT *cell_global_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(cell_global_id != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_plmn_identity_ie(&cell_global_id->plmn_id, ie_ptr);
|
|
liblte_rrc_pack_cell_identity_ie(cell_global_id->cell_id, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_eutra_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT *cell_global_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_global_id != NULL)
|
|
{
|
|
liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cell_global_id->plmn_id);
|
|
liblte_rrc_unpack_cell_identity_ie(ie_ptr, &cell_global_id->cell_id);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Global ID UTRA
|
|
|
|
Description: Specifies the global UTRAN Cell Identifier, the
|
|
globally unique identity of a cell in UTRA
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_utra_ie(LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT *cell_global_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(cell_global_id != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_plmn_identity_ie(&cell_global_id->plmn_id, ie_ptr);
|
|
liblte_value_2_bits(cell_global_id->cell_id, ie_ptr, 28);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_utra_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CELL_GLOBAL_ID_UTRA_STRUCT *cell_global_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_global_id != NULL)
|
|
{
|
|
liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cell_global_id->plmn_id);
|
|
cell_global_id->cell_id = liblte_bits_2_value(ie_ptr, 28);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Global ID GERAN
|
|
|
|
Description: Specifies the Cell Global Identity (CGI), the
|
|
globally unique identity of a cell in GERAN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_geran_ie(LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT *cell_global_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(cell_global_id != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_rrc_pack_plmn_identity_ie(&cell_global_id->plmn_id, ie_ptr);
|
|
liblte_value_2_bits(cell_global_id->lac, ie_ptr, 16);
|
|
liblte_value_2_bits(cell_global_id->cell_id, ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_geran_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CELL_GLOBAL_ID_GERAN_STRUCT *cell_global_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_global_id != NULL)
|
|
{
|
|
liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cell_global_id->plmn_id);
|
|
cell_global_id->lac = liblte_bits_2_value(ie_ptr, 16);
|
|
cell_global_id->cell_id = liblte_bits_2_value(ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cell Global ID CDMA2000
|
|
|
|
Description: Specifies the Cell Global Identity (CGI), the
|
|
globally unique identity of a cell in CDMA2000
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cell_global_id_cdma2000_ie(LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT *cell_global_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(cell_global_id != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits((uint32)(cell_global_id->onexrtt >> 15), ie_ptr, 32);
|
|
liblte_value_2_bits((uint32)(cell_global_id->onexrtt & 0x7FFFULL), ie_ptr, 15);
|
|
liblte_value_2_bits(cell_global_id->hrpd[0], ie_ptr, 32);
|
|
liblte_value_2_bits(cell_global_id->hrpd[1], ie_ptr, 32);
|
|
liblte_value_2_bits(cell_global_id->hrpd[2], ie_ptr, 32);
|
|
liblte_value_2_bits(cell_global_id->hrpd[3], ie_ptr, 32);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cell_global_id_cdma2000_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CELL_GLOBAL_ID_CDMA2000_STRUCT *cell_global_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cell_global_id != NULL)
|
|
{
|
|
cell_global_id->onexrtt = (uint64)liblte_bits_2_value(ie_ptr, 32) << 15;
|
|
cell_global_id->onexrtt |= (uint64)liblte_bits_2_value(ie_ptr, 15);
|
|
cell_global_id->hrpd[0] = liblte_bits_2_value(ie_ptr, 32);
|
|
cell_global_id->hrpd[1] = liblte_bits_2_value(ie_ptr, 32);
|
|
cell_global_id->hrpd[2] = liblte_bits_2_value(ie_ptr, 32);
|
|
cell_global_id->hrpd[3] = liblte_bits_2_value(ie_ptr, 32);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: CSG Identity
|
|
|
|
Description: Identifies a Closed Subscriber Group
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_csg_identity_ie(uint32 csg_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(csg_id, ie_ptr, 27);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_csg_identity_ie(uint8 **ie_ptr,
|
|
uint32 *csg_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
csg_id != NULL)
|
|
{
|
|
*csg_id = liblte_bits_2_value(ie_ptr, 27);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Mobility Control Info
|
|
|
|
Description: Includes parameters relevant for network controlled
|
|
mobility to/within E-UTRA
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_control_info_ie(LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT *mob_ctrl_info,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(mob_ctrl_info != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(mob_ctrl_info->carrier_freq_eutra_present, ie_ptr, 1);
|
|
liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra_present, ie_ptr, 1);
|
|
liblte_value_2_bits(mob_ctrl_info->add_spect_em_present, ie_ptr, 1);
|
|
liblte_value_2_bits(mob_ctrl_info->rach_cnfg_ded_present, ie_ptr, 1);
|
|
|
|
// Target Phys Cell ID
|
|
liblte_rrc_pack_phys_cell_id_ie(mob_ctrl_info->target_pci, ie_ptr);
|
|
|
|
// Carrier Freq
|
|
if(mob_ctrl_info->carrier_freq_eutra_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present, ie_ptr, 1);
|
|
|
|
// DL Carrier Freq
|
|
liblte_rrc_pack_arfcn_value_eutra_ie(mob_ctrl_info->carrier_freq_eutra.dl_carrier_freq, ie_ptr);
|
|
|
|
// UL Carrier Freq
|
|
if(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_eutra_ie(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// Carrier Bandwidth
|
|
if(mob_ctrl_info->carrier_bw_eutra_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra.ul_bw_present, ie_ptr, 1);
|
|
|
|
// DL Bandwidth
|
|
liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra.dl_bw, ie_ptr, 4);
|
|
|
|
// UL Bandwidth
|
|
if(mob_ctrl_info->carrier_bw_eutra.ul_bw_present)
|
|
{
|
|
liblte_value_2_bits(mob_ctrl_info->carrier_bw_eutra.ul_bw, ie_ptr, 4);
|
|
}
|
|
}
|
|
|
|
// Additional Spectrum Emission
|
|
if(mob_ctrl_info->add_spect_em_present)
|
|
{
|
|
liblte_rrc_pack_additional_spectrum_emission_ie(mob_ctrl_info->add_spect_em, ie_ptr);
|
|
}
|
|
|
|
// T304
|
|
liblte_value_2_bits(mob_ctrl_info->t304, ie_ptr, 3);
|
|
|
|
// New UE Identity
|
|
liblte_rrc_pack_c_rnti_ie(mob_ctrl_info->new_ue_id, ie_ptr);
|
|
|
|
// Radio Resource Config Common
|
|
liblte_rrc_pack_rr_config_common_ie(&mob_ctrl_info->rr_cnfg_common, ie_ptr);
|
|
|
|
// RACH Config Dedicated
|
|
if(mob_ctrl_info->rach_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_rach_config_dedicated_ie(&mob_ctrl_info->rach_cnfg_ded, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_control_info_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MOBILITY_CONTROL_INFO_STRUCT *mob_ctrl_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mob_ctrl_info != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
mob_ctrl_info->carrier_freq_eutra_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mob_ctrl_info->carrier_bw_eutra_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mob_ctrl_info->add_spect_em_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mob_ctrl_info->rach_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Target Phys Cell ID
|
|
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &mob_ctrl_info->target_pci);
|
|
|
|
// Carrier Freq
|
|
if(mob_ctrl_info->carrier_freq_eutra_present)
|
|
{
|
|
// Optional indicator
|
|
mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// DL Carrier Freq
|
|
liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &mob_ctrl_info->carrier_freq_eutra.dl_carrier_freq);
|
|
|
|
// UL Carrier Freq
|
|
if(mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq_present)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &mob_ctrl_info->carrier_freq_eutra.ul_carrier_freq);
|
|
}
|
|
}
|
|
|
|
// Carrier Bandwidth
|
|
if(mob_ctrl_info->carrier_bw_eutra_present)
|
|
{
|
|
// Optional indicator
|
|
mob_ctrl_info->carrier_bw_eutra.ul_bw_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// DL Bandwidth
|
|
mob_ctrl_info->carrier_bw_eutra.dl_bw = (LIBLTE_RRC_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// UL Bandwidth
|
|
if(mob_ctrl_info->carrier_bw_eutra.ul_bw_present)
|
|
{
|
|
mob_ctrl_info->carrier_bw_eutra.ul_bw = (LIBLTE_RRC_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
}
|
|
|
|
// Additional Spectrum Emission
|
|
if(mob_ctrl_info->add_spect_em_present)
|
|
{
|
|
liblte_rrc_unpack_additional_spectrum_emission_ie(ie_ptr, &mob_ctrl_info->add_spect_em);
|
|
}
|
|
|
|
// T304
|
|
mob_ctrl_info->t304 = (LIBLTE_RRC_T304_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// New UE Identity
|
|
liblte_rrc_unpack_c_rnti_ie(ie_ptr, &mob_ctrl_info->new_ue_id);
|
|
|
|
// Radio Resource Config Common
|
|
liblte_rrc_unpack_rr_config_common_ie(ie_ptr, &mob_ctrl_info->rr_cnfg_common);
|
|
|
|
// RACH Config Dedicated
|
|
if(mob_ctrl_info->rach_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_rach_config_dedicated_ie(ie_ptr, &mob_ctrl_info->rach_cnfg_ded);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Mobility Parameters CDMA2000 (1xRTT)
|
|
|
|
Description: Contains the parameters provided to the UE for
|
|
handover and (enhanced) CSFB to 1xRTT support
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: Mobility State Parameters
|
|
|
|
Description: Contains parameters to determine UE mobility state
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mobility_state_parameters_ie(LIBLTE_RRC_MOBILITY_STATE_PARAMETERS_STRUCT *mobility_state_params,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(mobility_state_params != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(mobility_state_params->t_eval, ie_ptr, 3);
|
|
liblte_value_2_bits(mobility_state_params->t_hyst_normal, ie_ptr, 3);
|
|
liblte_value_2_bits(mobility_state_params->n_cell_change_medium - 1, ie_ptr, 4);
|
|
liblte_value_2_bits(mobility_state_params->n_cell_change_high - 1, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_state_parameters_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MOBILITY_STATE_PARAMETERS_STRUCT *mobility_state_params)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mobility_state_params != NULL)
|
|
{
|
|
mobility_state_params->t_eval = (LIBLTE_RRC_T_EVALUATION_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
mobility_state_params->t_hyst_normal = (LIBLTE_RRC_T_HYST_NORMAL_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
mobility_state_params->n_cell_change_medium = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
mobility_state_params->n_cell_change_high = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID
|
|
|
|
Description: Indicates the physical layer identity of the cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_ie(uint16 phys_cell_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(phys_cell_id, ie_ptr, 9);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_ie(uint8 **ie_ptr,
|
|
uint16 *phys_cell_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phys_cell_id != NULL)
|
|
{
|
|
*phys_cell_id = liblte_bits_2_value(ie_ptr, 9);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID Range
|
|
|
|
Description: Encodes either a single or a range of physical cell
|
|
identities
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_range_ie(LIBLTE_RRC_PHYS_CELL_ID_RANGE_STRUCT *phys_cell_id_range,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool opt;
|
|
|
|
if(phys_cell_id_range != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
opt = (LIBLTE_RRC_PHYS_CELL_ID_RANGE_N1 != phys_cell_id_range->range);
|
|
|
|
liblte_value_2_bits(opt, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_phys_cell_id_ie(phys_cell_id_range->start, ie_ptr);
|
|
|
|
if(opt)
|
|
{
|
|
liblte_value_2_bits(phys_cell_id_range->range, ie_ptr, 4);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_range_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PHYS_CELL_ID_RANGE_STRUCT *phys_cell_id_range)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool opt;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phys_cell_id_range != NULL)
|
|
{
|
|
opt = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &phys_cell_id_range->start);
|
|
|
|
if(true == opt)
|
|
{
|
|
phys_cell_id_range->range = (LIBLTE_RRC_PHYS_CELL_ID_RANGE_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
}else{
|
|
phys_cell_id_range->range = LIBLTE_RRC_PHYS_CELL_ID_RANGE_N1;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID Range UTRA FDD List
|
|
|
|
Description: Encodes one or more of Phys Cell ID Range UTRA FDD
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID CDMA2000
|
|
|
|
Description: Identifies the PN offset that represents the
|
|
"Physical cell identity" in CDMA2000
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_cdma2000_ie(uint16 phys_cell_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(phys_cell_id, ie_ptr, 9);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_cdma2000_ie(uint8 **ie_ptr,
|
|
uint16 *phys_cell_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phys_cell_id != NULL)
|
|
{
|
|
*phys_cell_id = liblte_bits_2_value(ie_ptr, 9);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID GERAN
|
|
|
|
Description: Contains the Base Station Identity Code (BSIC)
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_geran_ie(LIBLTE_RRC_PHYS_CELL_ID_GERAN_STRUCT *phys_cell_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(phys_cell_id != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(phys_cell_id->ncc, ie_ptr, 3);
|
|
liblte_value_2_bits(phys_cell_id->bcc, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_geran_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PHYS_CELL_ID_GERAN_STRUCT *phys_cell_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phys_cell_id != NULL)
|
|
{
|
|
phys_cell_id->ncc = liblte_bits_2_value(ie_ptr, 3);
|
|
phys_cell_id->bcc = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID UTRA FDD
|
|
|
|
Description: Indicates the physical layer identity of the cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_utra_fdd_ie(uint16 phys_cell_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(phys_cell_id, ie_ptr, 9);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_utra_fdd_ie(uint8 **ie_ptr,
|
|
uint16 *phys_cell_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phys_cell_id != NULL)
|
|
{
|
|
*phys_cell_id = liblte_bits_2_value(ie_ptr, 9);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Phys Cell ID UTRA TDD
|
|
|
|
Description: Indicates the physical layer identity of the cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phys_cell_id_utra_tdd_ie(uint8 phys_cell_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(phys_cell_id, ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phys_cell_id_utra_tdd_ie(uint8 **ie_ptr,
|
|
uint8 *phys_cell_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phys_cell_id != NULL)
|
|
{
|
|
*phys_cell_id = liblte_bits_2_value(ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PLMN Identity
|
|
|
|
Description: Identifies a Public Land Mobile Network
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRUCT *plmn_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 mcc_opt = true;
|
|
uint8 mnc_size;
|
|
|
|
if(plmn_id != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(mcc_opt, ie_ptr, 1);
|
|
|
|
if(true == mcc_opt)
|
|
{
|
|
liblte_value_2_bits((plmn_id->mcc>>8)&0x0F, ie_ptr, 4);
|
|
liblte_value_2_bits((plmn_id->mcc>>4)&0x0F, ie_ptr, 4);
|
|
liblte_value_2_bits((plmn_id->mcc)&0x0F, ie_ptr, 4);
|
|
}
|
|
|
|
if((plmn_id->mnc & 0xFF00) == 0xFF00)
|
|
{
|
|
mnc_size = 2;
|
|
liblte_value_2_bits((mnc_size)-2, ie_ptr, 1);
|
|
liblte_value_2_bits((plmn_id->mnc>>4)&0x0F, ie_ptr, 4);
|
|
liblte_value_2_bits((plmn_id->mnc)&0x0F, ie_ptr, 4);
|
|
}else{
|
|
mnc_size = 3;
|
|
liblte_value_2_bits((mnc_size)-2, ie_ptr, 1);
|
|
liblte_value_2_bits((plmn_id->mnc>>8)&0x0F, ie_ptr, 4);
|
|
liblte_value_2_bits((plmn_id->mnc>>4)&0x0F, ie_ptr, 4);
|
|
liblte_value_2_bits((plmn_id->mnc)&0x0F, ie_ptr, 4);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_plmn_identity_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PLMN_IDENTITY_STRUCT *plmn_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 mcc_opt;
|
|
uint8 mnc_size;
|
|
|
|
if(ie_ptr != NULL &&
|
|
plmn_id != NULL)
|
|
{
|
|
mcc_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == mcc_opt)
|
|
{
|
|
plmn_id->mcc = 0xF000;
|
|
plmn_id->mcc |= (liblte_bits_2_value(ie_ptr, 4) << 8);
|
|
plmn_id->mcc |= (liblte_bits_2_value(ie_ptr, 4) << 4);
|
|
plmn_id->mcc |= liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
}else{
|
|
plmn_id->mcc = LIBLTE_RRC_MCC_NOT_PRESENT;
|
|
}
|
|
|
|
mnc_size = (liblte_bits_2_value(ie_ptr, 1) + 2);
|
|
if(2 == mnc_size)
|
|
{
|
|
plmn_id->mnc = 0xFF00;
|
|
plmn_id->mnc |= (liblte_bits_2_value(ie_ptr, 4) << 4);
|
|
plmn_id->mnc |= liblte_bits_2_value(ie_ptr, 4);
|
|
}else{
|
|
plmn_id->mnc = 0xF000;
|
|
plmn_id->mnc |= (liblte_bits_2_value(ie_ptr, 4) << 8);
|
|
plmn_id->mnc |= (liblte_bits_2_value(ie_ptr, 4) << 4);
|
|
plmn_id->mnc |= liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Pre Registration Info HRPD
|
|
|
|
Description: FIXME
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pre_registration_info_hrpd_ie(LIBLTE_RRC_PRE_REGISTRATION_INFO_HRPD_STRUCT *pre_reg_info_hrpd,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(pre_reg_info_hrpd != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(pre_reg_info_hrpd->pre_reg_zone_id_present, ie_ptr, 1);
|
|
if(0 != pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
|
|
liblte_value_2_bits(pre_reg_info_hrpd->pre_reg_allowed, ie_ptr, 1);
|
|
|
|
if(true == pre_reg_info_hrpd->pre_reg_zone_id_present)
|
|
{
|
|
liblte_value_2_bits(pre_reg_info_hrpd->pre_reg_zone_id, ie_ptr, 8);
|
|
}
|
|
|
|
if(0 != pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size)
|
|
{
|
|
liblte_value_2_bits(pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size - 1, ie_ptr, 1);
|
|
for(i=0; i<pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size; i++)
|
|
{
|
|
liblte_value_2_bits(pre_reg_info_hrpd->secondary_pre_reg_zone_id_list[i], ie_ptr, 8);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pre_registration_info_hrpd_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PRE_REGISTRATION_INFO_HRPD_STRUCT *pre_reg_info_hrpd)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool secondary_pre_reg_zone_id_opt;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pre_reg_info_hrpd != NULL)
|
|
{
|
|
// Optional indicators
|
|
pre_reg_info_hrpd->pre_reg_zone_id_present = liblte_bits_2_value(ie_ptr, 1);
|
|
secondary_pre_reg_zone_id_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
pre_reg_info_hrpd->pre_reg_allowed = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == pre_reg_info_hrpd->pre_reg_zone_id_present)
|
|
{
|
|
pre_reg_info_hrpd->pre_reg_zone_id = liblte_bits_2_value(ie_ptr, 8);
|
|
}
|
|
|
|
if(true == secondary_pre_reg_zone_id_opt)
|
|
{
|
|
pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size = liblte_bits_2_value(ie_ptr, 1) + 1;
|
|
for(i=0; i<pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size; i++)
|
|
{
|
|
pre_reg_info_hrpd->secondary_pre_reg_zone_id_list[i] = liblte_bits_2_value(ie_ptr, 8);
|
|
}
|
|
}else{
|
|
pre_reg_info_hrpd->secondary_pre_reg_zone_id_list_size = 0;
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Q Qual Min
|
|
|
|
Description: Indicates for cell selection/re-selection the
|
|
required minimum received RSRQ level in the (E-UTRA)
|
|
cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_q_qual_min_ie(int8 q_qual_min,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(q_qual_min + 34, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_qual_min_ie(uint8 **ie_ptr,
|
|
int8 *q_qual_min)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
q_qual_min != NULL)
|
|
{
|
|
*q_qual_min = (int8)liblte_bits_2_value(ie_ptr, 5) - 34;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Q Rx Lev Min
|
|
|
|
Description: Indicates the required minimum received RSRP level in
|
|
the (E-UTRA) cell for cell selection/re-selection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_q_rx_lev_min_ie(int16 q_rx_lev_min,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits((q_rx_lev_min / 2) + 70, ie_ptr, 6);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_rx_lev_min_ie(uint8 **ie_ptr,
|
|
int16 *q_rx_lev_min)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
q_rx_lev_min != NULL)
|
|
{
|
|
*q_rx_lev_min = ((int16)liblte_bits_2_value(ie_ptr, 6) - 70) * 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Q Offset Range
|
|
|
|
Description: Indicates a cell or frequency specific offset to be
|
|
applied when evaluating candidates for cell
|
|
reselection or when evaluating triggering conditions
|
|
for measurement reporting
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_q_offset_range_ie(LIBLTE_RRC_Q_OFFSET_RANGE_ENUM q_offset_range,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(q_offset_range, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_offset_range_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_Q_OFFSET_RANGE_ENUM *q_offset_range)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
q_offset_range != NULL)
|
|
{
|
|
*q_offset_range = (LIBLTE_RRC_Q_OFFSET_RANGE_ENUM)liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Q Offset Range Inter RAT
|
|
|
|
Description: Indicates a frequency specific offset to be applied
|
|
when evaluating triggering conditions for
|
|
measurement reporting
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_q_offset_range_inter_rat_ie(int8 q_offset_range_inter_rat,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(q_offset_range_inter_rat + 15, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_q_offset_range_inter_rat_ie(uint8 **ie_ptr,
|
|
int8 *q_offset_range_inter_rat)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
q_offset_range_inter_rat != NULL)
|
|
{
|
|
*q_offset_range_inter_rat = (int8)(liblte_bits_2_value(ie_ptr, 5)) - 15;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Reselection Threshold
|
|
|
|
Description: Indicates an RX level threshold for cell reselection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_reselection_threshold_ie(uint8 resel_thresh,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(resel_thresh / 2, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_reselection_threshold_ie(uint8 **ie_ptr,
|
|
uint8 *resel_thresh)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
resel_thresh != NULL)
|
|
{
|
|
*resel_thresh = liblte_bits_2_value(ie_ptr, 5) * 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Reselection Threshold Q
|
|
|
|
Description: Indicates a quality level threshold for cell
|
|
reselection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_reselection_threshold_q_ie(uint8 resel_thresh_q,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(resel_thresh_q, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_reselection_threshold_q_ie(uint8 **ie_ptr,
|
|
uint8 *resel_thresh_q)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
resel_thresh_q != NULL)
|
|
{
|
|
*resel_thresh_q = liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: S Cell Index
|
|
|
|
Description: Contains a short identity, used to identify an
|
|
SCell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_s_cell_index_ie(uint8 s_cell_idx,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(s_cell_idx - 1, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_s_cell_index_ie(uint8 **ie_ptr,
|
|
uint8 *s_cell_idx)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
s_cell_idx != NULL)
|
|
{
|
|
*s_cell_idx = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Serv Cell Index
|
|
|
|
Description: Contains a short identity, used to identify a
|
|
serving cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_serv_cell_index_ie(uint8 serv_cell_idx,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(serv_cell_idx, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_serv_cell_index_ie(uint8 **ie_ptr,
|
|
uint8 *serv_cell_idx)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
serv_cell_idx != NULL)
|
|
{
|
|
*serv_cell_idx = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Speed State Scale Factors
|
|
|
|
Description: Contains factors, to be applied when the UE is in
|
|
medium or high speed state, used for scaling a
|
|
mobility control related parameter
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_speed_state_scale_factors_ie(LIBLTE_RRC_SPEED_STATE_SCALE_FACTORS_STRUCT *speed_state_scale_factors,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(speed_state_scale_factors != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(speed_state_scale_factors->sf_medium, ie_ptr, 2);
|
|
liblte_value_2_bits(speed_state_scale_factors->sf_high, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_speed_state_scale_factors_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SPEED_STATE_SCALE_FACTORS_STRUCT *speed_state_scale_factors)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
speed_state_scale_factors != NULL)
|
|
{
|
|
speed_state_scale_factors->sf_medium = (LIBLTE_RRC_SSSF_MEDIUM_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
speed_state_scale_factors->sf_high = (LIBLTE_RRC_SSSF_HIGH_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Info List GERAN
|
|
|
|
Description: Contains system information of a GERAN cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: System Time Info CDMA2000
|
|
|
|
Description: Informs the UE about the absolute time in the current
|
|
cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_system_time_info_cdma2000_ie(LIBLTE_RRC_SYSTEM_TIME_INFO_CDMA2000_STRUCT *sys_time_info_cdma2000,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(sys_time_info_cdma2000 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(sys_time_info_cdma2000->cdma_eutra_sync, ie_ptr, 1);
|
|
liblte_value_2_bits(sys_time_info_cdma2000->system_time_async, ie_ptr, 1);
|
|
if(true == sys_time_info_cdma2000->system_time_async)
|
|
{
|
|
liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time >> 17), ie_ptr, 32);
|
|
liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time & 0x1FFFF), ie_ptr, 17);
|
|
}else{
|
|
liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time >> 7), ie_ptr, 32);
|
|
liblte_value_2_bits((uint32)(sys_time_info_cdma2000->system_time & 0x7F), ie_ptr, 7);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_system_time_info_cdma2000_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYSTEM_TIME_INFO_CDMA2000_STRUCT *sys_time_info_cdma2000)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sys_time_info_cdma2000 != NULL)
|
|
{
|
|
sys_time_info_cdma2000->cdma_eutra_sync = liblte_bits_2_value(ie_ptr, 1);
|
|
sys_time_info_cdma2000->system_time_async = liblte_bits_2_value(ie_ptr, 1);
|
|
if(true == sys_time_info_cdma2000->system_time_async)
|
|
{
|
|
sys_time_info_cdma2000->system_time = (uint64)liblte_bits_2_value(ie_ptr, 32) << 17;
|
|
sys_time_info_cdma2000->system_time |= (uint64)liblte_bits_2_value(ie_ptr, 17);
|
|
}else{
|
|
sys_time_info_cdma2000->system_time = (uint64)liblte_bits_2_value(ie_ptr, 32) << 7;
|
|
sys_time_info_cdma2000->system_time |= (uint64)liblte_bits_2_value(ie_ptr, 7);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Tracking Area Code
|
|
|
|
Description: Identifies a tracking area within the scope of a
|
|
PLMN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_tracking_area_code_ie(uint16 tac,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(tac, ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_tracking_area_code_ie(uint8 **ie_ptr,
|
|
uint16 *tac)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
tac != NULL)
|
|
{
|
|
*tac = liblte_bits_2_value(ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: T Reselection
|
|
|
|
Description: Contains the timer T_reselection_rat for E-UTRA,
|
|
UTRA, GERAN, or CDMA2000
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.4
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_t_reselection_ie(uint8 t_resel,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(t_resel, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_t_reselection_ie(uint8 **ie_ptr,
|
|
uint8 *t_resel)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
t_resel != NULL)
|
|
{
|
|
*t_resel = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Next Hop Chaining Count
|
|
|
|
Description: Updates the Kenb key and corresponds to parameter
|
|
NCC
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_next_hop_chaining_count_ie(uint8 next_hop_chaining_count,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(next_hop_chaining_count, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_next_hop_chaining_count_ie(uint8 **ie_ptr,
|
|
uint8 *next_hop_chaining_count)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
next_hop_chaining_count != NULL)
|
|
{
|
|
*next_hop_chaining_count = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Security Algorithm Config
|
|
|
|
Description: Configures AS integrity protection algorithm (SRBs)
|
|
and AS ciphering algorithm (SRBs and DRBs)
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_security_algorithm_config_ie(LIBLTE_RRC_SECURITY_ALGORITHM_CONFIG_STRUCT *sec_alg_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(sec_alg_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sec_alg_cnfg->cipher_alg, ie_ptr, 3);
|
|
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sec_alg_cnfg->int_alg, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_algorithm_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SECURITY_ALGORITHM_CONFIG_STRUCT *sec_alg_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sec_alg_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sec_alg_cnfg->cipher_alg = (LIBLTE_RRC_CIPHERING_ALGORITHM_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sec_alg_cnfg->int_alg = (LIBLTE_RRC_INTEGRITY_PROT_ALGORITHM_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Short MAC I
|
|
|
|
Description: Identifies and verifies the UE at RRC connection
|
|
re-establishment
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.3
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_short_mac_i_ie(uint16 short_mac_i,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(short_mac_i, ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_short_mac_i_ie(uint8 **ie_ptr,
|
|
uint16 *short_mac_i)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
short_mac_i != NULL)
|
|
{
|
|
*short_mac_i = liblte_bits_2_value(ie_ptr, 16);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Antenna Info
|
|
|
|
Description: Specifies the common and the UE specific antenna
|
|
configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_antenna_info_common_ie(LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM antenna_ports_cnt,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(antenna_ports_cnt, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_antenna_info_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM *antenna_ports_cnt)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
antenna_ports_cnt != NULL)
|
|
{
|
|
*antenna_ports_cnt = (LIBLTE_RRC_ANTENNA_PORTS_COUNT_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_antenna_info_dedicated_ie(LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *antenna_info,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(antenna_info != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction_present, ie_ptr, 1);
|
|
|
|
// Transmission Mode
|
|
liblte_value_2_bits(antenna_info->tx_mode, ie_ptr, 3);
|
|
|
|
// Codebook Subset Restriction
|
|
if(antenna_info->codebook_subset_restriction_present)
|
|
{
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction_choice, ie_ptr, 3);
|
|
switch(antenna_info->codebook_subset_restriction_choice)
|
|
{
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3:
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 2);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM3:
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM5:
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM6:
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 4);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM4:
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 6);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM4:
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction >> 32, ie_ptr, 32);
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 32);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM5:
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM6:
|
|
liblte_value_2_bits(antenna_info->codebook_subset_restriction, ie_ptr, 16);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// UE Transmit Antenna Selection
|
|
liblte_value_2_bits(antenna_info->ue_tx_antenna_selection_setup_present, ie_ptr, 1);
|
|
if(antenna_info->ue_tx_antenna_selection_setup_present)
|
|
{
|
|
liblte_value_2_bits(antenna_info->ue_tx_antenna_selection_setup, ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_antenna_info_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT *antenna_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
antenna_info != NULL)
|
|
{
|
|
// Optional indicator
|
|
antenna_info->codebook_subset_restriction_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Transmission Mode
|
|
antenna_info->tx_mode = (LIBLTE_RRC_TRANSMISSION_MODE_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// Codebook Subset Restriction
|
|
if(antenna_info->codebook_subset_restriction_present)
|
|
{
|
|
antenna_info->codebook_subset_restriction_choice = (LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
switch(antenna_info->codebook_subset_restriction_choice)
|
|
{
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM3:
|
|
antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 2);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM3:
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM5:
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM6:
|
|
antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 4);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N2_TM4:
|
|
antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 6);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM4:
|
|
antenna_info->codebook_subset_restriction = (uint64)(liblte_bits_2_value(ie_ptr, 32)) << 32;
|
|
antenna_info->codebook_subset_restriction |= liblte_bits_2_value(ie_ptr, 32);
|
|
break;
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM5:
|
|
case LIBLTE_RRC_CODEBOOK_SUBSET_RESTRICTION_N4_TM6:
|
|
antenna_info->codebook_subset_restriction = liblte_bits_2_value(ie_ptr, 16);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// UE Transmit Antenna Selection
|
|
antenna_info->ue_tx_antenna_selection_setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(antenna_info->ue_tx_antenna_selection_setup_present)
|
|
{
|
|
antenna_info->ue_tx_antenna_selection_setup = (LIBLTE_RRC_UE_TX_ANTENNA_SELECTION_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: CQI Report Config
|
|
|
|
Description: Specifies the CQI reporting configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_cqi_report_config_ie(LIBLTE_RRC_CQI_REPORT_CONFIG_STRUCT *cqi_report_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(cqi_report_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(cqi_report_cnfg->report_mode_aperiodic_present, ie_ptr, 1);
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic_present, ie_ptr, 1);
|
|
|
|
// CQI Report Mode Aperiodic
|
|
if(cqi_report_cnfg->report_mode_aperiodic_present)
|
|
{
|
|
liblte_value_2_bits(cqi_report_cnfg->report_mode_aperiodic, ie_ptr, 3);
|
|
}
|
|
|
|
// Nom PDSCH RS EPRE Offset
|
|
liblte_value_2_bits(cqi_report_cnfg->nom_pdsch_rs_epre_offset + 1, ie_ptr, 3);
|
|
|
|
// CQI Report Periodic
|
|
if(cqi_report_cnfg->report_periodic_present)
|
|
{
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic_setup_present, ie_ptr, 1);
|
|
if(cqi_report_cnfg->report_periodic_setup_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present, ie_ptr, 1);
|
|
|
|
// CQI PUCCH Resource Index
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.pucch_resource_idx, ie_ptr, 11);
|
|
|
|
// CQI PMI Config Index
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.pmi_cnfg_idx, ie_ptr, 10);
|
|
|
|
// CQI Format Indicator Periodic
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.format_ind_periodic, ie_ptr, 1);
|
|
if(LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI == cqi_report_cnfg->report_periodic.format_ind_periodic)
|
|
{
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.format_ind_periodic_subband_k - 1, ie_ptr, 2);
|
|
}
|
|
|
|
// RI Config Index
|
|
if(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present)
|
|
{
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.ri_cnfg_idx, ie_ptr, 10);
|
|
}
|
|
|
|
// Simultaneous Ack/Nack and CQI
|
|
liblte_value_2_bits(cqi_report_cnfg->report_periodic.simult_ack_nack_and_cqi, ie_ptr, 1);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_cqi_report_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_CQI_REPORT_CONFIG_STRUCT *cqi_report_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
cqi_report_cnfg != NULL)
|
|
{
|
|
// Optional indicators
|
|
cqi_report_cnfg->report_mode_aperiodic_present = liblte_bits_2_value(ie_ptr, 1);
|
|
cqi_report_cnfg->report_periodic_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// CQI Report Mode Aperiodic
|
|
if(cqi_report_cnfg->report_mode_aperiodic_present)
|
|
{
|
|
cqi_report_cnfg->report_mode_aperiodic = (LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
}
|
|
|
|
// Nom PDSCH RS EPRE Offset
|
|
cqi_report_cnfg->nom_pdsch_rs_epre_offset = liblte_bits_2_value(ie_ptr, 3) - 1;
|
|
|
|
// CQI Report Periodic
|
|
if(cqi_report_cnfg->report_periodic_present)
|
|
{
|
|
cqi_report_cnfg->report_periodic_setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(cqi_report_cnfg->report_periodic_setup_present)
|
|
{
|
|
// Optional indicator
|
|
cqi_report_cnfg->report_periodic.ri_cnfg_idx_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// CQI PUCCH Resource Index
|
|
cqi_report_cnfg->report_periodic.pucch_resource_idx = liblte_bits_2_value(ie_ptr, 11);
|
|
|
|
// CQI PMI Config Index
|
|
cqi_report_cnfg->report_periodic.pmi_cnfg_idx = liblte_bits_2_value(ie_ptr, 10);
|
|
|
|
// CQI Format Indicator Periodic
|
|
cqi_report_cnfg->report_periodic.format_ind_periodic = (LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI == cqi_report_cnfg->report_periodic.format_ind_periodic)
|
|
{
|
|
cqi_report_cnfg->report_periodic.format_ind_periodic_subband_k = liblte_bits_2_value(ie_ptr, 2) + 1;
|
|
}
|
|
|
|
// RI Config Index
|
|
if(cqi_report_cnfg->report_periodic.ri_cnfg_idx_present)
|
|
{
|
|
cqi_report_cnfg->report_periodic.ri_cnfg_idx = liblte_bits_2_value(ie_ptr, 10);
|
|
}
|
|
|
|
// Simultaneous Ack/Nack and CQI
|
|
cqi_report_cnfg->report_periodic.simult_ack_nack_and_cqi = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Cross Carrier Scheduling Config
|
|
|
|
Description: Specifies the configuration when the cross carrier
|
|
scheduling is used in a cell
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: CSI RS Config
|
|
|
|
Description: Specifies the CSI (Channel State Information)
|
|
reference signal configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: DRB Identity
|
|
|
|
Description: Identifies a DRB used by a UE
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_drb_identity_ie(uint8 drb_id,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(drb_id - 1, ie_ptr, 5);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_drb_identity_ie(uint8 **ie_ptr,
|
|
uint8 *drb_id)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
drb_id != NULL)
|
|
{
|
|
*drb_id = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Logical Channel Config
|
|
|
|
Description: Configures the logical channel parameters
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_logical_channel_config_ie(LIBLTE_RRC_LOGICAL_CHANNEL_CONFIG_STRUCT *log_chan_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(log_chan_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1); // FIXME: Handle extension
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(log_chan_cnfg->ul_specific_params_present, ie_ptr, 1);
|
|
|
|
if(true == log_chan_cnfg->ul_specific_params_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(log_chan_cnfg->ul_specific_params.log_chan_group_present, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(log_chan_cnfg->ul_specific_params.priority - 1, ie_ptr, 4);
|
|
liblte_value_2_bits(log_chan_cnfg->ul_specific_params.prioritized_bit_rate, ie_ptr, 4);
|
|
liblte_value_2_bits(log_chan_cnfg->ul_specific_params.bucket_size_duration, ie_ptr, 3);
|
|
|
|
if(true == log_chan_cnfg->ul_specific_params.log_chan_group_present)
|
|
{
|
|
liblte_value_2_bits(log_chan_cnfg->ul_specific_params.log_chan_group, ie_ptr, 2);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_logical_channel_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_LOGICAL_CHANNEL_CONFIG_STRUCT *log_chan_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext;
|
|
|
|
if(ie_ptr != NULL &&
|
|
log_chan_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(ie_ptr, 1); // FIXME: Handle extension
|
|
|
|
// Optional indicator
|
|
log_chan_cnfg->ul_specific_params_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == log_chan_cnfg->ul_specific_params_present)
|
|
{
|
|
// Optional indicator
|
|
log_chan_cnfg->ul_specific_params.log_chan_group_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
log_chan_cnfg->ul_specific_params.priority = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
log_chan_cnfg->ul_specific_params.prioritized_bit_rate = (LIBLTE_RRC_PRIORITIZED_BIT_RATE_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
log_chan_cnfg->ul_specific_params.bucket_size_duration = (LIBLTE_RRC_BUCKET_SIZE_DURATION_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
if(true == log_chan_cnfg->ul_specific_params.log_chan_group_present)
|
|
{
|
|
log_chan_cnfg->ul_specific_params.log_chan_group = liblte_bits_2_value(ie_ptr, 2);
|
|
}
|
|
}
|
|
|
|
// Consume non-critical extensions
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: MAC Main Config
|
|
|
|
Description: Specifies the MAC main configuration for signalling
|
|
and data radio bearers
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_mac_main_config_ie(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_main_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext = false;
|
|
|
|
if(mac_main_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(mac_main_cnfg->phr_cnfg_present, ie_ptr, 1);
|
|
|
|
// ULSCH Config
|
|
if(mac_main_cnfg->ulsch_cnfg_present)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present, ie_ptr, 1);
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present, ie_ptr, 1);
|
|
|
|
// Max HARQ TX
|
|
if(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present)
|
|
{
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.max_harq_tx, ie_ptr, 4);
|
|
}
|
|
|
|
// Periodic BSR Timer
|
|
if(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present)
|
|
{
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer, ie_ptr, 4);
|
|
}
|
|
|
|
// Re-TX BSR Timer
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.retx_bsr_timer, ie_ptr, 3);
|
|
|
|
// TTI Bundling
|
|
liblte_value_2_bits(mac_main_cnfg->ulsch_cnfg.tti_bundling, ie_ptr, 1);
|
|
}
|
|
|
|
// DRX Config
|
|
if(mac_main_cnfg->drx_cnfg_present)
|
|
{
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.setup_present, ie_ptr, 1);
|
|
if(mac_main_cnfg->drx_cnfg.setup_present)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_present, ie_ptr, 1);
|
|
|
|
// On Duration Timer
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.on_duration_timer, ie_ptr, 4);
|
|
|
|
// DRX Inactivity Timer
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.drx_inactivity_timer, ie_ptr, 5);
|
|
|
|
// DRX Retransmission Timer
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.drx_retx_timer, ie_ptr, 3);
|
|
|
|
// Long DRX Cycle Start Offset
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice, ie_ptr, 4);
|
|
switch(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice)
|
|
{
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF10:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 4);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF20:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF32:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 5);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF40:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF64:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 6);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF80:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF128:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 7);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF160:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF256:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 8);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF320:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF512:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 9);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF640:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1024:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 10);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1280:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2048:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 11);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2560:
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset, ie_ptr, 12);
|
|
break;
|
|
}
|
|
|
|
// Short DRX
|
|
if(mac_main_cnfg->drx_cnfg.short_drx_present)
|
|
{
|
|
// Short DRX Cycle
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_cycle, ie_ptr, 4);
|
|
|
|
// DRX Short Cycle Timer
|
|
liblte_value_2_bits(mac_main_cnfg->drx_cnfg.short_drx_cycle_timer - 1, ie_ptr, 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Time Alignment Timer Dedicated
|
|
liblte_rrc_pack_time_alignment_timer_ie(mac_main_cnfg->time_alignment_timer, ie_ptr);
|
|
|
|
// PHR Config
|
|
if(mac_main_cnfg->phr_cnfg_present)
|
|
{
|
|
liblte_value_2_bits(mac_main_cnfg->phr_cnfg.setup_present, ie_ptr, 1);
|
|
if(mac_main_cnfg->phr_cnfg.setup_present)
|
|
{
|
|
// Periodic PHR Timer
|
|
liblte_value_2_bits(mac_main_cnfg->phr_cnfg.periodic_phr_timer, ie_ptr, 3);
|
|
|
|
// Prohibit PHR Timer
|
|
liblte_value_2_bits(mac_main_cnfg->phr_cnfg.prohibit_phr_timer, ie_ptr, 3);
|
|
|
|
// DL Pathloss Change
|
|
liblte_value_2_bits(mac_main_cnfg->phr_cnfg.dl_pathloss_change, ie_ptr, 2);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_mac_main_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_main_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext;
|
|
|
|
if(ie_ptr != NULL &&
|
|
mac_main_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
mac_main_cnfg->ulsch_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mac_main_cnfg->drx_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mac_main_cnfg->phr_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// ULSCH Config
|
|
if(mac_main_cnfg->ulsch_cnfg_present)
|
|
{
|
|
// Optional indicators
|
|
mac_main_cnfg->ulsch_cnfg.max_harq_tx_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Max HARQ TX
|
|
if(mac_main_cnfg->ulsch_cnfg.max_harq_tx_present)
|
|
{
|
|
mac_main_cnfg->ulsch_cnfg.max_harq_tx = (LIBLTE_RRC_MAX_HARQ_TX_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
// Periodic BSR Timer
|
|
if(mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer_present)
|
|
{
|
|
mac_main_cnfg->ulsch_cnfg.periodic_bsr_timer = (LIBLTE_RRC_PERIODIC_BSR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
// Re-TX BSR Timer
|
|
mac_main_cnfg->ulsch_cnfg.retx_bsr_timer = (LIBLTE_RRC_RETRANSMISSION_BSR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// TTI Bundling
|
|
mac_main_cnfg->ulsch_cnfg.tti_bundling = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
// DRX Config
|
|
if(mac_main_cnfg->drx_cnfg_present)
|
|
{
|
|
mac_main_cnfg->drx_cnfg.setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(mac_main_cnfg->drx_cnfg.setup_present)
|
|
{
|
|
// Optional indicators
|
|
mac_main_cnfg->drx_cnfg.short_drx_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// On Duration Timer
|
|
mac_main_cnfg->drx_cnfg.on_duration_timer = (LIBLTE_RRC_ON_DURATION_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// DRX Inactivity Timer
|
|
mac_main_cnfg->drx_cnfg.drx_inactivity_timer = (LIBLTE_RRC_DRX_INACTIVITY_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
// DRX Retransmission Timer
|
|
mac_main_cnfg->drx_cnfg.drx_retx_timer = (LIBLTE_RRC_DRX_RETRANSMISSION_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// Long DRX Cycle Short Offset
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice = (LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_CHOICE_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
switch(mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset_choice)
|
|
{
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF10:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 4);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF20:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF32:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 5);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF40:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF64:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 6);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF80:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF128:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 7);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF160:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF256:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 8);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF320:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF512:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 9);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF640:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1024:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 10);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF1280:
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2048:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 11);
|
|
break;
|
|
case LIBLTE_RRC_LONG_DRX_CYCLE_START_OFFSET_SF2560:
|
|
mac_main_cnfg->drx_cnfg.long_drx_cycle_start_offset = liblte_bits_2_value(ie_ptr, 12);
|
|
break;
|
|
}
|
|
|
|
// Short DRX
|
|
if(mac_main_cnfg->drx_cnfg.short_drx_present)
|
|
{
|
|
// Short DRX Cycle
|
|
mac_main_cnfg->drx_cnfg.short_drx_cycle = (LIBLTE_RRC_SHORT_DRX_CYCLE_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// DRX Short Cycle Timer
|
|
mac_main_cnfg->drx_cnfg.short_drx_cycle_timer = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Time Alignment Timer Dedicated
|
|
liblte_rrc_unpack_time_alignment_timer_ie(ie_ptr, &mac_main_cnfg->time_alignment_timer);
|
|
|
|
// PHR Config
|
|
if(mac_main_cnfg->phr_cnfg_present)
|
|
{
|
|
mac_main_cnfg->phr_cnfg.setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(mac_main_cnfg->phr_cnfg.setup_present)
|
|
{
|
|
// Periodic PHR Timer
|
|
mac_main_cnfg->phr_cnfg.periodic_phr_timer = (LIBLTE_RRC_PERIODIC_PHR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// Prohibit PHR Timer
|
|
mac_main_cnfg->phr_cnfg.prohibit_phr_timer = (LIBLTE_RRC_PROHIBIT_PHR_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// DL Pathloss Change
|
|
mac_main_cnfg->phr_cnfg.dl_pathloss_change = (LIBLTE_RRC_DL_PATHLOSS_CHANGE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
}
|
|
}
|
|
|
|
// Consume non-critical extensions
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PDCP Config
|
|
|
|
Description: Sets the configurable PDCP parameters for data
|
|
radio bearers
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pdcp_config_ie(LIBLTE_RRC_PDCP_CONFIG_STRUCT *pdcp_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(pdcp_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(pdcp_cnfg->discard_timer_present, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->rlc_am_status_report_required_present, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->rlc_um_pdcp_sn_size_present, ie_ptr, 1);
|
|
|
|
// Discard Timer
|
|
if(pdcp_cnfg->discard_timer_present)
|
|
{
|
|
liblte_value_2_bits(pdcp_cnfg->discard_timer, ie_ptr, 3);
|
|
}
|
|
|
|
// RLC AM
|
|
if(pdcp_cnfg->rlc_am_status_report_required_present)
|
|
{
|
|
liblte_value_2_bits(pdcp_cnfg->rlc_am_status_report_required, ie_ptr, 1);
|
|
}
|
|
|
|
// RLC UM
|
|
if(pdcp_cnfg->rlc_um_pdcp_sn_size_present)
|
|
{
|
|
liblte_value_2_bits(pdcp_cnfg->rlc_um_pdcp_sn_size, ie_ptr, 1);
|
|
}
|
|
|
|
// Header Compression
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_rohc, ie_ptr, 1);
|
|
if(pdcp_cnfg->hdr_compression_rohc)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Max CID
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_max_cid - 1, ie_ptr, 14);
|
|
|
|
// Profiles
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0001, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0002, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0003, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0004, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0006, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0101, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0102, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0103, ie_ptr, 1);
|
|
liblte_value_2_bits(pdcp_cnfg->hdr_compression_profile_0104, ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdcp_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PDCP_CONFIG_STRUCT *pdcp_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pdcp_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
pdcp_cnfg->discard_timer_present = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->rlc_am_status_report_required_present = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->rlc_um_pdcp_sn_size_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Discard Timer
|
|
if(pdcp_cnfg->discard_timer_present)
|
|
{
|
|
pdcp_cnfg->discard_timer = (LIBLTE_RRC_DISCARD_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
}
|
|
|
|
// RLC AM
|
|
if(pdcp_cnfg->rlc_am_status_report_required_present)
|
|
{
|
|
pdcp_cnfg->rlc_am_status_report_required = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
// RLC UM
|
|
if(pdcp_cnfg->rlc_um_pdcp_sn_size_present)
|
|
{
|
|
pdcp_cnfg->rlc_um_pdcp_sn_size = (LIBLTE_RRC_PDCP_SN_SIZE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
// Header Compression
|
|
pdcp_cnfg->hdr_compression_rohc = liblte_bits_2_value(ie_ptr, 1);
|
|
if(pdcp_cnfg->hdr_compression_rohc)
|
|
{
|
|
// Extension indicator
|
|
bool ext2 = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Max CID
|
|
pdcp_cnfg->hdr_compression_max_cid = liblte_bits_2_value(ie_ptr, 14) + 1;
|
|
|
|
// Profiles
|
|
pdcp_cnfg->hdr_compression_profile_0001 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0002 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0003 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0004 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0006 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0101 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0102 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0103 = liblte_bits_2_value(ie_ptr, 1);
|
|
pdcp_cnfg->hdr_compression_profile_0104 = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext2, __func__, ie_ptr);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PDSCH Config
|
|
|
|
Description: Specifies the common and the UE specific PDSCH
|
|
configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pdsch_config_common_ie(LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT *pdsch_config,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(pdsch_config != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(pdsch_config->rs_power + 60, ie_ptr, 7);
|
|
liblte_value_2_bits(pdsch_config->p_b, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdsch_config_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PDSCH_CONFIG_COMMON_STRUCT *pdsch_config)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pdsch_config != NULL)
|
|
{
|
|
pdsch_config->rs_power = liblte_bits_2_value(ie_ptr, 7) - 60;
|
|
pdsch_config->p_b = liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pdsch_config_dedicated_ie(LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM p_a,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(p_a, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pdsch_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM *p_a)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(p_a != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
*p_a = (LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PHICH Config
|
|
|
|
Description: Specifies the PHICH configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_phich_config_ie(LIBLTE_RRC_PHICH_CONFIG_STRUCT *phich_config,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(phich_config != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(phich_config->dur, ie_ptr, 1);
|
|
liblte_value_2_bits(phich_config->res, ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_phich_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PHICH_CONFIG_STRUCT *phich_config)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phich_config != NULL)
|
|
{
|
|
phich_config->dur = (LIBLTE_RRC_PHICH_DURATION_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
phich_config->res = (LIBLTE_RRC_PHICH_RESOURCE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Physical Config Dedicated
|
|
|
|
Description: Specifies the UE specific physical channel
|
|
configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_physical_config_dedicated_ie(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg_ded,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext = false;
|
|
|
|
if(phy_cnfg_ded != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(phy_cnfg_ded->pdsch_cnfg_ded_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->pucch_cnfg_ded_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->pusch_cnfg_ded_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->ul_pwr_ctrl_ded_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->cqi_report_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->srs_ul_cnfg_ded_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->antenna_info_present, ie_ptr, 1);
|
|
liblte_value_2_bits(phy_cnfg_ded->sched_request_cnfg_present, ie_ptr, 1);
|
|
|
|
// PDSCH Config
|
|
if(phy_cnfg_ded->pdsch_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_pdsch_config_dedicated_ie(phy_cnfg_ded->pdsch_cnfg_ded, ie_ptr);
|
|
}
|
|
|
|
// PUCCH Config
|
|
if(phy_cnfg_ded->pucch_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_pucch_config_dedicated_ie(&phy_cnfg_ded->pucch_cnfg_ded, ie_ptr);
|
|
}
|
|
|
|
// PUSCH Config
|
|
if(phy_cnfg_ded->pusch_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_pusch_config_dedicated_ie(&phy_cnfg_ded->pusch_cnfg_ded, ie_ptr);
|
|
}
|
|
|
|
// Uplink Power Control
|
|
if(phy_cnfg_ded->ul_pwr_ctrl_ded_present)
|
|
{
|
|
liblte_rrc_pack_ul_power_control_dedicated_ie(&phy_cnfg_ded->ul_pwr_ctrl_ded, ie_ptr);
|
|
}
|
|
|
|
// TPC PDCCH Config PUCCH
|
|
if(phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present)
|
|
{
|
|
liblte_rrc_pack_tpc_pdcch_config_ie(&phy_cnfg_ded->tpc_pdcch_cnfg_pucch, ie_ptr);
|
|
}
|
|
|
|
// TPC PDCCH Config PUSCH
|
|
if(phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present)
|
|
{
|
|
liblte_rrc_pack_tpc_pdcch_config_ie(&phy_cnfg_ded->tpc_pdcch_cnfg_pusch, ie_ptr);
|
|
}
|
|
|
|
// CQI Report Config
|
|
if(phy_cnfg_ded->cqi_report_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_cqi_report_config_ie(&phy_cnfg_ded->cqi_report_cnfg, ie_ptr);
|
|
}
|
|
|
|
// SRS UL Config
|
|
if(phy_cnfg_ded->srs_ul_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_srs_ul_config_dedicated_ie(&phy_cnfg_ded->srs_ul_cnfg_ded, ie_ptr);
|
|
}
|
|
|
|
// Antenna Info
|
|
if(phy_cnfg_ded->antenna_info_present)
|
|
{
|
|
liblte_value_2_bits(phy_cnfg_ded->antenna_info_default_value, ie_ptr, 1);
|
|
if(!phy_cnfg_ded->antenna_info_default_value)
|
|
{
|
|
liblte_rrc_pack_antenna_info_dedicated_ie(&phy_cnfg_ded->antenna_info_explicit_value, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// Scheduling Request Config
|
|
if(phy_cnfg_ded->sched_request_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_scheduling_request_config_ie(&phy_cnfg_ded->sched_request_cnfg, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_physical_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg_ded)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext;
|
|
|
|
if(ie_ptr != NULL &&
|
|
phy_cnfg_ded != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
phy_cnfg_ded->pdsch_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->pucch_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->pusch_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->ul_pwr_ctrl_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->cqi_report_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->srs_ul_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->antenna_info_present = liblte_bits_2_value(ie_ptr, 1);
|
|
phy_cnfg_ded->sched_request_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// PDSCH Config
|
|
if(phy_cnfg_ded->pdsch_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_pdsch_config_dedicated_ie(ie_ptr, &phy_cnfg_ded->pdsch_cnfg_ded);
|
|
}
|
|
|
|
// PUCCH Config
|
|
if(phy_cnfg_ded->pucch_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_pucch_config_dedicated_ie(ie_ptr, &phy_cnfg_ded->pucch_cnfg_ded);
|
|
}
|
|
|
|
// PUSCH Config
|
|
if(phy_cnfg_ded->pusch_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_pusch_config_dedicated_ie(ie_ptr, &phy_cnfg_ded->pusch_cnfg_ded);
|
|
}
|
|
|
|
// Uplink Power Control
|
|
if(phy_cnfg_ded->ul_pwr_ctrl_ded_present)
|
|
{
|
|
liblte_rrc_unpack_ul_power_control_dedicated_ie(ie_ptr, &phy_cnfg_ded->ul_pwr_ctrl_ded);
|
|
}
|
|
|
|
// TPC PDCCH Config PUCCH
|
|
if(phy_cnfg_ded->tpc_pdcch_cnfg_pucch_present)
|
|
{
|
|
liblte_rrc_unpack_tpc_pdcch_config_ie(ie_ptr, &phy_cnfg_ded->tpc_pdcch_cnfg_pucch);
|
|
}
|
|
|
|
// TPC PDCCH Config PUSCH
|
|
if(phy_cnfg_ded->tpc_pdcch_cnfg_pusch_present)
|
|
{
|
|
liblte_rrc_unpack_tpc_pdcch_config_ie(ie_ptr, &phy_cnfg_ded->tpc_pdcch_cnfg_pusch);
|
|
}
|
|
|
|
// CQI Report Config
|
|
if(phy_cnfg_ded->cqi_report_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_cqi_report_config_ie(ie_ptr, &phy_cnfg_ded->cqi_report_cnfg);
|
|
}
|
|
|
|
// SRS UL Config
|
|
if(phy_cnfg_ded->srs_ul_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_srs_ul_config_dedicated_ie(ie_ptr, &phy_cnfg_ded->srs_ul_cnfg_ded);
|
|
}
|
|
|
|
// Antenna Info
|
|
if(phy_cnfg_ded->antenna_info_present)
|
|
{
|
|
phy_cnfg_ded->antenna_info_default_value = liblte_bits_2_value(ie_ptr, 1);
|
|
if(!phy_cnfg_ded->antenna_info_default_value)
|
|
{
|
|
liblte_rrc_unpack_antenna_info_dedicated_ie(ie_ptr, &phy_cnfg_ded->antenna_info_explicit_value);
|
|
}
|
|
}
|
|
|
|
// Scheduling Request Config
|
|
if(phy_cnfg_ded->sched_request_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_scheduling_request_config_ie(ie_ptr, &phy_cnfg_ded->sched_request_cnfg);
|
|
}
|
|
|
|
// Consume non-critical extensions
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: P Max
|
|
|
|
Description: Limits the UE's uplink transmission power on a
|
|
carrier frequency and is used to calculate the
|
|
parameter P Compensation
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_p_max_ie(int8 p_max,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(p_max + 30, ie_ptr, 6);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_p_max_ie(uint8 **ie_ptr,
|
|
int8 *p_max)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
p_max != NULL)
|
|
{
|
|
*p_max = (int8)liblte_bits_2_value(ie_ptr, 6) - 30;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PRACH Config
|
|
|
|
Description: Specifies the PRACH configuration in the system
|
|
information and in the mobility control information
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_sib_ie(LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *prach_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(prach_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(prach_cnfg->root_sequence_index, ie_ptr, 10);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_config_index, ie_ptr, 6);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.high_speed_flag, ie_ptr, 1);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.zero_correlation_zone_config, ie_ptr, 4);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_freq_offset, ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_prach_config_sib_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PRACH_CONFIG_SIB_STRUCT *prach_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
prach_cnfg != NULL)
|
|
{
|
|
prach_cnfg->root_sequence_index = liblte_bits_2_value(ie_ptr, 10);
|
|
prach_cnfg->prach_cnfg_info.prach_config_index = liblte_bits_2_value(ie_ptr, 6);
|
|
prach_cnfg->prach_cnfg_info.high_speed_flag = liblte_bits_2_value(ie_ptr, 1);
|
|
prach_cnfg->prach_cnfg_info.zero_correlation_zone_config = liblte_bits_2_value(ie_ptr, 4);
|
|
prach_cnfg->prach_cnfg_info.prach_freq_offset = liblte_bits_2_value(ie_ptr, 7);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_ie(LIBLTE_RRC_PRACH_CONFIG_STRUCT *prach_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(prach_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info_present, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(prach_cnfg->root_sequence_index, ie_ptr, 10);
|
|
|
|
if(true == prach_cnfg->prach_cnfg_info_present)
|
|
{
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_config_index, ie_ptr, 6);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.high_speed_flag, ie_ptr, 1);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.zero_correlation_zone_config, ie_ptr, 4);
|
|
liblte_value_2_bits(prach_cnfg->prach_cnfg_info.prach_freq_offset, ie_ptr, 7);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_prach_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PRACH_CONFIG_STRUCT *prach_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
prach_cnfg != NULL)
|
|
{
|
|
// Optional indicator
|
|
prach_cnfg->prach_cnfg_info_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
prach_cnfg->root_sequence_index = liblte_bits_2_value(ie_ptr, 10);
|
|
|
|
if(true == prach_cnfg->prach_cnfg_info_present)
|
|
{
|
|
prach_cnfg->prach_cnfg_info.prach_config_index = liblte_bits_2_value(ie_ptr, 6);
|
|
prach_cnfg->prach_cnfg_info.high_speed_flag = liblte_bits_2_value(ie_ptr, 1);
|
|
prach_cnfg->prach_cnfg_info.zero_correlation_zone_config = liblte_bits_2_value(ie_ptr, 4);
|
|
prach_cnfg->prach_cnfg_info.prach_freq_offset = liblte_bits_2_value(ie_ptr, 7);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_prach_config_scell_r10_ie(uint8 prach_cnfg_idx,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(prach_cnfg_idx, ie_ptr, 6);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_prach_config_scell_r10_ie(uint8 **ie_ptr,
|
|
uint8 *prach_cnfg_idx)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
prach_cnfg_idx != NULL)
|
|
{
|
|
*prach_cnfg_idx = liblte_bits_2_value(ie_ptr, 6);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Presence Antenna Port 1
|
|
|
|
Description: Indicates whether all the neighboring cells use
|
|
antenna port 1
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_presence_antenna_port_1_ie(bool presence_ant_port_1,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(presence_ant_port_1, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_presence_antenna_port_1_ie(uint8 **ie_ptr,
|
|
bool *presence_ant_port_1)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
presence_ant_port_1 != NULL)
|
|
{
|
|
*presence_ant_port_1 = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PUCCH Config
|
|
|
|
Description: Specifies the common and the UE specific PUCCH
|
|
configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pucch_config_common_ie(LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT *pucch_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(pucch_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(pucch_cnfg->delta_pucch_shift, ie_ptr, 2);
|
|
liblte_value_2_bits(pucch_cnfg->n_rb_cqi, ie_ptr, 7);
|
|
liblte_value_2_bits(pucch_cnfg->n_cs_an, ie_ptr, 3);
|
|
liblte_value_2_bits(pucch_cnfg->n1_pucch_an, ie_ptr, 11);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pucch_config_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PUCCH_CONFIG_COMMON_STRUCT *pucch_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pucch_cnfg != NULL)
|
|
{
|
|
pucch_cnfg->delta_pucch_shift = (LIBLTE_RRC_DELTA_PUCCH_SHIFT_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
pucch_cnfg->n_rb_cqi = liblte_bits_2_value(ie_ptr, 7);
|
|
pucch_cnfg->n_cs_an = liblte_bits_2_value(ie_ptr, 3);
|
|
pucch_cnfg->n1_pucch_an = liblte_bits_2_value(ie_ptr, 11);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pucch_config_dedicated_ie(LIBLTE_RRC_PUCCH_CONFIG_DEDICATED_STRUCT *pucch_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(pucch_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(pucch_cnfg->tdd_ack_nack_feedback_mode_present, ie_ptr, 1);
|
|
|
|
// Ack/Nack Repetition
|
|
liblte_value_2_bits(pucch_cnfg->ack_nack_repetition_setup_present, ie_ptr, 1);
|
|
if(pucch_cnfg->ack_nack_repetition_setup_present)
|
|
{
|
|
// Repetition Factor
|
|
liblte_value_2_bits(pucch_cnfg->ack_nack_repetition_factor, ie_ptr, 2);
|
|
|
|
// N1 PUCCH AN Repetition
|
|
liblte_value_2_bits(pucch_cnfg->ack_nack_repetition_n1_pucch_an, ie_ptr, 11);
|
|
}
|
|
|
|
// TDD Ack/Nack Feedback Mode
|
|
if(pucch_cnfg->tdd_ack_nack_feedback_mode_present)
|
|
{
|
|
liblte_value_2_bits(pucch_cnfg->tdd_ack_nack_feedback_mode, ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pucch_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PUCCH_CONFIG_DEDICATED_STRUCT *pucch_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pucch_cnfg != NULL)
|
|
{
|
|
// Optional indicator
|
|
pucch_cnfg->tdd_ack_nack_feedback_mode_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Ack/Nack Repetition
|
|
pucch_cnfg->ack_nack_repetition_setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(pucch_cnfg->ack_nack_repetition_setup_present)
|
|
{
|
|
// Repetition Factor
|
|
pucch_cnfg->ack_nack_repetition_factor = (LIBLTE_RRC_ACK_NACK_REPETITION_FACTOR_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
// N1 PUCCH AN Repetition
|
|
pucch_cnfg->ack_nack_repetition_n1_pucch_an = liblte_bits_2_value(ie_ptr, 11);
|
|
}
|
|
|
|
// TDD Ack/Nack Feedback Mode
|
|
if(pucch_cnfg->tdd_ack_nack_feedback_mode_present)
|
|
{
|
|
pucch_cnfg->tdd_ack_nack_feedback_mode = (LIBLTE_RRC_TDD_ACK_NACK_FEEDBACK_MODE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: PUSCH Config
|
|
|
|
Description: Specifies the common and the UE specific PUSCH
|
|
configuration and the reference signal configuration
|
|
for PUSCH and PUCCH
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_common_ie(LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT *pusch_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(pusch_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// PUSCH Config Basic
|
|
liblte_value_2_bits(pusch_cnfg->n_sb - 1, ie_ptr, 2);
|
|
liblte_value_2_bits(pusch_cnfg->hopping_mode, ie_ptr, 1);
|
|
liblte_value_2_bits(pusch_cnfg->pusch_hopping_offset, ie_ptr, 7);
|
|
liblte_value_2_bits(pusch_cnfg->enable_64_qam, ie_ptr, 1);
|
|
|
|
// UL Reference Signals PUSCH
|
|
liblte_value_2_bits(pusch_cnfg->ul_rs.group_hopping_enabled, ie_ptr, 1);
|
|
liblte_value_2_bits(pusch_cnfg->ul_rs.group_assignment_pusch, ie_ptr, 5);
|
|
liblte_value_2_bits(pusch_cnfg->ul_rs.sequence_hopping_enabled, ie_ptr, 1);
|
|
liblte_value_2_bits(pusch_cnfg->ul_rs.cyclic_shift, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PUSCH_CONFIG_COMMON_STRUCT *pusch_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pusch_cnfg != NULL)
|
|
{
|
|
// PUSCH Config Basic
|
|
pusch_cnfg->n_sb = liblte_bits_2_value(ie_ptr, 2) + 1;
|
|
pusch_cnfg->hopping_mode = (LIBLTE_RRC_HOPPING_MODE_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
pusch_cnfg->pusch_hopping_offset = liblte_bits_2_value(ie_ptr, 7);
|
|
pusch_cnfg->enable_64_qam = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// UL Reference Signals PUSCH
|
|
pusch_cnfg->ul_rs.group_hopping_enabled = liblte_bits_2_value(ie_ptr, 1);
|
|
pusch_cnfg->ul_rs.group_assignment_pusch = liblte_bits_2_value(ie_ptr, 5);
|
|
pusch_cnfg->ul_rs.sequence_hopping_enabled = liblte_bits_2_value(ie_ptr, 1);
|
|
pusch_cnfg->ul_rs.cyclic_shift = liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pusch_config_dedicated_ie(LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT *pusch_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(pusch_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Beta Offset ACK Index
|
|
liblte_value_2_bits(pusch_cnfg->beta_offset_ack_idx, ie_ptr, 4);
|
|
|
|
// Beta Offset RI Index
|
|
liblte_value_2_bits(pusch_cnfg->beta_offset_ri_idx, ie_ptr, 4);
|
|
|
|
// Beta Offset CQI Index
|
|
liblte_value_2_bits(pusch_cnfg->beta_offset_cqi_idx, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pusch_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT *pusch_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
pusch_cnfg != NULL)
|
|
{
|
|
// Beta Offset ACK Index
|
|
pusch_cnfg->beta_offset_ack_idx = liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Beta Offset RI Index
|
|
pusch_cnfg->beta_offset_ri_idx = liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Beta Offset CQI Index
|
|
pusch_cnfg->beta_offset_cqi_idx = liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RACH Config Common
|
|
|
|
Description: Specifies the generic random access parameters
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rach_config_common_ie(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rach_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Preamble Info
|
|
liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.present, ie_ptr, 1);
|
|
liblte_value_2_bits(rach_cnfg->num_ra_preambles, ie_ptr, 4);
|
|
if(true == rach_cnfg->preambles_group_a_cnfg.present)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.size_of_ra, ie_ptr, 4);
|
|
liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.msg_size, ie_ptr, 2);
|
|
liblte_value_2_bits(rach_cnfg->preambles_group_a_cnfg.msg_pwr_offset_group_b, ie_ptr, 3);
|
|
}
|
|
|
|
// Power Ramping Parameters
|
|
liblte_value_2_bits(rach_cnfg->pwr_ramping_step, ie_ptr, 2);
|
|
liblte_value_2_bits(rach_cnfg->preamble_init_rx_target_pwr, ie_ptr, 4);
|
|
|
|
// RA Supervision Info
|
|
liblte_value_2_bits(rach_cnfg->preamble_trans_max, ie_ptr, 4);
|
|
liblte_value_2_bits(rach_cnfg->ra_resp_win_size, ie_ptr, 3);
|
|
liblte_value_2_bits(rach_cnfg->mac_con_res_timer, ie_ptr, 3);
|
|
|
|
liblte_value_2_bits(rach_cnfg->max_harq_msg3_tx - 1, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rach_config_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT *rach_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rach_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Preamble Info
|
|
rach_cnfg->preambles_group_a_cnfg.present = liblte_bits_2_value(ie_ptr, 1);
|
|
rach_cnfg->num_ra_preambles = (LIBLTE_RRC_NUMBER_OF_RA_PREAMBLES_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
if(true == rach_cnfg->preambles_group_a_cnfg.present)
|
|
{
|
|
// Extension indicator
|
|
bool ext2 = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
rach_cnfg->preambles_group_a_cnfg.size_of_ra = (LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
rach_cnfg->preambles_group_a_cnfg.msg_size = (LIBLTE_RRC_MESSAGE_SIZE_GROUP_A_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
rach_cnfg->preambles_group_a_cnfg.msg_pwr_offset_group_b = (LIBLTE_RRC_MESSAGE_POWER_OFFSET_GROUP_B_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext2, __func__, ie_ptr);
|
|
|
|
}else{
|
|
rach_cnfg->preambles_group_a_cnfg.size_of_ra = (LIBLTE_RRC_SIZE_OF_RA_PREAMBLES_GROUP_A_ENUM)rach_cnfg->num_ra_preambles;
|
|
}
|
|
|
|
// Power Ramping Parameters
|
|
rach_cnfg->pwr_ramping_step = (LIBLTE_RRC_POWER_RAMPING_STEP_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
rach_cnfg->preamble_init_rx_target_pwr = (LIBLTE_RRC_PREAMBLE_INITIAL_RECEIVED_TARGET_POWER_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// RA Supervision Info
|
|
rach_cnfg->preamble_trans_max = (LIBLTE_RRC_PREAMBLE_TRANS_MAX_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
rach_cnfg->ra_resp_win_size = (LIBLTE_RRC_RA_RESPONSE_WINDOW_SIZE_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
rach_cnfg->mac_con_res_timer = (LIBLTE_RRC_MAC_CONTENTION_RESOLUTION_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
rach_cnfg->max_harq_msg3_tx = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RACH Config Dedicated
|
|
|
|
Description: Specifies the dedicated random access parameters
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rach_config_dedicated_ie(LIBLTE_RRC_RACH_CONFIG_DEDICATED_STRUCT *rach_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rach_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(rach_cnfg->preamble_index, ie_ptr, 6);
|
|
liblte_value_2_bits(rach_cnfg->prach_mask_index, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rach_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RACH_CONFIG_DEDICATED_STRUCT *rach_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rach_cnfg != NULL)
|
|
{
|
|
rach_cnfg->preamble_index = liblte_bits_2_value(ie_ptr, 6);
|
|
rach_cnfg->prach_mask_index = liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Radio Resource Config Common
|
|
|
|
Description: Specifies the common radio resource configurations
|
|
in the system information and in the mobility control
|
|
information, including random access parameters
|
|
and static physical layer parameters
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_sib_ie(LIBLTE_RRC_RR_CONFIG_COMMON_SIB_STRUCT *rr_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rr_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_rach_config_common_ie(&rr_cnfg->rach_cnfg, ie_ptr);
|
|
|
|
// BCCH Config
|
|
liblte_value_2_bits(rr_cnfg->bcch_cnfg.modification_period_coeff, ie_ptr, 2);
|
|
|
|
// PCCH Config
|
|
liblte_value_2_bits(rr_cnfg->pcch_cnfg.default_paging_cycle, ie_ptr, 2);
|
|
liblte_value_2_bits(rr_cnfg->pcch_cnfg.nB, ie_ptr, 3);
|
|
|
|
liblte_rrc_pack_prach_config_sib_ie(&rr_cnfg->prach_cnfg, ie_ptr);
|
|
liblte_rrc_pack_pdsch_config_common_ie(&rr_cnfg->pdsch_cnfg, ie_ptr);
|
|
liblte_rrc_pack_pusch_config_common_ie(&rr_cnfg->pusch_cnfg, ie_ptr);
|
|
liblte_rrc_pack_pucch_config_common_ie(&rr_cnfg->pucch_cnfg, ie_ptr);
|
|
liblte_rrc_pack_srs_ul_config_common_ie(&rr_cnfg->srs_ul_cnfg, ie_ptr);
|
|
liblte_rrc_pack_ul_power_control_common_ie(&rr_cnfg->ul_pwr_ctrl, ie_ptr);
|
|
|
|
// UL CP Length
|
|
liblte_value_2_bits(rr_cnfg->ul_cp_length, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_sib_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RR_CONFIG_COMMON_SIB_STRUCT *rr_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rr_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_rach_config_common_ie(ie_ptr, &rr_cnfg->rach_cnfg);
|
|
|
|
// BCCH Config
|
|
rr_cnfg->bcch_cnfg.modification_period_coeff = (LIBLTE_RRC_MODIFICATION_PERIOD_COEFF_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
// PCCH Config
|
|
rr_cnfg->pcch_cnfg.default_paging_cycle = (LIBLTE_RRC_DEFAULT_PAGING_CYCLE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
rr_cnfg->pcch_cnfg.nB = (LIBLTE_RRC_NB_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
liblte_rrc_unpack_prach_config_sib_ie(ie_ptr, &rr_cnfg->prach_cnfg);
|
|
liblte_rrc_unpack_pdsch_config_common_ie(ie_ptr, &rr_cnfg->pdsch_cnfg);
|
|
liblte_rrc_unpack_pusch_config_common_ie(ie_ptr, &rr_cnfg->pusch_cnfg);
|
|
liblte_rrc_unpack_pucch_config_common_ie(ie_ptr, &rr_cnfg->pucch_cnfg);
|
|
liblte_rrc_unpack_srs_ul_config_common_ie(ie_ptr, &rr_cnfg->srs_ul_cnfg);
|
|
liblte_rrc_unpack_ul_power_control_common_ie(ie_ptr, &rr_cnfg->ul_pwr_ctrl);
|
|
|
|
// UL CP Length
|
|
rr_cnfg->ul_cp_length = (LIBLTE_RRC_UL_CP_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_common_ie(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *rr_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rr_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(rr_cnfg->rach_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->pdsch_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->phich_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->pucch_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->srs_ul_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->ul_pwr_ctrl_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->ant_info_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->p_max_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->tdd_cnfg_present, ie_ptr, 1);
|
|
|
|
// RACH Config Common
|
|
if(rr_cnfg->rach_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_rach_config_common_ie(&rr_cnfg->rach_cnfg, ie_ptr);
|
|
}
|
|
|
|
// PRACH Config
|
|
liblte_rrc_pack_prach_config_ie(&rr_cnfg->prach_cnfg, ie_ptr);
|
|
|
|
// PDSCH Config Common
|
|
if(rr_cnfg->pdsch_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_pdsch_config_common_ie(&rr_cnfg->pdsch_cnfg, ie_ptr);
|
|
}
|
|
|
|
// PUSCH Config Common
|
|
liblte_rrc_pack_pusch_config_common_ie(&rr_cnfg->pusch_cnfg, ie_ptr);
|
|
|
|
// PHICH Config
|
|
if(rr_cnfg->phich_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_phich_config_ie(&rr_cnfg->phich_cnfg, ie_ptr);
|
|
}
|
|
|
|
// PUCCH Config Common
|
|
if(rr_cnfg->pucch_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_pucch_config_common_ie(&rr_cnfg->pucch_cnfg, ie_ptr);
|
|
}
|
|
|
|
// Sounding RS UL Config Common
|
|
if(rr_cnfg->srs_ul_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_srs_ul_config_common_ie(&rr_cnfg->srs_ul_cnfg, ie_ptr);
|
|
}
|
|
|
|
// Antenna Info Common
|
|
if(rr_cnfg->ant_info_present)
|
|
{
|
|
liblte_rrc_pack_antenna_info_common_ie(rr_cnfg->ant_info, ie_ptr);
|
|
}
|
|
|
|
// P Max
|
|
if(rr_cnfg->p_max_present)
|
|
{
|
|
liblte_rrc_pack_p_max_ie(rr_cnfg->p_max, ie_ptr);
|
|
}
|
|
|
|
// TDD Config
|
|
if(rr_cnfg->tdd_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_tdd_config_ie(&rr_cnfg->tdd_cnfg, ie_ptr);
|
|
}
|
|
|
|
// UL CP Length
|
|
liblte_value_2_bits(rr_cnfg->ul_cp_length, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *rr_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rr_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
rr_cnfg->rach_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->pdsch_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->phich_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->pucch_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->srs_ul_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->ul_pwr_ctrl_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->ant_info_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->p_max_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->tdd_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// RACH Config Common
|
|
if(rr_cnfg->rach_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_rach_config_common_ie(ie_ptr, &rr_cnfg->rach_cnfg);
|
|
}
|
|
|
|
// PRACH Config
|
|
liblte_rrc_unpack_prach_config_ie(ie_ptr, &rr_cnfg->prach_cnfg);
|
|
|
|
// PDSCH Config Common
|
|
if(rr_cnfg->pdsch_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_pdsch_config_common_ie(ie_ptr, &rr_cnfg->pdsch_cnfg);
|
|
}
|
|
|
|
// PUSCH Config Common
|
|
liblte_rrc_unpack_pusch_config_common_ie(ie_ptr, &rr_cnfg->pusch_cnfg);
|
|
|
|
// PHICH Config
|
|
if(rr_cnfg->phich_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_phich_config_ie(ie_ptr, &rr_cnfg->phich_cnfg);
|
|
}
|
|
|
|
// PUCCH Config Common
|
|
if(rr_cnfg->pucch_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_pucch_config_common_ie(ie_ptr, &rr_cnfg->pucch_cnfg);
|
|
}
|
|
|
|
// Sounding RS UL Config Common
|
|
if(rr_cnfg->srs_ul_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_srs_ul_config_common_ie(ie_ptr, &rr_cnfg->srs_ul_cnfg);
|
|
}
|
|
|
|
// Antenna Info Common
|
|
if(rr_cnfg->ant_info_present)
|
|
{
|
|
liblte_rrc_unpack_antenna_info_common_ie(ie_ptr, &rr_cnfg->ant_info);
|
|
}
|
|
|
|
// P Max
|
|
if(rr_cnfg->p_max_present)
|
|
{
|
|
liblte_rrc_unpack_p_max_ie(ie_ptr, &rr_cnfg->p_max);
|
|
}
|
|
|
|
// TDD Config
|
|
if(rr_cnfg->tdd_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_tdd_config_ie(ie_ptr, &rr_cnfg->tdd_cnfg);
|
|
}
|
|
|
|
// UL CP Length
|
|
rr_cnfg->ul_cp_length = (LIBLTE_RRC_UL_CP_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Radio Resource Config Dedicated
|
|
|
|
Description: Sets up/Modifies/Releases RBs, modifies the MAC
|
|
main configuration, modifies the SPS configuration
|
|
and modifies dedicated physical configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rr_config_dedicated_ie(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *rr_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(rr_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(rr_cnfg->rlf_timers_and_constants_present, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
if(rr_cnfg->srb_to_add_mod_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
if(rr_cnfg->drb_to_add_mod_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
if(rr_cnfg->drb_to_release_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(rr_cnfg->mac_main_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->sps_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->phy_cnfg_ded_present, ie_ptr, 1);
|
|
|
|
// SRB To Add Mod List
|
|
if(rr_cnfg->srb_to_add_mod_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list_size - 1, ie_ptr, 1);
|
|
}
|
|
for(i=0; i<rr_cnfg->srb_to_add_mod_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present, ie_ptr, 1);
|
|
|
|
// SRB Identity
|
|
liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].srb_id - 1, ie_ptr, 1);
|
|
|
|
// RLC Config
|
|
if(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present)
|
|
{
|
|
// Choice
|
|
liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present, ie_ptr, 1);
|
|
|
|
// Explicit Config
|
|
if(!rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_rlc_config_ie(&rr_cnfg->srb_to_add_mod_list[i].rlc_explicit_cnfg, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// Logical Channel Config
|
|
if(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present)
|
|
{
|
|
// Choice
|
|
liblte_value_2_bits(rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present, ie_ptr, 1);
|
|
|
|
// Explicit Config
|
|
if(!rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_logical_channel_config_ie(&rr_cnfg->srb_to_add_mod_list[i].lc_explicit_cnfg, ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
// DRB To Add Mod List
|
|
if(rr_cnfg->drb_to_add_mod_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list_size - 1, ie_ptr, 4);
|
|
}
|
|
for(i=0; i<rr_cnfg->drb_to_add_mod_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_id_present, ie_ptr, 1);
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present, ie_ptr, 1);
|
|
|
|
// EPS Bearer Identity
|
|
if(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present)
|
|
{
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id, ie_ptr, 4);
|
|
}
|
|
|
|
// DRB Identity
|
|
liblte_rrc_pack_drb_identity_ie(rr_cnfg->drb_to_add_mod_list[i].drb_id, ie_ptr);
|
|
|
|
// PDCP Config
|
|
if(rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_pdcp_config_ie(&rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg, ie_ptr);
|
|
}
|
|
|
|
// RLC Config
|
|
if(rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_rlc_config_ie(&rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg, ie_ptr);
|
|
}
|
|
|
|
// Logical Channel Identity
|
|
if(rr_cnfg->drb_to_add_mod_list[i].lc_id_present)
|
|
{
|
|
liblte_value_2_bits(rr_cnfg->drb_to_add_mod_list[i].lc_id - 3, ie_ptr, 3);
|
|
}
|
|
|
|
// Logical Channel Configuration
|
|
if(rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_logical_channel_config_ie(&rr_cnfg->drb_to_add_mod_list[i].lc_cnfg, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// DRB To Release List
|
|
if(rr_cnfg->drb_to_release_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(rr_cnfg->drb_to_release_list_size - 1, ie_ptr, 4);
|
|
}
|
|
for(i=0; i<rr_cnfg->drb_to_release_list_size; i++)
|
|
{
|
|
liblte_rrc_pack_drb_identity_ie(rr_cnfg->drb_to_release_list[i], ie_ptr);
|
|
}
|
|
|
|
// MAC Main Config
|
|
if(rr_cnfg->mac_main_cnfg_present)
|
|
{
|
|
liblte_value_2_bits(rr_cnfg->mac_main_cnfg.default_value, ie_ptr, 1);
|
|
if(!rr_cnfg->mac_main_cnfg.default_value)
|
|
{
|
|
liblte_rrc_pack_mac_main_config_ie(&rr_cnfg->mac_main_cnfg.explicit_value, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// SPS Config
|
|
if(rr_cnfg->sps_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_sps_config_ie(&rr_cnfg->sps_cnfg, ie_ptr);
|
|
}
|
|
|
|
// Physical Config Dedicated
|
|
if(rr_cnfg->phy_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_physical_config_dedicated_ie(&rr_cnfg->phy_cnfg_ded, ie_ptr);
|
|
}
|
|
|
|
// Extension
|
|
// Optional indicators
|
|
liblte_value_2_bits(rr_cnfg->rlf_timers_and_constants_present, ie_ptr, 1);
|
|
|
|
// RLF Timers and Constants
|
|
if(rr_cnfg->rlf_timers_and_constants_present)
|
|
{
|
|
liblte_rrc_pack_rlf_timers_and_constants_ie(&rr_cnfg->rlf_timers_and_constants, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rr_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *rr_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool ext;
|
|
bool srb_ext;
|
|
bool drb_ext;
|
|
bool srb_to_add_mod_list_present;
|
|
bool drb_to_add_mod_list_present;
|
|
bool drb_to_release_list_present;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rr_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
srb_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
drb_to_add_mod_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
drb_to_release_list_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->mac_main_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->sps_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->phy_cnfg_ded_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// SRB To Add Mod List
|
|
if(srb_to_add_mod_list_present)
|
|
{
|
|
rr_cnfg->srb_to_add_mod_list_size = liblte_bits_2_value(ie_ptr, 1) + 1;
|
|
for(i=0; i<rr_cnfg->srb_to_add_mod_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
srb_ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// SRB Identity
|
|
rr_cnfg->srb_to_add_mod_list[i].srb_id = liblte_bits_2_value(ie_ptr, 1) + 1;
|
|
|
|
// RLC Config
|
|
if(rr_cnfg->srb_to_add_mod_list[i].rlc_cnfg_present)
|
|
{
|
|
// Choice
|
|
rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Explicit Config
|
|
if(!rr_cnfg->srb_to_add_mod_list[i].rlc_default_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_rlc_config_ie(ie_ptr, &rr_cnfg->srb_to_add_mod_list[i].rlc_explicit_cnfg);
|
|
}
|
|
}
|
|
|
|
// Logical Channel Config
|
|
if(rr_cnfg->srb_to_add_mod_list[i].lc_cnfg_present)
|
|
{
|
|
// Choice
|
|
rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Explicit Config
|
|
if(!rr_cnfg->srb_to_add_mod_list[i].lc_default_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_logical_channel_config_ie(ie_ptr, &rr_cnfg->srb_to_add_mod_list[i].lc_explicit_cnfg);
|
|
}
|
|
}
|
|
|
|
// Consume non-critical extensions
|
|
liblte_rrc_consume_noncrit_extension(srb_ext, __func__, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// DRB To Add Mod List
|
|
if(drb_to_add_mod_list_present)
|
|
{
|
|
rr_cnfg->drb_to_add_mod_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<rr_cnfg->drb_to_add_mod_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
drb_ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->drb_to_add_mod_list[i].lc_id_present = liblte_bits_2_value(ie_ptr, 1);
|
|
rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// EPS Bearer Identity
|
|
if(rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id_present)
|
|
{
|
|
rr_cnfg->drb_to_add_mod_list[i].eps_bearer_id = liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
// DRB Identity
|
|
liblte_rrc_unpack_drb_identity_ie(ie_ptr, &rr_cnfg->drb_to_add_mod_list[i].drb_id);
|
|
|
|
// PDCP Config
|
|
if(rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_pdcp_config_ie(ie_ptr, &rr_cnfg->drb_to_add_mod_list[i].pdcp_cnfg);
|
|
}
|
|
|
|
// RLC Config
|
|
if(rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_rlc_config_ie(ie_ptr, &rr_cnfg->drb_to_add_mod_list[i].rlc_cnfg);
|
|
}
|
|
|
|
// Logical Channel Identity
|
|
if(rr_cnfg->drb_to_add_mod_list[i].lc_id_present)
|
|
{
|
|
rr_cnfg->drb_to_add_mod_list[i].lc_id = liblte_bits_2_value(ie_ptr, 3) + 3;
|
|
}
|
|
|
|
// Logical Channel Configuration
|
|
if(rr_cnfg->drb_to_add_mod_list[i].lc_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_logical_channel_config_ie(ie_ptr, &rr_cnfg->drb_to_add_mod_list[i].lc_cnfg);
|
|
}
|
|
|
|
// Consume non-critical extensions
|
|
liblte_rrc_consume_noncrit_extension(drb_ext, __func__, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// DRB To Release List
|
|
if(drb_to_release_list_present)
|
|
{
|
|
rr_cnfg->drb_to_release_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<rr_cnfg->drb_to_release_list_size; i++)
|
|
{
|
|
liblte_rrc_unpack_drb_identity_ie(ie_ptr, &rr_cnfg->drb_to_release_list[i]);
|
|
}
|
|
}
|
|
|
|
// MAC Main Config
|
|
if(rr_cnfg->mac_main_cnfg_present)
|
|
{
|
|
rr_cnfg->mac_main_cnfg.default_value = liblte_bits_2_value(ie_ptr, 1);
|
|
if(!rr_cnfg->mac_main_cnfg.default_value)
|
|
{
|
|
liblte_rrc_unpack_mac_main_config_ie(ie_ptr, &rr_cnfg->mac_main_cnfg.explicit_value);
|
|
}
|
|
}
|
|
|
|
// SPS Config
|
|
if(rr_cnfg->sps_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_sps_config_ie(ie_ptr, &rr_cnfg->sps_cnfg);
|
|
}
|
|
|
|
// Physical Config Dedicated
|
|
if(rr_cnfg->phy_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_physical_config_dedicated_ie(ie_ptr, &rr_cnfg->phy_cnfg_ded);
|
|
}
|
|
|
|
// Extension (FIXME: only handling r9 extensions)
|
|
#if 0
|
|
if(ext)
|
|
{
|
|
// Optional indicators
|
|
rr_cnfg->rlf_timers_and_constants_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// RLF Timers and Constants
|
|
if(rr_cnfg->rlf_timers_and_constants_present)
|
|
{
|
|
liblte_rrc_unpack_rlf_timers_and_constants_ie(ie_ptr, &rr_cnfg->rlf_timers_and_constants);
|
|
}
|
|
}
|
|
#endif
|
|
// Modified by ismael, just skip extensions
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RLC Config
|
|
|
|
Description: Specifies the RLC configuration of SRBs and DRBs
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rlc_config_ie(LIBLTE_RRC_RLC_CONFIG_STRUCT *rlc_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rlc_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Mode Choice
|
|
liblte_value_2_bits(rlc_cnfg->rlc_mode, ie_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_RLC_MODE_AM == rlc_cnfg->rlc_mode)
|
|
{
|
|
// UL AM RLC
|
|
{
|
|
// T Poll Retransmit
|
|
liblte_value_2_bits(rlc_cnfg->ul_am_rlc.t_poll_retx, ie_ptr, 6);
|
|
|
|
// Poll PDU
|
|
liblte_value_2_bits(rlc_cnfg->ul_am_rlc.poll_pdu, ie_ptr, 3);
|
|
|
|
// Poll Byte
|
|
liblte_value_2_bits(rlc_cnfg->ul_am_rlc.poll_byte, ie_ptr, 4);
|
|
|
|
// Max Retransmission Threshold
|
|
liblte_value_2_bits(rlc_cnfg->ul_am_rlc.max_retx_thresh, ie_ptr, 3);
|
|
}
|
|
|
|
// DL AM RLC
|
|
{
|
|
// T Reordering
|
|
liblte_value_2_bits(rlc_cnfg->dl_am_rlc.t_reordering, ie_ptr, 5);
|
|
|
|
// T Status Prohibit
|
|
liblte_value_2_bits(rlc_cnfg->dl_am_rlc.t_status_prohibit, ie_ptr, 6);
|
|
}
|
|
}else if(LIBLTE_RRC_RLC_MODE_UM_BI == rlc_cnfg->rlc_mode){
|
|
// UL UM RLC
|
|
{
|
|
// SN Field Length
|
|
liblte_value_2_bits(rlc_cnfg->ul_um_bi_rlc.sn_field_len, ie_ptr, 1);
|
|
}
|
|
|
|
// DL UM RLC
|
|
{
|
|
// SN Field Length
|
|
liblte_value_2_bits(rlc_cnfg->dl_um_bi_rlc.sn_field_len, ie_ptr, 1);
|
|
|
|
// T Reordering
|
|
liblte_value_2_bits(rlc_cnfg->dl_um_bi_rlc.t_reordering, ie_ptr, 5);
|
|
}
|
|
}else if(LIBLTE_RRC_RLC_MODE_UM_UNI_UL == rlc_cnfg->rlc_mode){
|
|
// SN Field Length
|
|
liblte_value_2_bits(rlc_cnfg->ul_um_uni_rlc.sn_field_len, ie_ptr, 1);
|
|
}else{ // LIBLTE_RRC_RLC_MODE_UM_UNI_DL == rlc_cnfg->rlc_mode
|
|
// SN Field Length
|
|
liblte_value_2_bits(rlc_cnfg->dl_um_uni_rlc.sn_field_len, ie_ptr, 1);
|
|
|
|
// T Reordering
|
|
liblte_value_2_bits(rlc_cnfg->dl_um_uni_rlc.t_reordering, ie_ptr, 5);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rlc_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RLC_CONFIG_STRUCT *rlc_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rlc_cnfg != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Mode Choice
|
|
rlc_cnfg->rlc_mode = (LIBLTE_RRC_RLC_MODE_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_RLC_MODE_AM == rlc_cnfg->rlc_mode)
|
|
{
|
|
// UL AM RLC
|
|
{
|
|
// T Poll Retransmit
|
|
rlc_cnfg->ul_am_rlc.t_poll_retx = (LIBLTE_RRC_T_POLL_RETRANSMIT_ENUM)liblte_bits_2_value(ie_ptr, 6);
|
|
|
|
// Poll PDU
|
|
rlc_cnfg->ul_am_rlc.poll_pdu = (LIBLTE_RRC_POLL_PDU_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
// Poll Byte
|
|
rlc_cnfg->ul_am_rlc.poll_byte = (LIBLTE_RRC_POLL_BYTE_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Max Retransmission Threshold
|
|
rlc_cnfg->ul_am_rlc.max_retx_thresh = (LIBLTE_RRC_MAX_RETX_THRESHOLD_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
}
|
|
|
|
// DL AM RLC
|
|
{
|
|
// T Reordering
|
|
rlc_cnfg->dl_am_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
// T Status Prohibit
|
|
rlc_cnfg->dl_am_rlc.t_status_prohibit = (LIBLTE_RRC_T_STATUS_PROHIBIT_ENUM)liblte_bits_2_value(ie_ptr, 6);
|
|
}
|
|
}else if(LIBLTE_RRC_RLC_MODE_UM_BI == rlc_cnfg->rlc_mode){
|
|
// UL UM RLC
|
|
{
|
|
// SN Field Length
|
|
rlc_cnfg->ul_um_bi_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
// DL UM RLC
|
|
{
|
|
// SN Field Length
|
|
rlc_cnfg->dl_um_bi_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// T Reordering
|
|
rlc_cnfg->dl_um_bi_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)liblte_bits_2_value(ie_ptr, 5);
|
|
}
|
|
}else if(LIBLTE_RRC_RLC_MODE_UM_UNI_UL == rlc_cnfg->rlc_mode){
|
|
// SN Field Length
|
|
rlc_cnfg->ul_um_uni_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}else{ // LIBLTE_RRC_RLC_MODE_UM_UNI_DL == rlc_cnfg->rlc_mode
|
|
// SN Field Length
|
|
rlc_cnfg->dl_um_uni_rlc.sn_field_len = (LIBLTE_RRC_SN_FIELD_LENGTH_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// T Reordering
|
|
rlc_cnfg->dl_um_uni_rlc.t_reordering = (LIBLTE_RRC_T_REORDERING_ENUM)liblte_bits_2_value(ie_ptr, 5);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RLF Timers and Constants
|
|
|
|
Description: Contains UE specific timers and constants applicable
|
|
for UEs in RRC_CONNECTED
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rlf_timers_and_constants_ie(LIBLTE_RRC_RLF_TIMERS_AND_CONSTANTS_STRUCT *rlf_timers_and_constants,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(rlf_timers_and_constants != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Release choice
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
|
|
// Extension
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(rlf_timers_and_constants->t301, ie_ptr, 3);
|
|
liblte_value_2_bits(rlf_timers_and_constants->t310, ie_ptr, 3);
|
|
liblte_value_2_bits(rlf_timers_and_constants->n310, ie_ptr, 3);
|
|
liblte_value_2_bits(rlf_timers_and_constants->t311, ie_ptr, 3);
|
|
liblte_value_2_bits(rlf_timers_and_constants->n311, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rlf_timers_and_constants_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_RLF_TIMERS_AND_CONSTANTS_STRUCT *rlf_timers_and_constants)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
rlf_timers_and_constants != NULL)
|
|
{
|
|
// Release choice
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Extension
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
rlf_timers_and_constants->t301 = (LIBLTE_RRC_T301_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
rlf_timers_and_constants->t310 = (LIBLTE_RRC_T310_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
rlf_timers_and_constants->n310 = (LIBLTE_RRC_N310_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
rlf_timers_and_constants->t311 = (LIBLTE_RRC_T311_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
rlf_timers_and_constants->n311 = (LIBLTE_RRC_N311_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: RN Subframe Config
|
|
|
|
Description: Specifies the subframe configuration for an RN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: Scheduling Request Config
|
|
|
|
Description: Specifies the scheduling request related parameters
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_scheduling_request_config_ie(LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sched_request_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(sched_request_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Setup
|
|
liblte_value_2_bits(sched_request_cnfg->setup_present, ie_ptr, 1);
|
|
if(sched_request_cnfg->setup_present)
|
|
{
|
|
// SR PUCCH Resource Index
|
|
liblte_value_2_bits(sched_request_cnfg->sr_pucch_resource_idx, ie_ptr, 11);
|
|
|
|
// SR Config Index
|
|
liblte_value_2_bits(sched_request_cnfg->sr_cnfg_idx, ie_ptr, 8);
|
|
|
|
// DRS Trans Max
|
|
liblte_value_2_bits(sched_request_cnfg->dsr_trans_max, ie_ptr, 3);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_scheduling_request_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SCHEDULING_REQUEST_CONFIG_STRUCT *sched_request_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sched_request_cnfg != NULL)
|
|
{
|
|
// Setup
|
|
sched_request_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(sched_request_cnfg->setup_present)
|
|
{
|
|
// SR PUCCH Resource Index
|
|
sched_request_cnfg->sr_pucch_resource_idx = liblte_bits_2_value(ie_ptr, 11);
|
|
|
|
// SR Config Index
|
|
sched_request_cnfg->sr_cnfg_idx = liblte_bits_2_value(ie_ptr, 8);
|
|
|
|
// DRS Trans Max
|
|
sched_request_cnfg->dsr_trans_max = (LIBLTE_RRC_DSR_TRANS_MAX_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Sounding RS UL Config
|
|
|
|
Description: Specifies the uplink Sounding RS configuration for
|
|
periodic and aperiodic sounding
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_srs_ul_config_common_ie(LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT *srs_ul_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(srs_ul_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(srs_ul_cnfg->present, ie_ptr, 1);
|
|
|
|
if(true == srs_ul_cnfg->present)
|
|
{
|
|
liblte_value_2_bits(srs_ul_cnfg->max_up_pts_present, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(srs_ul_cnfg->bw_cnfg, ie_ptr, 3);
|
|
liblte_value_2_bits(srs_ul_cnfg->subfr_cnfg, ie_ptr, 4);
|
|
liblte_value_2_bits(srs_ul_cnfg->ack_nack_simul_tx, ie_ptr, 1);
|
|
|
|
if(true == srs_ul_cnfg->max_up_pts_present)
|
|
{
|
|
liblte_value_2_bits(srs_ul_cnfg->max_up_pts, ie_ptr, 1);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_srs_ul_config_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT *srs_ul_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
srs_ul_cnfg != NULL)
|
|
{
|
|
srs_ul_cnfg->present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == srs_ul_cnfg->present)
|
|
{
|
|
srs_ul_cnfg->max_up_pts_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
srs_ul_cnfg->bw_cnfg = (LIBLTE_RRC_SRS_BW_CONFIG_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
srs_ul_cnfg->subfr_cnfg = (LIBLTE_RRC_SRS_SUBFR_CONFIG_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
srs_ul_cnfg->ack_nack_simul_tx = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == srs_ul_cnfg->max_up_pts_present)
|
|
{
|
|
srs_ul_cnfg->max_up_pts = liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_srs_ul_config_dedicated_ie(LIBLTE_RRC_SRS_UL_CONFIG_DEDICATED_STRUCT *srs_ul_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(srs_ul_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Setup
|
|
liblte_value_2_bits(srs_ul_cnfg->setup_present, ie_ptr, 1);
|
|
if(srs_ul_cnfg->setup_present)
|
|
{
|
|
// SRS Bandwidth
|
|
liblte_value_2_bits(srs_ul_cnfg->srs_bandwidth, ie_ptr, 2);
|
|
|
|
// SRS Hopping Bandwidth
|
|
liblte_value_2_bits(srs_ul_cnfg->srs_hopping_bandwidth, ie_ptr, 2);
|
|
|
|
// Frequency Domain Position
|
|
liblte_value_2_bits(srs_ul_cnfg->freq_domain_pos, ie_ptr, 5);
|
|
|
|
// Duration
|
|
liblte_value_2_bits(srs_ul_cnfg->duration, ie_ptr, 1);
|
|
|
|
// SRS Config Index
|
|
liblte_value_2_bits(srs_ul_cnfg->srs_cnfg_idx, ie_ptr, 10);
|
|
|
|
// Transmission Comb
|
|
liblte_value_2_bits(srs_ul_cnfg->tx_comb, ie_ptr, 1);
|
|
|
|
// Cyclic Shift
|
|
liblte_value_2_bits(srs_ul_cnfg->cyclic_shift, ie_ptr, 3);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_srs_ul_config_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SRS_UL_CONFIG_DEDICATED_STRUCT *srs_ul_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
srs_ul_cnfg != NULL)
|
|
{
|
|
// Setup
|
|
srs_ul_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(srs_ul_cnfg->setup_present)
|
|
{
|
|
// SRS Bandwidth
|
|
srs_ul_cnfg->srs_bandwidth = (LIBLTE_RRC_SRS_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
// SRS Hopping Bandwidth
|
|
srs_ul_cnfg->srs_hopping_bandwidth = (LIBLTE_RRC_SRS_HOPPING_BANDWIDTH_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
// Frequency Domain Position
|
|
srs_ul_cnfg->freq_domain_pos = liblte_bits_2_value(ie_ptr, 5);
|
|
|
|
// Duration
|
|
srs_ul_cnfg->duration = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// SRS Config Index
|
|
srs_ul_cnfg->srs_cnfg_idx = liblte_bits_2_value(ie_ptr, 10);
|
|
|
|
// Transmission Comb
|
|
srs_ul_cnfg->tx_comb = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Cyclic Shift
|
|
srs_ul_cnfg->cyclic_shift = (LIBLTE_RRC_CYCLIC_SHIFT_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: SPS Config
|
|
|
|
Description: Specifies the semi-persistent scheduling
|
|
configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sps_config_ie(LIBLTE_RRC_SPS_CONFIG_STRUCT *sps_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(sps_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sps_cnfg->sps_c_rnti_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_dl_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul_present, ie_ptr, 1);
|
|
|
|
// SPS C-RNTI
|
|
if(sps_cnfg->sps_c_rnti_present)
|
|
{
|
|
liblte_rrc_pack_c_rnti_ie(sps_cnfg->sps_c_rnti, ie_ptr);
|
|
}
|
|
|
|
// SPS Config DL
|
|
if(sps_cnfg->sps_cnfg_dl_present)
|
|
{
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.setup_present, ie_ptr, 1);
|
|
if(sps_cnfg->sps_cnfg_dl.setup_present)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// SPS Interval DL
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.sps_interval_dl, ie_ptr, 4);
|
|
|
|
// Number of Configured SPS Processes
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.N_sps_processes - 1, ie_ptr, 3);
|
|
|
|
// N1 PUCCH AN Persistent List
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size - 1, ie_ptr, 2);
|
|
for(i=0; i<sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size; i++)
|
|
{
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list[i], ie_ptr, 11);
|
|
}
|
|
}
|
|
}
|
|
|
|
// SPS Config UL
|
|
if(sps_cnfg->sps_cnfg_ul_present)
|
|
{
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.setup_present, ie_ptr, 1);
|
|
if(sps_cnfg->sps_cnfg_ul.setup_present)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_persistent_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present, ie_ptr, 1);
|
|
|
|
// SPS Interval UL
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.sps_interval_ul, ie_ptr, 4);
|
|
|
|
// Implicit Release After
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.implicit_release_after, ie_ptr, 2);
|
|
|
|
// P0 Persistent
|
|
if(sps_cnfg->sps_cnfg_ul.p0_persistent_present)
|
|
{
|
|
// P0 Nominal PUSCH Persistent
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_nominal_pusch + 126, ie_ptr, 8);
|
|
|
|
// P0 UE PUSCH Persistent
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.p0_ue_pusch + 8, ie_ptr, 4);
|
|
}
|
|
|
|
// Two Intervals Config
|
|
if(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present)
|
|
{
|
|
liblte_value_2_bits(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg, ie_ptr, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sps_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SPS_CONFIG_STRUCT *sps_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sps_cnfg != NULL)
|
|
{
|
|
// Optional indicators
|
|
sps_cnfg->sps_c_rnti_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sps_cnfg->sps_cnfg_dl_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sps_cnfg->sps_cnfg_ul_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// SPS C-RNTI
|
|
if(sps_cnfg->sps_c_rnti_present)
|
|
{
|
|
liblte_rrc_unpack_c_rnti_ie(ie_ptr, &sps_cnfg->sps_c_rnti);
|
|
}
|
|
|
|
// SPS Config DL
|
|
if(sps_cnfg->sps_cnfg_dl_present)
|
|
{
|
|
sps_cnfg->sps_cnfg_dl.setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(sps_cnfg->sps_cnfg_dl.setup_present)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// SPS Interval DL
|
|
sps_cnfg->sps_cnfg_dl.sps_interval_dl = (LIBLTE_RRC_SPS_INTERVAL_DL_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Number of Configured SPS Processes
|
|
sps_cnfg->sps_cnfg_dl.N_sps_processes = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
|
|
// N1 PUCCH AN Persistent List
|
|
sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size = liblte_bits_2_value(ie_ptr, 2) + 1;
|
|
for(i=0; i<sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list_size; i++)
|
|
{
|
|
sps_cnfg->sps_cnfg_dl.n1_pucch_an_persistent_list[i] = liblte_bits_2_value(ie_ptr, 11);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
}
|
|
}
|
|
|
|
// SPS Config UL
|
|
if(sps_cnfg->sps_cnfg_ul_present)
|
|
{
|
|
sps_cnfg->sps_cnfg_ul.setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(sps_cnfg->sps_cnfg_ul.setup_present)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
sps_cnfg->sps_cnfg_ul.p0_persistent_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// SPS Interval UL
|
|
sps_cnfg->sps_cnfg_ul.sps_interval_ul = (LIBLTE_RRC_SPS_INTERVAL_UL_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Implicit Release After
|
|
sps_cnfg->sps_cnfg_ul.implicit_release_after = (LIBLTE_RRC_IMPLICIT_RELEASE_AFTER_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
// P0 Persistent
|
|
if(sps_cnfg->sps_cnfg_ul.p0_persistent_present)
|
|
{
|
|
// P0 Nominal PUSCH Persistent
|
|
sps_cnfg->sps_cnfg_ul.p0_nominal_pusch = liblte_bits_2_value(ie_ptr, 8) - 126;
|
|
|
|
// P0 UE PUSCH Persistent
|
|
sps_cnfg->sps_cnfg_ul.p0_ue_pusch = liblte_bits_2_value(ie_ptr, 4) - 8;
|
|
}
|
|
|
|
// Two Intervals Config
|
|
if(sps_cnfg->sps_cnfg_ul.two_intervals_cnfg_present)
|
|
{
|
|
sps_cnfg->sps_cnfg_ul.two_intervals_cnfg = (LIBLTE_RRC_TWO_INTERVALS_CONFIG_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: TDD Config
|
|
|
|
Description: Specifies the TDD specific physical channel
|
|
configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_tdd_config_ie(LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(tdd_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(tdd_cnfg->sf_assignment, ie_ptr, 3);
|
|
liblte_value_2_bits(tdd_cnfg->special_sf_patterns, ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_tdd_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_TDD_CONFIG_STRUCT *tdd_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
tdd_cnfg != NULL)
|
|
{
|
|
tdd_cnfg->sf_assignment = (LIBLTE_RRC_SUBFRAME_ASSIGNMENT_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
tdd_cnfg->special_sf_patterns = (LIBLTE_RRC_SPECIAL_SUBFRAME_PATTERNS_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Time Alignment Timer
|
|
|
|
Description: Controls how long the UE is considered uplink time
|
|
aligned
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_time_alignment_timer_ie(LIBLTE_RRC_TIME_ALIGNMENT_TIMER_ENUM time_alignment_timer,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(time_alignment_timer, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_time_alignment_timer_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_TIME_ALIGNMENT_TIMER_ENUM *time_alignment_timer)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
time_alignment_timer != NULL)
|
|
{
|
|
*time_alignment_timer = (LIBLTE_RRC_TIME_ALIGNMENT_TIMER_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: TPC PDCCH Config
|
|
|
|
Description: Specifies the RNTIs and indecies for PUCCH and PUSCH
|
|
power control
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_tpc_pdcch_config_ie(LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT *tpc_pdcch_cnfg,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(tpc_pdcch_cnfg != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Setup
|
|
liblte_value_2_bits(tpc_pdcch_cnfg->setup_present, ie_ptr, 1);
|
|
if(tpc_pdcch_cnfg->setup_present)
|
|
{
|
|
// TPC RNTI
|
|
liblte_value_2_bits(tpc_pdcch_cnfg->tpc_rnti, ie_ptr, 16);
|
|
|
|
// TPC Index
|
|
liblte_value_2_bits(tpc_pdcch_cnfg->tpc_idx_choice, ie_ptr, 1);
|
|
if(LIBLTE_RRC_TPC_INDEX_FORMAT_3 == tpc_pdcch_cnfg->tpc_idx_choice)
|
|
{
|
|
liblte_value_2_bits(tpc_pdcch_cnfg->tpc_idx - 1, ie_ptr, 4);
|
|
}else{
|
|
liblte_value_2_bits(tpc_pdcch_cnfg->tpc_idx - 1, ie_ptr, 5);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_tpc_pdcch_config_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_TPC_PDCCH_CONFIG_STRUCT *tpc_pdcch_cnfg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
tpc_pdcch_cnfg != NULL)
|
|
{
|
|
// Setup
|
|
tpc_pdcch_cnfg->setup_present = liblte_bits_2_value(ie_ptr, 1);
|
|
if(tpc_pdcch_cnfg->setup_present)
|
|
{
|
|
// TPC RNTI
|
|
tpc_pdcch_cnfg->tpc_rnti = liblte_bits_2_value(ie_ptr, 16);
|
|
|
|
// TPC Index
|
|
tpc_pdcch_cnfg->tpc_idx_choice = (LIBLTE_RRC_TPC_INDEX_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
if(LIBLTE_RRC_TPC_INDEX_FORMAT_3 == tpc_pdcch_cnfg->tpc_idx_choice)
|
|
{
|
|
tpc_pdcch_cnfg->tpc_idx = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
}else{
|
|
tpc_pdcch_cnfg->tpc_idx = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: UL Antenna Info
|
|
|
|
Description: Specifies the UL antenna configuration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_antenna_info_ie(LIBLTE_RRC_UL_ANTENNA_INFO_STRUCT *ul_ant_info,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ul_ant_info != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(ul_ant_info->ul_tx_mode, ie_ptr, 3);
|
|
liblte_value_2_bits(ul_ant_info->four_ant_port_activated, ie_ptr, 1);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_antenna_info_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_UL_ANTENNA_INFO_STRUCT *ul_ant_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
ul_ant_info != NULL)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
ul_ant_info->ul_tx_mode = (LIBLTE_RRC_UL_TRANSMISSION_MODE_R10_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ul_ant_info->four_ant_port_activated = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: Uplink Power Control
|
|
|
|
Description: Specifies the parameters for uplink power control in
|
|
the system information and in the dedicated
|
|
signalling
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_power_control_common_ie(LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT *ul_pwr_ctrl,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ul_pwr_ctrl != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
liblte_value_2_bits(ul_pwr_ctrl->p0_nominal_pusch + 126, ie_ptr, 8);
|
|
liblte_value_2_bits(ul_pwr_ctrl->alpha, ie_ptr, 3);
|
|
liblte_value_2_bits(ul_pwr_ctrl->p0_nominal_pucch + 127, ie_ptr, 5);
|
|
|
|
// Delta F List
|
|
liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_1, ie_ptr, 2);
|
|
liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_1b, ie_ptr, 2);
|
|
liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2, ie_ptr, 2);
|
|
liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2a, ie_ptr, 2);
|
|
liblte_value_2_bits(ul_pwr_ctrl->delta_flist_pucch.format_2b, ie_ptr, 2);
|
|
|
|
liblte_value_2_bits((ul_pwr_ctrl->delta_preamble_msg3 / 2) + 1, ie_ptr, 3);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_power_control_common_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_UL_POWER_CONTROL_COMMON_STRUCT *ul_pwr_ctrl)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
ul_pwr_ctrl != NULL)
|
|
{
|
|
ul_pwr_ctrl->p0_nominal_pusch = liblte_bits_2_value(ie_ptr, 8) - 126;
|
|
ul_pwr_ctrl->alpha = (LIBLTE_RRC_UL_POWER_CONTROL_ALPHA_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
ul_pwr_ctrl->p0_nominal_pucch = liblte_bits_2_value(ie_ptr, 5) - 127;
|
|
|
|
// Delta F List
|
|
ul_pwr_ctrl->delta_flist_pucch.format_1 = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
ul_pwr_ctrl->delta_flist_pucch.format_1b = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_1B_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
ul_pwr_ctrl->delta_flist_pucch.format_2 = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
ul_pwr_ctrl->delta_flist_pucch.format_2a = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2A_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
ul_pwr_ctrl->delta_flist_pucch.format_2b = (LIBLTE_RRC_DELTA_F_PUCCH_FORMAT_2B_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
|
|
ul_pwr_ctrl->delta_preamble_msg3 = (liblte_bits_2_value(ie_ptr, 3) - 1) * 2;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_power_control_dedicated_ie(LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT *ul_pwr_ctrl,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ul_pwr_ctrl != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Filter Coefficient default?
|
|
liblte_value_2_bits(ul_pwr_ctrl->filter_coeff_present, ie_ptr, 1);
|
|
|
|
// P0 UE PUSCH
|
|
liblte_value_2_bits(ul_pwr_ctrl->p0_ue_pusch + 8, ie_ptr, 4);
|
|
|
|
// Delta MCS Enabled
|
|
liblte_value_2_bits(ul_pwr_ctrl->delta_mcs_en, ie_ptr, 1);
|
|
|
|
// Accumulation Enabled
|
|
liblte_value_2_bits(ul_pwr_ctrl->accumulation_en, ie_ptr, 1);
|
|
|
|
// P0 UE PUCCH
|
|
liblte_value_2_bits(ul_pwr_ctrl->p0_ue_pucch + 8, ie_ptr, 4);
|
|
|
|
// P SRS Offset
|
|
liblte_value_2_bits(ul_pwr_ctrl->p_srs_offset, ie_ptr, 4);
|
|
|
|
// Filter Coefficient
|
|
if(ul_pwr_ctrl->filter_coeff_present)
|
|
{
|
|
liblte_rrc_pack_filter_coefficient_ie(ul_pwr_ctrl->filter_coeff, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_power_control_dedicated_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_UL_POWER_CONTROL_DEDICATED_STRUCT *ul_pwr_ctrl)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(ie_ptr != NULL &&
|
|
ul_pwr_ctrl != NULL)
|
|
{
|
|
// Filter Coefficient default?
|
|
ul_pwr_ctrl->filter_coeff_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// P0 UE PUSCH
|
|
ul_pwr_ctrl->p0_ue_pusch = liblte_bits_2_value(ie_ptr, 4) - 8;
|
|
|
|
// Delta MCS Enabled
|
|
ul_pwr_ctrl->delta_mcs_en = (LIBLTE_RRC_DELTA_MCS_ENABLED_ENUM)liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Accumulation Enabled
|
|
ul_pwr_ctrl->accumulation_en = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// P0 UE PUCCH
|
|
ul_pwr_ctrl->p0_ue_pucch = liblte_bits_2_value(ie_ptr, 4) - 8;
|
|
|
|
// P SRS Offset
|
|
ul_pwr_ctrl->p_srs_offset = liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Filter Coefficient
|
|
if(ul_pwr_ctrl->filter_coeff_present)
|
|
{
|
|
liblte_rrc_unpack_filter_coefficient_ie(ie_ptr, &ul_pwr_ctrl->filter_coeff);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 2
|
|
|
|
Description: Contains radio resource configuration that is common
|
|
for all UEs
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_2_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool mbsfn_subfr_cnfg_list_opt;
|
|
|
|
if(sib2 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib2->ac_barring_info_present, ie_ptr, 1);
|
|
if(0 != sib2->mbsfn_subfr_cnfg_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
mbsfn_subfr_cnfg_list_opt = true;
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
mbsfn_subfr_cnfg_list_opt = false;
|
|
}
|
|
|
|
// AC Barring
|
|
if(true == sib2->ac_barring_info_present)
|
|
{
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.enabled, ie_ptr, 1);
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_data.enabled, ie_ptr, 1);
|
|
|
|
// AC Barring for emergency
|
|
liblte_value_2_bits(sib2->ac_barring_for_emergency, ie_ptr, 1);
|
|
|
|
// AC Barring for MO signalling
|
|
if(true == sib2->ac_barring_for_mo_signalling.enabled)
|
|
{
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.factor, ie_ptr, 4);
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.time, ie_ptr, 3);
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_signalling.for_special_ac, ie_ptr, 5);
|
|
}
|
|
|
|
// AC Barring for MO data
|
|
if(true == sib2->ac_barring_for_mo_data.enabled)
|
|
{
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_data.factor, ie_ptr, 4);
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_data.time, ie_ptr, 3);
|
|
liblte_value_2_bits(sib2->ac_barring_for_mo_data.for_special_ac, ie_ptr, 5);
|
|
}
|
|
}
|
|
|
|
// Radio Resource Config Common
|
|
liblte_rrc_pack_rr_config_common_sib_ie(&sib2->rr_config_common_sib, ie_ptr);
|
|
|
|
// UE Timers and Constants
|
|
liblte_rrc_pack_ue_timers_and_constants_ie(&sib2->ue_timers_and_constants, ie_ptr);
|
|
|
|
// Frequency information
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib2->arfcn_value_eutra.present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib2->ul_bw.present, ie_ptr, 1);
|
|
|
|
// UL Carrier Frequency
|
|
if(true == sib2->arfcn_value_eutra.present)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_eutra_ie(sib2->arfcn_value_eutra.value, ie_ptr);
|
|
}
|
|
|
|
// UL Bandwidth
|
|
if(true == sib2->ul_bw.present)
|
|
{
|
|
liblte_value_2_bits(sib2->ul_bw.bw, ie_ptr, 3);
|
|
}
|
|
|
|
// Additional Spectrum Emission
|
|
liblte_rrc_pack_additional_spectrum_emission_ie(sib2->additional_spectrum_emission,
|
|
ie_ptr);
|
|
}
|
|
|
|
// MBSFN Subframe Config List
|
|
if(true == mbsfn_subfr_cnfg_list_opt)
|
|
{
|
|
liblte_value_2_bits(sib2->mbsfn_subfr_cnfg_list_size - 1, ie_ptr, 3);
|
|
for(i=0; i<sib2->mbsfn_subfr_cnfg_list_size; i++)
|
|
{
|
|
liblte_rrc_pack_mbsfn_subframe_config_ie(&sib2->mbsfn_subfr_cnfg[i], ie_ptr);
|
|
}
|
|
}
|
|
|
|
// Time Alignment Timer Common
|
|
liblte_rrc_pack_time_alignment_timer_ie(sib2->time_alignment_timer, ie_ptr);
|
|
|
|
// FIXME: Not handling extensions
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_2_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint8 ext_ind;
|
|
bool mbsfn_subfr_cnfg_list_opt;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib2 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
sib2->ac_barring_info_present = liblte_bits_2_value(ie_ptr, 1);
|
|
mbsfn_subfr_cnfg_list_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// AC Barring
|
|
if(true == sib2->ac_barring_info_present)
|
|
{
|
|
// Optional indicators
|
|
sib2->ac_barring_for_mo_signalling.enabled = liblte_bits_2_value(ie_ptr, 1);
|
|
sib2->ac_barring_for_mo_data.enabled = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// AC Barring for emergency
|
|
sib2->ac_barring_for_emergency = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// AC Barring for MO signalling
|
|
if(true == sib2->ac_barring_for_mo_signalling.enabled)
|
|
{
|
|
sib2->ac_barring_for_mo_signalling.factor = (LIBLTE_RRC_AC_BARRING_FACTOR_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
sib2->ac_barring_for_mo_signalling.time = (LIBLTE_RRC_AC_BARRING_TIME_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
sib2->ac_barring_for_mo_signalling.for_special_ac = liblte_bits_2_value(ie_ptr, 5);
|
|
}
|
|
|
|
// AC Barring for MO data
|
|
if(true == sib2->ac_barring_for_mo_data.enabled)
|
|
{
|
|
sib2->ac_barring_for_mo_data.factor = (LIBLTE_RRC_AC_BARRING_FACTOR_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
sib2->ac_barring_for_mo_data.time = (LIBLTE_RRC_AC_BARRING_TIME_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
sib2->ac_barring_for_mo_data.for_special_ac = liblte_bits_2_value(ie_ptr, 5);
|
|
}
|
|
}else{
|
|
sib2->ac_barring_for_emergency = false;
|
|
sib2->ac_barring_for_mo_signalling.enabled = false;
|
|
sib2->ac_barring_for_mo_data.enabled = false;
|
|
}
|
|
|
|
// Radio Resource Config Common
|
|
liblte_rrc_unpack_rr_config_common_sib_ie(ie_ptr, &sib2->rr_config_common_sib);
|
|
|
|
// UE Timers and Constants
|
|
liblte_rrc_unpack_ue_timers_and_constants_ie(ie_ptr, &sib2->ue_timers_and_constants);
|
|
|
|
// Frequency information
|
|
{
|
|
// Optional indicators
|
|
sib2->arfcn_value_eutra.present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib2->ul_bw.present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// UL Carrier Frequency
|
|
if(true == sib2->arfcn_value_eutra.present)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &sib2->arfcn_value_eutra.value);
|
|
}
|
|
|
|
// UL Bandwidth
|
|
if(true == sib2->ul_bw.present)
|
|
{
|
|
sib2->ul_bw.bw = (LIBLTE_RRC_UL_BW_ENUM)liblte_bits_2_value(ie_ptr, 3);
|
|
}
|
|
|
|
// Additional Spectrum Emission
|
|
liblte_rrc_unpack_additional_spectrum_emission_ie(ie_ptr,
|
|
&sib2->additional_spectrum_emission);
|
|
}
|
|
|
|
// MBSFN Subframe Config List
|
|
if(true == mbsfn_subfr_cnfg_list_opt)
|
|
{
|
|
sib2->mbsfn_subfr_cnfg_list_size = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
for(i=0; i<sib2->mbsfn_subfr_cnfg_list_size; i++)
|
|
{
|
|
liblte_rrc_unpack_mbsfn_subframe_config_ie(ie_ptr, &sib2->mbsfn_subfr_cnfg[i]);
|
|
}
|
|
}else{
|
|
sib2->mbsfn_subfr_cnfg_list_size = 0;
|
|
}
|
|
|
|
// Time Alignment Timer Common
|
|
liblte_rrc_unpack_time_alignment_timer_ie(ie_ptr, &sib2->time_alignment_timer);
|
|
|
|
// Extensions
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 3
|
|
|
|
Description: Contains cell reselection information common for
|
|
intra-frequency, inter-frequency, and/or inter-RAT
|
|
cell re-selection as well as intra-frequency cell
|
|
re-selection information other than neighboring
|
|
cell related
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_3_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
|
|
if(sib3 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Cell reselection info common
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib3->speed_state_resel_params.present, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sib3->q_hyst, ie_ptr, 4);
|
|
|
|
// Speed state reselection parameters
|
|
if(true == sib3->speed_state_resel_params.present)
|
|
{
|
|
liblte_rrc_pack_mobility_state_parameters_ie(&sib3->speed_state_resel_params.mobility_state_params, ie_ptr);
|
|
|
|
liblte_value_2_bits(sib3->speed_state_resel_params.q_hyst_sf.medium, ie_ptr, 2);
|
|
liblte_value_2_bits(sib3->speed_state_resel_params.q_hyst_sf.high, ie_ptr, 2);
|
|
}
|
|
}
|
|
|
|
// Cell reselection serving frequency information
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib3->s_non_intra_search_present, ie_ptr, 1);
|
|
|
|
if(true == sib3->s_non_intra_search_present)
|
|
{
|
|
liblte_rrc_pack_reselection_threshold_ie(sib3->s_non_intra_search, ie_ptr);
|
|
}
|
|
|
|
liblte_rrc_pack_reselection_threshold_ie(sib3->thresh_serving_low, ie_ptr);
|
|
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib3->cell_resel_prio, ie_ptr);
|
|
}
|
|
|
|
// Intra frequency cell reselection information
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib3->p_max_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib3->s_intra_search_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib3->allowed_meas_bw_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib3->t_resel_eutra_sf_present, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_q_rx_lev_min_ie(sib3->q_rx_lev_min, ie_ptr);
|
|
|
|
if(true == sib3->p_max_present)
|
|
{
|
|
liblte_rrc_pack_p_max_ie(sib3->p_max, ie_ptr);
|
|
}
|
|
|
|
if(true == sib3->s_intra_search_present)
|
|
{
|
|
liblte_rrc_pack_reselection_threshold_ie(sib3->s_intra_search, ie_ptr);
|
|
}
|
|
|
|
if(true == sib3->allowed_meas_bw_present)
|
|
{
|
|
liblte_rrc_pack_allowed_meas_bandwidth_ie(sib3->allowed_meas_bw, ie_ptr);
|
|
}
|
|
|
|
liblte_rrc_pack_presence_antenna_port_1_ie(sib3->presence_ant_port_1, ie_ptr);
|
|
|
|
liblte_rrc_pack_neigh_cell_config_ie(sib3->neigh_cell_cnfg, ie_ptr);
|
|
|
|
liblte_rrc_pack_t_reselection_ie(sib3->t_resel_eutra, ie_ptr);
|
|
|
|
if(true == sib3->t_resel_eutra_sf_present)
|
|
{
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&sib3->t_resel_eutra_sf, ie_ptr);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_3_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext_ind;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib3 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Cell reselection info common
|
|
{
|
|
// Optional indicator
|
|
sib3->speed_state_resel_params.present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sib3->q_hyst = (LIBLTE_RRC_Q_HYST_ENUM)liblte_bits_2_value(ie_ptr, 4);
|
|
|
|
// Speed state reselection parameters
|
|
if(true == sib3->speed_state_resel_params.present)
|
|
{
|
|
liblte_rrc_unpack_mobility_state_parameters_ie(ie_ptr, &sib3->speed_state_resel_params.mobility_state_params);
|
|
|
|
sib3->speed_state_resel_params.q_hyst_sf.medium = (LIBLTE_RRC_SF_MEDIUM_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
sib3->speed_state_resel_params.q_hyst_sf.high = (LIBLTE_RRC_SF_HIGH_ENUM)liblte_bits_2_value(ie_ptr, 2);
|
|
}
|
|
}
|
|
|
|
// Cell reselection serving frequency information
|
|
{
|
|
// Optional indicators
|
|
sib3->s_non_intra_search_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == sib3->s_non_intra_search_present)
|
|
{
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib3->s_non_intra_search);
|
|
}
|
|
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib3->thresh_serving_low);
|
|
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib3->cell_resel_prio);
|
|
}
|
|
|
|
// Intra frequency cell reselection information
|
|
{
|
|
// Optional indicators
|
|
sib3->p_max_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib3->s_intra_search_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib3->allowed_meas_bw_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib3->t_resel_eutra_sf_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_q_rx_lev_min_ie(ie_ptr, &sib3->q_rx_lev_min);
|
|
|
|
if(true == sib3->p_max_present)
|
|
{
|
|
liblte_rrc_unpack_p_max_ie(ie_ptr, &sib3->p_max);
|
|
}
|
|
|
|
if(true == sib3->s_intra_search_present)
|
|
{
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib3->s_intra_search);
|
|
}
|
|
|
|
if(true == sib3->allowed_meas_bw_present)
|
|
{
|
|
liblte_rrc_unpack_allowed_meas_bandwidth_ie(ie_ptr, &sib3->allowed_meas_bw);
|
|
}
|
|
|
|
liblte_rrc_unpack_presence_antenna_port_1_ie(ie_ptr, &sib3->presence_ant_port_1);
|
|
|
|
liblte_rrc_unpack_neigh_cell_config_ie(ie_ptr, &sib3->neigh_cell_cnfg);
|
|
|
|
liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib3->t_resel_eutra);
|
|
|
|
if(true == sib3->t_resel_eutra_sf_present)
|
|
{
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib3->t_resel_eutra_sf);
|
|
}
|
|
}
|
|
|
|
// Extensions
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 4
|
|
|
|
Description: Contains the neighboring cell related information
|
|
relevant only for intra-frequency cell reselection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_4_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *sib4,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(sib4 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
if(0 != sib4->intra_freq_neigh_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
if(0 != sib4->intra_freq_black_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(sib4->csg_phys_cell_id_range_present, ie_ptr, 1);
|
|
|
|
if(0 != sib4->intra_freq_neigh_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(sib4->intra_freq_neigh_cell_list_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib4->intra_freq_neigh_cell_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_phys_cell_id_ie(sib4->intra_freq_neigh_cell_list[i].phys_cell_id, ie_ptr);
|
|
liblte_rrc_pack_q_offset_range_ie(sib4->intra_freq_neigh_cell_list[i].q_offset_range, ie_ptr);
|
|
}
|
|
}
|
|
|
|
if(0 != sib4->intra_freq_black_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(sib4->intra_freq_black_cell_list_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib4->intra_freq_black_cell_list_size; i++)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_range_ie(&sib4->intra_freq_black_cell_list[i], ie_ptr);
|
|
}
|
|
}
|
|
|
|
if(true == sib4->csg_phys_cell_id_range_present)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_range_ie(&sib4->csg_phys_cell_id_range, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_4_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *sib4)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool ext_ind;
|
|
bool intra_freq_neigh_cell_list_opt;
|
|
bool intra_freq_black_cell_list_opt;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib4 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
intra_freq_neigh_cell_list_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
intra_freq_black_cell_list_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
sib4->csg_phys_cell_id_range_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == intra_freq_neigh_cell_list_opt)
|
|
{
|
|
sib4->intra_freq_neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib4->intra_freq_neigh_cell_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &sib4->intra_freq_neigh_cell_list[i].phys_cell_id);
|
|
liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &sib4->intra_freq_neigh_cell_list[i].q_offset_range);
|
|
}
|
|
}else{
|
|
sib4->intra_freq_neigh_cell_list_size = 0;
|
|
}
|
|
|
|
if(true == intra_freq_black_cell_list_opt)
|
|
{
|
|
sib4->intra_freq_black_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib4->intra_freq_black_cell_list_size; i++)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &sib4->intra_freq_black_cell_list[i]);
|
|
}
|
|
}else{
|
|
sib4->intra_freq_black_cell_list_size = 0;
|
|
}
|
|
|
|
if(true == sib4->csg_phys_cell_id_range_present)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &sib4->csg_phys_cell_id_range);
|
|
}
|
|
|
|
// Extension
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 5
|
|
|
|
Description: Contains information relevant only for
|
|
inter-frequency cell reselection, i.e. information
|
|
about other E-UTRA frequencies and inter-frequency
|
|
neighboring cells relevant for cell reselection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_5_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5_STRUCT *sib5,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 j;
|
|
|
|
if(sib5 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sib5->inter_freq_carrier_freq_list_size - 1, ie_ptr, 3);
|
|
for(i=0; i<sib5->inter_freq_carrier_freq_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].p_max_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present, ie_ptr, 1);
|
|
if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
|
|
liblte_rrc_pack_arfcn_value_eutra_ie(sib5->inter_freq_carrier_freq_list[i].dl_carrier_freq, ie_ptr);
|
|
liblte_rrc_pack_q_rx_lev_min_ie(sib5->inter_freq_carrier_freq_list[i].q_rx_lev_min, ie_ptr);
|
|
if(true == sib5->inter_freq_carrier_freq_list[i].p_max_present)
|
|
{
|
|
liblte_rrc_pack_p_max_ie(sib5->inter_freq_carrier_freq_list[i].p_max, ie_ptr);
|
|
}
|
|
liblte_rrc_pack_t_reselection_ie(sib5->inter_freq_carrier_freq_list[i].t_resel_eutra, ie_ptr);
|
|
if(true == sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present)
|
|
{
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf, ie_ptr);
|
|
}
|
|
liblte_rrc_pack_reselection_threshold_ie(sib5->inter_freq_carrier_freq_list[i].threshx_high, ie_ptr);
|
|
liblte_rrc_pack_reselection_threshold_ie(sib5->inter_freq_carrier_freq_list[i].threshx_low, ie_ptr);
|
|
liblte_rrc_pack_allowed_meas_bandwidth_ie(sib5->inter_freq_carrier_freq_list[i].allowed_meas_bw, ie_ptr);
|
|
liblte_rrc_pack_presence_antenna_port_1_ie(sib5->inter_freq_carrier_freq_list[i].presence_ant_port_1, ie_ptr);
|
|
if(true == sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib5->inter_freq_carrier_freq_list[i].cell_resel_prio, ie_ptr);
|
|
}
|
|
liblte_rrc_pack_neigh_cell_config_ie(sib5->inter_freq_carrier_freq_list[i].neigh_cell_cnfg, ie_ptr);
|
|
liblte_rrc_pack_q_offset_range_ie(sib5->inter_freq_carrier_freq_list[i].q_offset_freq, ie_ptr);
|
|
if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size - 1, ie_ptr, 4);
|
|
for(j=0; j<sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size; j++)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_ie(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].phys_cell_id, ie_ptr);
|
|
liblte_rrc_pack_q_offset_range_ie(sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].q_offset_cell, ie_ptr);
|
|
}
|
|
}
|
|
if(0 != sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size)
|
|
{
|
|
liblte_value_2_bits(sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size - 1, ie_ptr, 4);
|
|
for(j=0; j<sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size; j++)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_range_ie(&sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j], ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_5_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5_STRUCT *sib5)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 j;
|
|
bool ext_ind;
|
|
bool inter_freq_carrier_freq_list_ext_ind;
|
|
bool q_offset_freq_opt;
|
|
bool inter_freq_neigh_cell_list_opt;
|
|
bool inter_freq_black_cell_list_opt;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib5 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sib5->inter_freq_carrier_freq_list_size = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
for(i=0; i<sib5->inter_freq_carrier_freq_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
inter_freq_carrier_freq_list_ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
sib5->inter_freq_carrier_freq_list[i].p_max_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1);
|
|
q_offset_freq_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
inter_freq_neigh_cell_list_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
inter_freq_black_cell_list_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_arfcn_value_eutra_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].dl_carrier_freq);
|
|
liblte_rrc_unpack_q_rx_lev_min_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].q_rx_lev_min);
|
|
if(true == sib5->inter_freq_carrier_freq_list[i].p_max_present)
|
|
{
|
|
liblte_rrc_unpack_p_max_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].p_max);
|
|
}
|
|
liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].t_resel_eutra);
|
|
if(true == sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf_present)
|
|
{
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].t_resel_eutra_sf);
|
|
}
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].threshx_high);
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].threshx_low);
|
|
liblte_rrc_unpack_allowed_meas_bandwidth_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].allowed_meas_bw);
|
|
liblte_rrc_unpack_presence_antenna_port_1_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].presence_ant_port_1);
|
|
if(true == sib5->inter_freq_carrier_freq_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].cell_resel_prio);
|
|
}
|
|
liblte_rrc_unpack_neigh_cell_config_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].neigh_cell_cnfg);
|
|
if(true == q_offset_freq_opt)
|
|
{
|
|
liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].q_offset_freq);
|
|
}else{
|
|
sib5->inter_freq_carrier_freq_list[i].q_offset_freq = LIBLTE_RRC_Q_OFFSET_RANGE_DB_0;
|
|
}
|
|
if(true == inter_freq_neigh_cell_list_opt)
|
|
{
|
|
sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(j=0; j<sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size; j++)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].phys_cell_id);
|
|
liblte_rrc_unpack_q_offset_range_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list[j].q_offset_cell);
|
|
}
|
|
}else{
|
|
sib5->inter_freq_carrier_freq_list[i].inter_freq_neigh_cell_list_size = 0;
|
|
}
|
|
if(true == inter_freq_black_cell_list_opt)
|
|
{
|
|
sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(j=0; j<sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size; j++)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_range_ie(ie_ptr, &sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list[j]);
|
|
}
|
|
}else{
|
|
sib5->inter_freq_carrier_freq_list[i].inter_freq_black_cell_list_size = 0;
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 6
|
|
|
|
Description: Contains information relevant only for inter-RAT
|
|
cell reselection, i.e. information about UTRA
|
|
frequencies and UTRA neighboring cells relevant for
|
|
cell reselection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_6_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT *sib6,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(sib6 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
if(0 != sib6->carrier_freq_list_utra_fdd_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
if(0 != sib6->carrier_freq_list_utra_tdd_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(sib6->t_resel_utra_sf_present, ie_ptr, 1);
|
|
|
|
if(0 != sib6->carrier_freq_list_utra_fdd_size)
|
|
{
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib6->carrier_freq_list_utra_fdd_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_arfcn_value_utra_ie(sib6->carrier_freq_list_utra_fdd[i].carrier_freq, ie_ptr);
|
|
if(true == sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio, ie_ptr);
|
|
}
|
|
liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_fdd[i].threshx_high, ie_ptr);
|
|
liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_fdd[i].threshx_low, ie_ptr);
|
|
liblte_value_2_bits(((sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min - 1) / 2) + 60, ie_ptr, 6);
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].p_max_utra + 50, ie_ptr, 7);
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_fdd[i].q_qual_min + 24, ie_ptr, 5);
|
|
}
|
|
}
|
|
if(0 != sib6->carrier_freq_list_utra_tdd_size)
|
|
{
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_tdd_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib6->carrier_freq_list_utra_tdd_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_arfcn_value_utra_ie(sib6->carrier_freq_list_utra_tdd[i].carrier_freq, ie_ptr);
|
|
if(true == sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio, ie_ptr);
|
|
}
|
|
liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_tdd[i].threshx_high, ie_ptr);
|
|
liblte_rrc_pack_reselection_threshold_ie(sib6->carrier_freq_list_utra_tdd[i].threshx_low, ie_ptr);
|
|
liblte_value_2_bits(((sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min - 1) / 2) + 60, ie_ptr, 6);
|
|
liblte_value_2_bits(sib6->carrier_freq_list_utra_tdd[i].p_max_utra + 50, ie_ptr, 7);
|
|
}
|
|
}
|
|
liblte_rrc_pack_t_reselection_ie(sib6->t_resel_utra, ie_ptr);
|
|
if(true == sib6->t_resel_utra_sf_present)
|
|
{
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&sib6->t_resel_utra_sf, ie_ptr);
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_6_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT *sib6)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool ext_ind;
|
|
bool carrier_freq_list_utra_fdd_opt;
|
|
bool carrier_freq_list_utra_fdd_ext_ind;
|
|
bool carrier_freq_list_utra_tdd_opt;
|
|
bool carrier_freq_list_utra_tdd_ext_ind;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib6 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
carrier_freq_list_utra_fdd_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
carrier_freq_list_utra_tdd_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
sib6->t_resel_utra_sf_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == carrier_freq_list_utra_fdd_opt)
|
|
{
|
|
sib6->carrier_freq_list_utra_fdd_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib6->carrier_freq_list_utra_fdd_size; i++)
|
|
{
|
|
// Extension indicator
|
|
carrier_freq_list_utra_fdd_ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_arfcn_value_utra_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].carrier_freq);
|
|
if(true == sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].cell_resel_prio);
|
|
}
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].threshx_high);
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_fdd[i].threshx_low);
|
|
sib6->carrier_freq_list_utra_fdd[i].q_rx_lev_min = (int8)((liblte_bits_2_value(ie_ptr, 6) - 60) * 2) + 1;
|
|
sib6->carrier_freq_list_utra_fdd[i].p_max_utra = (int8)liblte_bits_2_value(ie_ptr, 7) - 50;
|
|
sib6->carrier_freq_list_utra_fdd[i].q_qual_min = (int8)liblte_bits_2_value(ie_ptr, 5) - 24;
|
|
}
|
|
}else{
|
|
sib6->carrier_freq_list_utra_fdd_size = 0;
|
|
}
|
|
if(true == carrier_freq_list_utra_tdd_opt)
|
|
{
|
|
sib6->carrier_freq_list_utra_tdd_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib6->carrier_freq_list_utra_tdd_size; i++)
|
|
{
|
|
// Extension indicator
|
|
carrier_freq_list_utra_tdd_ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_arfcn_value_utra_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].carrier_freq);
|
|
if(true == sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].cell_resel_prio);
|
|
}
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].threshx_high);
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib6->carrier_freq_list_utra_tdd[i].threshx_low);
|
|
sib6->carrier_freq_list_utra_tdd[i].q_rx_lev_min = (int8)((liblte_bits_2_value(ie_ptr, 6) * 2) + 1) - 60;
|
|
sib6->carrier_freq_list_utra_tdd[i].p_max_utra = (int8)liblte_bits_2_value(ie_ptr, 7) - 50;
|
|
}
|
|
}else{
|
|
sib6->carrier_freq_list_utra_tdd_size = 0;
|
|
}
|
|
liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib6->t_resel_utra);
|
|
if(true == sib6->t_resel_utra_sf_present)
|
|
{
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib6->t_resel_utra_sf);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 7
|
|
|
|
Description: Contains information relevant only for inter-RAT
|
|
cell reselection, i.e. information about GERAN
|
|
frequencies relevant for cell reselection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_7_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT *sib7,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(sib7 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib7->t_resel_geran_sf_present, ie_ptr, 1);
|
|
if(0 != sib7->carrier_freqs_info_list_size)
|
|
{
|
|
liblte_value_2_bits(1, ie_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
}
|
|
|
|
liblte_rrc_pack_t_reselection_ie(sib7->t_resel_geran, ie_ptr);
|
|
if(true == sib7->t_resel_geran_sf_present)
|
|
{
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&sib7->t_resel_geran_sf, ie_ptr);
|
|
}
|
|
if(0 != sib7->carrier_freqs_info_list_size)
|
|
{
|
|
liblte_value_2_bits(sib7->carrier_freqs_info_list_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib7->carrier_freqs_info_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_carrier_freqs_geran_ie(&sib7->carrier_freqs_info_list[i].carrier_freqs, ie_ptr);
|
|
|
|
// Common Info
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib7->carrier_freqs_info_list[i].cell_resel_prio_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib7->carrier_freqs_info_list[i].p_max_geran_present, ie_ptr, 1);
|
|
|
|
if(true == sib7->carrier_freqs_info_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib7->carrier_freqs_info_list[i].cell_resel_prio, ie_ptr);
|
|
}
|
|
liblte_value_2_bits(sib7->carrier_freqs_info_list[i].ncc_permitted, ie_ptr, 8);
|
|
liblte_value_2_bits((sib7->carrier_freqs_info_list[i].q_rx_lev_min + 115) / 2, ie_ptr, 6);
|
|
if(true == sib7->carrier_freqs_info_list[i].p_max_geran_present)
|
|
{
|
|
liblte_value_2_bits(sib7->carrier_freqs_info_list[i].p_max_geran, ie_ptr, 6);
|
|
}
|
|
liblte_rrc_pack_reselection_threshold_ie(sib7->carrier_freqs_info_list[i].threshx_high, ie_ptr);
|
|
liblte_rrc_pack_reselection_threshold_ie(sib7->carrier_freqs_info_list[i].threshx_low, ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_7_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT *sib7)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool ext_ind;
|
|
bool carrier_freqs_info_list_opt;
|
|
bool carrier_freqs_info_list_ext_ind;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib7 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
sib7->t_resel_geran_sf_present = liblte_bits_2_value(ie_ptr, 1);
|
|
carrier_freqs_info_list_opt = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib7->t_resel_geran);
|
|
if(true == sib7->t_resel_geran_sf_present)
|
|
{
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib7->t_resel_geran_sf);
|
|
}
|
|
if(true == carrier_freqs_info_list_opt)
|
|
{
|
|
sib7->carrier_freqs_info_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib7->carrier_freqs_info_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
carrier_freqs_info_list_ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_carrier_freqs_geran_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].carrier_freqs);
|
|
|
|
// Common Info
|
|
{
|
|
// Optional indicators
|
|
sib7->carrier_freqs_info_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib7->carrier_freqs_info_list[i].p_max_geran_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == sib7->carrier_freqs_info_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].cell_resel_prio);
|
|
}
|
|
sib7->carrier_freqs_info_list[i].ncc_permitted = liblte_bits_2_value(ie_ptr, 8);
|
|
sib7->carrier_freqs_info_list[i].q_rx_lev_min = (liblte_bits_2_value(ie_ptr, 6) * 2) - 115;
|
|
if(true == sib7->carrier_freqs_info_list[i].p_max_geran_present)
|
|
{
|
|
sib7->carrier_freqs_info_list[i].p_max_geran = liblte_bits_2_value(ie_ptr, 6);
|
|
}
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].threshx_high);
|
|
liblte_rrc_unpack_reselection_threshold_ie(ie_ptr, &sib7->carrier_freqs_info_list[i].threshx_low);
|
|
}
|
|
}
|
|
}else{
|
|
sib7->carrier_freqs_info_list_size = 0;
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 8
|
|
|
|
Description: Contains information relevant only for inter-RAT
|
|
cell re-selection i.e. information about CDMA2000
|
|
frequencies and CDMA2000 neighboring cells relevant
|
|
for cell re-selection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_8_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *sib8,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_RRC_NEIGH_CELL_CDMA2000_STRUCT *neigh_cell_list;
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 j;
|
|
uint32 k;
|
|
|
|
if(sib8 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib8->sys_time_info_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib8->search_win_size_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib8->params_hrpd_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib8->params_1xrtt_present, ie_ptr, 1);
|
|
|
|
if(true == sib8->sys_time_info_present)
|
|
{
|
|
liblte_rrc_pack_system_time_info_cdma2000_ie(&sib8->sys_time_info_cdma2000, ie_ptr);
|
|
}
|
|
|
|
if(true == sib8->search_win_size_present)
|
|
{
|
|
liblte_value_2_bits(sib8->search_win_size, ie_ptr, 4);
|
|
}
|
|
|
|
if(true == sib8->params_hrpd_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd_present, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_pre_registration_info_hrpd_ie(&sib8->pre_reg_info_hrpd, ie_ptr);
|
|
|
|
if(true == sib8->cell_resel_params_hrpd_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list_size - 1, ie_ptr, 5);
|
|
for(i=0; i<sib8->cell_resel_params_hrpd.band_class_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_band_class_cdma2000_ie(sib8->cell_resel_params_hrpd.band_class_list[i].band_class, ie_ptr);
|
|
if(true == sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio, ie_ptr);
|
|
}
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high, ie_ptr, 6);
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low, ie_ptr, 6);
|
|
}
|
|
|
|
liblte_value_2_bits(sib8->cell_resel_params_hrpd.neigh_cell_list_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib8->cell_resel_params_hrpd.neigh_cell_list_size; i++)
|
|
{
|
|
neigh_cell_list = &sib8->cell_resel_params_hrpd.neigh_cell_list[i];
|
|
liblte_rrc_pack_band_class_cdma2000_ie(neigh_cell_list->band_class, ie_ptr);
|
|
liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list_size - 1, ie_ptr, 4);
|
|
for(j=0; j<neigh_cell_list->neigh_cells_per_freq_list_size; j++)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].arfcn, ie_ptr);
|
|
liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size - 1, ie_ptr, 4);
|
|
for(k=0; k<neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k], ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
liblte_rrc_pack_t_reselection_ie(sib8->cell_resel_params_hrpd.t_resel_cdma2000, ie_ptr);
|
|
|
|
if(true == sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present)
|
|
{
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf, ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(true == sib8->params_1xrtt_present)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib8->csfb_reg_param_1xrtt_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib8->long_code_state_1xrtt_present, ie_ptr, 1);
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt_present, ie_ptr, 1);
|
|
|
|
if(true == sib8->csfb_reg_param_1xrtt_present)
|
|
{
|
|
liblte_rrc_pack_csfb_registration_param_1xrtt_ie(&sib8->csfb_reg_param_1xrtt, ie_ptr);
|
|
}
|
|
|
|
if(true == sib8->long_code_state_1xrtt_present)
|
|
{
|
|
liblte_value_2_bits((uint32)(sib8->long_code_state_1xrtt >> 10), ie_ptr, 32);
|
|
liblte_value_2_bits((uint32)(sib8->long_code_state_1xrtt & 0x3FF), ie_ptr, 10);
|
|
}
|
|
|
|
if(true == sib8->cell_resel_params_1xrtt_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list_size - 1, ie_ptr, 5);
|
|
for(i=0; i<sib8->cell_resel_params_1xrtt.band_class_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present, ie_ptr, 1);
|
|
|
|
liblte_rrc_pack_band_class_cdma2000_ie(sib8->cell_resel_params_1xrtt.band_class_list[i].band_class, ie_ptr);
|
|
if(true == sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_pack_cell_reselection_priority_ie(sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio, ie_ptr);
|
|
}
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high, ie_ptr, 6);
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low, ie_ptr, 6);
|
|
}
|
|
|
|
liblte_value_2_bits(sib8->cell_resel_params_1xrtt.neigh_cell_list_size - 1, ie_ptr, 4);
|
|
for(i=0; i<sib8->cell_resel_params_1xrtt.neigh_cell_list_size; i++)
|
|
{
|
|
neigh_cell_list = &sib8->cell_resel_params_1xrtt.neigh_cell_list[i];
|
|
liblte_rrc_pack_band_class_cdma2000_ie(neigh_cell_list->band_class, ie_ptr);
|
|
liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list_size - 1, ie_ptr, 4);
|
|
for(j=0; j<neigh_cell_list->neigh_cells_per_freq_list_size; j++)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].arfcn, ie_ptr);
|
|
liblte_value_2_bits(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size - 1, ie_ptr, 4);
|
|
for(k=0; k<neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++)
|
|
{
|
|
liblte_rrc_pack_phys_cell_id_cdma2000_ie(neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k], ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
liblte_rrc_pack_t_reselection_ie(sib8->cell_resel_params_1xrtt.t_resel_cdma2000, ie_ptr);
|
|
|
|
if(true == sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present)
|
|
{
|
|
liblte_rrc_pack_speed_state_scale_factors_ie(&sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf, ie_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_8_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *sib8)
|
|
{
|
|
LIBLTE_RRC_NEIGH_CELL_CDMA2000_STRUCT *neigh_cell_list;
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
uint32 j;
|
|
uint32 k;
|
|
bool ext_ind;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib8 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
sib8->sys_time_info_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib8->search_win_size_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib8->params_hrpd_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib8->params_1xrtt_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == sib8->sys_time_info_present)
|
|
{
|
|
liblte_rrc_unpack_system_time_info_cdma2000_ie(ie_ptr, &sib8->sys_time_info_cdma2000);
|
|
}
|
|
|
|
if(true == sib8->search_win_size_present)
|
|
{
|
|
sib8->search_win_size = liblte_bits_2_value(ie_ptr, 4);
|
|
}
|
|
|
|
if(true == sib8->params_hrpd_present)
|
|
{
|
|
// Optional indicator
|
|
sib8->cell_resel_params_hrpd_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_pre_registration_info_hrpd_ie(ie_ptr, &sib8->pre_reg_info_hrpd);
|
|
|
|
if(true == sib8->cell_resel_params_hrpd_present)
|
|
{
|
|
// Optional indicator
|
|
sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sib8->cell_resel_params_hrpd.band_class_list_size = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<sib8->cell_resel_params_hrpd.band_class_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &sib8->cell_resel_params_hrpd.band_class_list[i].band_class);
|
|
if(true == sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib8->cell_resel_params_hrpd.band_class_list[i].cell_resel_prio);
|
|
}
|
|
sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_high = liblte_bits_2_value(ie_ptr, 6);
|
|
sib8->cell_resel_params_hrpd.band_class_list[i].thresh_x_low = liblte_bits_2_value(ie_ptr, 6);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr);
|
|
|
|
}
|
|
|
|
sib8->cell_resel_params_hrpd.neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib8->cell_resel_params_hrpd.neigh_cell_list_size; i++)
|
|
{
|
|
neigh_cell_list = &sib8->cell_resel_params_hrpd.neigh_cell_list[i];
|
|
liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &neigh_cell_list->band_class);
|
|
neigh_cell_list->neigh_cells_per_freq_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(j=0; j<neigh_cell_list->neigh_cells_per_freq_list_size; j++)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].arfcn);
|
|
neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(k=0; k<neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k]);
|
|
}
|
|
}
|
|
}
|
|
liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib8->cell_resel_params_hrpd.t_resel_cdma2000);
|
|
|
|
if(true == sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf_present)
|
|
{
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib8->cell_resel_params_hrpd.t_resel_cdma2000_sf);
|
|
}
|
|
}
|
|
}else{
|
|
sib8->cell_resel_params_hrpd_present = false;
|
|
}
|
|
|
|
if(true == sib8->params_1xrtt_present)
|
|
{
|
|
// Optional indicators
|
|
sib8->csfb_reg_param_1xrtt_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib8->long_code_state_1xrtt_present = liblte_bits_2_value(ie_ptr, 1);
|
|
sib8->cell_resel_params_1xrtt_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == sib8->csfb_reg_param_1xrtt_present)
|
|
{
|
|
liblte_rrc_unpack_csfb_registration_param_1xrtt_ie(ie_ptr, &sib8->csfb_reg_param_1xrtt);
|
|
}
|
|
|
|
if(true == sib8->long_code_state_1xrtt_present)
|
|
{
|
|
sib8->long_code_state_1xrtt = (uint64)liblte_bits_2_value(ie_ptr, 32) << 10;
|
|
sib8->long_code_state_1xrtt |= (uint64)liblte_bits_2_value(ie_ptr, 10);
|
|
}
|
|
|
|
if(true == sib8->cell_resel_params_1xrtt_present)
|
|
{
|
|
// Optional indicator
|
|
sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sib8->cell_resel_params_1xrtt.band_class_list_size = liblte_bits_2_value(ie_ptr, 5) + 1;
|
|
for(i=0; i<sib8->cell_resel_params_1xrtt.band_class_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
bool ext2 = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicator
|
|
sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &sib8->cell_resel_params_1xrtt.band_class_list[i].band_class);
|
|
if(true == sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio_present)
|
|
{
|
|
liblte_rrc_unpack_cell_reselection_priority_ie(ie_ptr, &sib8->cell_resel_params_1xrtt.band_class_list[i].cell_resel_prio);
|
|
}
|
|
sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_high = liblte_bits_2_value(ie_ptr, 6);
|
|
sib8->cell_resel_params_1xrtt.band_class_list[i].thresh_x_low = liblte_bits_2_value(ie_ptr, 6);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext2, __func__, ie_ptr);
|
|
}
|
|
|
|
sib8->cell_resel_params_1xrtt.neigh_cell_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(i=0; i<sib8->cell_resel_params_1xrtt.neigh_cell_list_size; i++)
|
|
{
|
|
neigh_cell_list = &sib8->cell_resel_params_1xrtt.neigh_cell_list[i];
|
|
liblte_rrc_unpack_band_class_cdma2000_ie(ie_ptr, &neigh_cell_list->band_class);
|
|
neigh_cell_list->neigh_cells_per_freq_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(j=0; j<neigh_cell_list->neigh_cells_per_freq_list_size; j++)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].arfcn);
|
|
neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size = liblte_bits_2_value(ie_ptr, 4) + 1;
|
|
for(k=0; k<neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list_size; k++)
|
|
{
|
|
liblte_rrc_unpack_phys_cell_id_cdma2000_ie(ie_ptr, &neigh_cell_list->neigh_cells_per_freq_list[j].phys_cell_id_list[k]);
|
|
}
|
|
}
|
|
}
|
|
liblte_rrc_unpack_t_reselection_ie(ie_ptr, &sib8->cell_resel_params_1xrtt.t_resel_cdma2000);
|
|
|
|
if(true == sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf_present)
|
|
{
|
|
liblte_rrc_unpack_speed_state_scale_factors_ie(ie_ptr, &sib8->cell_resel_params_1xrtt.t_resel_cdma2000_sf);
|
|
}
|
|
}
|
|
}else{
|
|
sib8->csfb_reg_param_1xrtt_present = false;
|
|
sib8->long_code_state_1xrtt_present = false;
|
|
sib8->cell_resel_params_1xrtt_present = false;
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 9
|
|
|
|
Description: Contains a home eNB name (HNB name)
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_9_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *sib9,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(sib9 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib9->hnb_name_present, ie_ptr, 1);
|
|
|
|
if(true == sib9->hnb_name_present) {
|
|
// Dynamic octet string - hnb_name
|
|
liblte_value_2_bits(sib9->hnb_name_size - 1, ie_ptr, 6);
|
|
|
|
// Octets
|
|
for(i=0;i<sib9->hnb_name_size;i++) {
|
|
liblte_value_2_bits(sib9->hnb_name[i], ie_ptr, 8);
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_9_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *sib9)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
bool ext_ind;
|
|
uint32 i;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib9 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
sib9->hnb_name_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
if(true == sib9->hnb_name_present) {
|
|
// Dynamic octet string - hnb_name
|
|
// Length
|
|
sib9->hnb_name_size = liblte_bits_2_value(ie_ptr, 6) + 1;
|
|
|
|
// Octets
|
|
for(i=0;i<sib9->hnb_name_size;i++) {
|
|
sib9->hnb_name[i] = liblte_bits_2_value(ie_ptr, 8);
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 10
|
|
|
|
Description: Contains an ETWS primary notification
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 11
|
|
|
|
Description: Contains an ETWS secondary notification
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 12
|
|
|
|
Description: Contains a CMAS notification
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
IE Name: System Information Block Type 13
|
|
|
|
Description: Contains the information required to acquire the
|
|
MBMS control information associated with one or more
|
|
MBSFN areas
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.3.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_13_ie(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13,
|
|
uint8 **ie_ptr)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
|
|
if(sib13 != NULL &&
|
|
ie_ptr != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(0, ie_ptr, 1);
|
|
|
|
liblte_value_2_bits(sib13->mbsfn_area_info_list_r9_size - 1, ie_ptr, 3);
|
|
for(i=0; i<sib13->mbsfn_area_info_list_r9_size; i++)
|
|
{
|
|
liblte_rrc_pack_mbsfn_area_info_ie(&sib13->mbsfn_area_info_list_r9[i], ie_ptr);
|
|
}
|
|
liblte_rrc_pack_mbsfn_notification_config_ie(&sib13->mbms_notification_config, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_13_ie(uint8 **ie_ptr,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint32 i;
|
|
bool ext_ind;
|
|
bool non_crit_ext_present;
|
|
|
|
if(ie_ptr != NULL &&
|
|
sib13 != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext_ind = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
// Optional indicators
|
|
non_crit_ext_present = liblte_bits_2_value(ie_ptr, 1);
|
|
|
|
sib13->mbsfn_area_info_list_r9_size = liblte_bits_2_value(ie_ptr, 3) + 1;
|
|
for(i=0; i<sib13->mbsfn_area_info_list_r9_size; i++)
|
|
{
|
|
liblte_rrc_unpack_mbsfn_area_info_ie(ie_ptr, &sib13->mbsfn_area_info_list_r9[i]);
|
|
}
|
|
liblte_rrc_unpack_mbsfn_notification_config_ie(ie_ptr, &sib13->mbms_notification_config);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext_ind, __func__, ie_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
MESSAGE FUNCTIONS
|
|
*******************************************************************************/
|
|
|
|
/*********************************************************************
|
|
Message Name: UL Information Transfer
|
|
|
|
Description: Used for the uplink transfer dedicated NAS
|
|
information
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_information_transfer_msg(LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *ul_info_transfer,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(ul_info_transfer != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Dedicated info type choice
|
|
liblte_value_2_bits(ul_info_transfer->dedicated_info_type, &msg_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS == ul_info_transfer->dedicated_info_type)
|
|
{
|
|
liblte_rrc_pack_dedicated_info_nas_ie(&ul_info_transfer->dedicated_info,
|
|
&msg_ptr);
|
|
}else{
|
|
liblte_rrc_pack_dedicated_info_cdma2000_ie(&ul_info_transfer->dedicated_info,
|
|
&msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_information_transfer_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *ul_info_transfer)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
ul_info_transfer != NULL)
|
|
{
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Dedicated info type choice
|
|
ul_info_transfer->dedicated_info_type = (LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_UL_INFORMATION_TRANSFER_TYPE_NAS == ul_info_transfer->dedicated_info_type)
|
|
{
|
|
liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr,
|
|
&ul_info_transfer->dedicated_info);
|
|
}else{
|
|
liblte_rrc_unpack_dedicated_info_cdma2000_ie(&msg_ptr,
|
|
&ul_info_transfer->dedicated_info);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: UL Handover Preparation Transfer (CDMA2000)
|
|
|
|
Description: Used for the uplink transfer of handover related
|
|
CDMA2000 information when requested by the higher
|
|
layers
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: UE Information Response
|
|
|
|
Description: Used by the UE to transfer the information requested
|
|
by the E-UTRAN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: UE Information Request
|
|
|
|
Description: Used by E-UTRAN to retrieve information from the UE
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_information_request_msg(LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *ue_info_req,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(ue_info_req != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(ue_info_req->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// RACH report required
|
|
liblte_value_2_bits(ue_info_req->rach_report_req, &msg_ptr, 1);
|
|
|
|
// RLF report required
|
|
liblte_value_2_bits(ue_info_req->rlf_report_req, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_information_request_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *ue_info_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
ue_info_req != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&ue_info_req->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// RACH report required
|
|
ue_info_req->rach_report_req = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// RLF report required
|
|
ue_info_req->rlf_report_req = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: UE Capability Information
|
|
|
|
Description: Used to transfer UE radio access capabilities
|
|
requested by the E-UTRAN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_information_msg(LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *ue_capability_info,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
|
|
if(ue_capability_info != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(ue_capability_info->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 3);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
liblte_value_2_bits(ue_capability_info->N_ue_caps, &msg_ptr, 4);
|
|
for(i=0; i<ue_capability_info->N_ue_caps; i++)
|
|
{
|
|
// RAT-Type
|
|
liblte_value_2_bits(0, &msg_ptr, 1); //Optional indicator
|
|
liblte_value_2_bits(ue_capability_info->ue_capability_rat[i].rat_type, &msg_ptr, 3);
|
|
|
|
// Octet string
|
|
LIBLTE_BIT_MSG_STRUCT tmp;
|
|
liblte_rrc_pack_ue_eutra_capability_ie(&ue_capability_info->ue_capability_rat[i].eutra_capability, &tmp);
|
|
|
|
uint32 pad = 8 - tmp.N_bits%8;
|
|
uint32 n_bytes = (tmp.N_bits+pad) / 8;
|
|
if(n_bytes < 128)
|
|
{
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
liblte_value_2_bits(n_bytes, &msg_ptr, 7);
|
|
}else if(n_bytes < 16383){
|
|
liblte_value_2_bits(1, &msg_ptr, 1);
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
liblte_value_2_bits(n_bytes, &msg_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
}
|
|
|
|
for(i=0; i<tmp.N_bits; i++)
|
|
{
|
|
*msg_ptr = tmp.msg[i];
|
|
msg_ptr++;
|
|
}
|
|
|
|
msg_ptr += pad;
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_information_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *ue_capability_info)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
|
|
if(msg != NULL &&
|
|
ue_capability_info != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&ue_capability_info->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
ue_capability_info->N_ue_caps = liblte_bits_2_value(&msg_ptr, 4);
|
|
for(i=0; i<ue_capability_info->N_ue_caps; i++)
|
|
{
|
|
liblte_bits_2_value(&msg_ptr, 1); //Optional indicator
|
|
ue_capability_info->ue_capability_rat[i].rat_type = (LIBLTE_RRC_RAT_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
//Octet string
|
|
uint32 n_bytes = 0;
|
|
if(0 == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
n_bytes = liblte_bits_2_value(&msg_ptr, 7);
|
|
}else{
|
|
if(0 == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
n_bytes = liblte_bits_2_value(&msg_ptr, 14);
|
|
}else{
|
|
// FIXME: Unlikely to have more than 16K of octets
|
|
n_bytes = 0;
|
|
}
|
|
}
|
|
|
|
liblte_rrc_unpack_ue_eutra_capability_ie(&msg_ptr, &ue_capability_info->ue_capability_rat[i].eutra_capability);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
Message Name: UE Capability Enquiry
|
|
|
|
Description: Used to request the transfer of UE radio access
|
|
capabilities for E-UTRA as well as for other RATs
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ue_capability_enquiry_msg(LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_cap_enquiry,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
|
|
if(ue_cap_enquiry != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(ue_cap_enquiry->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// UE-CapabilityRequest
|
|
liblte_value_2_bits(ue_cap_enquiry->N_ue_cap_reqs - 1, &msg_ptr, 3);
|
|
for(i=0; i<LIBLTE_RRC_MAX_RAT_CAPABILITIES; i++)
|
|
{
|
|
liblte_rrc_pack_rat_type_ie(ue_cap_enquiry->ue_capability_request[i], &msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ue_capability_enquiry_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *ue_cap_enquiry)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
|
|
if(msg != NULL &&
|
|
ue_cap_enquiry != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&ue_cap_enquiry->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
ue_cap_enquiry->N_ue_cap_reqs = liblte_bits_2_value(&msg_ptr, 3) + 1;
|
|
for(i=0; i<ue_cap_enquiry->N_ue_cap_reqs; i++)
|
|
{
|
|
liblte_rrc_unpack_rat_type_ie(&msg_ptr, &ue_cap_enquiry->ue_capability_request[i]);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
|
|
/*********************************************************************
|
|
Message Name: System Information Block Type 1
|
|
|
|
Description: Contains information relevant when evaluating if a
|
|
UE is allowed to access a cell and defines the
|
|
scheduling of other system information
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_block_type_1_msg(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
uint32 j;
|
|
uint8 non_crit_ext_opt = false;
|
|
uint8 csg_id_opt = false;
|
|
uint8 q_rx_lev_min_offset_opt = false;
|
|
uint8 extension = false;
|
|
|
|
if(sib1 != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(sib1->p_max_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(sib1->tdd, &msg_ptr, 1);
|
|
liblte_value_2_bits(non_crit_ext_opt, &msg_ptr, 1);
|
|
|
|
// Cell Access Related Info
|
|
liblte_value_2_bits(csg_id_opt, &msg_ptr, 1);
|
|
liblte_value_2_bits(sib1->N_plmn_ids - 1, &msg_ptr, 3);
|
|
for(i=0; i<sib1->N_plmn_ids; i++)
|
|
{
|
|
liblte_rrc_pack_plmn_identity_ie(&sib1->plmn_id[i].id, &msg_ptr);
|
|
liblte_value_2_bits(sib1->plmn_id[i].resv_for_oper, &msg_ptr, 1);
|
|
}
|
|
liblte_rrc_pack_tracking_area_code_ie(sib1->tracking_area_code, &msg_ptr);
|
|
liblte_rrc_pack_cell_identity_ie(sib1->cell_id, &msg_ptr);
|
|
liblte_value_2_bits(sib1->cell_barred, &msg_ptr, 1);
|
|
liblte_value_2_bits(sib1->intra_freq_reselection, &msg_ptr, 1);
|
|
liblte_value_2_bits(sib1->csg_indication, &msg_ptr, 1);
|
|
if(true == csg_id_opt)
|
|
{
|
|
liblte_rrc_pack_csg_identity_ie(sib1->csg_id, &msg_ptr);
|
|
}
|
|
|
|
// Cell Selection Info
|
|
liblte_value_2_bits(q_rx_lev_min_offset_opt, &msg_ptr, 1);
|
|
liblte_rrc_pack_q_rx_lev_min_ie(sib1->q_rx_lev_min, &msg_ptr);
|
|
if(true == q_rx_lev_min_offset_opt)
|
|
{
|
|
liblte_value_2_bits((sib1->q_rx_lev_min_offset / 2) - 1, &msg_ptr, 3);
|
|
}
|
|
|
|
// P Max
|
|
if(true == sib1->p_max_present)
|
|
{
|
|
liblte_rrc_pack_p_max_ie(sib1->p_max, &msg_ptr);
|
|
}
|
|
|
|
// Freq Band Indicator
|
|
liblte_value_2_bits(sib1->freq_band_indicator - 1, &msg_ptr, 6);
|
|
|
|
// Scheduling Info List
|
|
liblte_value_2_bits(sib1->N_sched_info - 1, &msg_ptr, 5);
|
|
for(i=0; i<sib1->N_sched_info; i++)
|
|
{
|
|
liblte_value_2_bits(sib1->sched_info[i].si_periodicity, &msg_ptr, 3);
|
|
liblte_value_2_bits(sib1->sched_info[i].N_sib_mapping_info, &msg_ptr, 5);
|
|
for(j=0; j<sib1->sched_info[i].N_sib_mapping_info; j++)
|
|
{
|
|
liblte_value_2_bits(extension, &msg_ptr, 1);
|
|
liblte_value_2_bits(sib1->sched_info[i].sib_mapping_info[j].sib_type, &msg_ptr, 4);
|
|
}
|
|
}
|
|
|
|
// TDD Config
|
|
if(true == sib1->tdd)
|
|
{
|
|
liblte_rrc_pack_tdd_config_ie(&sib1->tdd_cnfg, &msg_ptr);
|
|
}
|
|
|
|
// SI Window Length
|
|
liblte_value_2_bits(sib1->si_window_length, &msg_ptr, 3);
|
|
|
|
// System Info Value Tag
|
|
liblte_value_2_bits(sib1->system_info_value_tag, &msg_ptr, 5);
|
|
|
|
// Non Critical Extension
|
|
// FIXME
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_block_type_1_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *sib1,
|
|
uint32 *N_bits_used)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
uint32 j;
|
|
bool tdd_config_opt;
|
|
bool non_crit_ext_opt;
|
|
bool csg_id_opt;
|
|
bool q_rx_lev_min_offset_opt;
|
|
bool extension;
|
|
|
|
if(msg != NULL &&
|
|
sib1 != NULL &&
|
|
N_bits_used != NULL)
|
|
{
|
|
|
|
// Optional indicators
|
|
sib1->p_max_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
tdd_config_opt = liblte_bits_2_value(&msg_ptr, 1);
|
|
non_crit_ext_opt = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Cell Access Related Info
|
|
csg_id_opt = liblte_bits_2_value(&msg_ptr, 1);
|
|
sib1->N_plmn_ids = liblte_bits_2_value(&msg_ptr, 3) + 1;
|
|
for(i=0; i<sib1->N_plmn_ids; i++)
|
|
{
|
|
liblte_rrc_unpack_plmn_identity_ie(&msg_ptr, &sib1->plmn_id[i].id);
|
|
if(LIBLTE_RRC_MCC_NOT_PRESENT == sib1->plmn_id[i].id.mcc &&
|
|
0 != i)
|
|
{
|
|
sib1->plmn_id[i].id.mcc = sib1->plmn_id[i-1].id.mcc;
|
|
}
|
|
sib1->plmn_id[i].resv_for_oper = (LIBLTE_RRC_RESV_FOR_OPER_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
}
|
|
liblte_rrc_unpack_tracking_area_code_ie(&msg_ptr, &sib1->tracking_area_code);
|
|
liblte_rrc_unpack_cell_identity_ie(&msg_ptr, &sib1->cell_id);
|
|
sib1->cell_barred = (LIBLTE_RRC_CELL_BARRED_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
sib1->intra_freq_reselection = (LIBLTE_RRC_INTRA_FREQ_RESELECTION_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
sib1->csg_indication = liblte_bits_2_value(&msg_ptr, 1);
|
|
if(true == csg_id_opt)
|
|
{
|
|
liblte_rrc_unpack_csg_identity_ie(&msg_ptr, &sib1->csg_id);
|
|
}else{
|
|
sib1->csg_id = LIBLTE_RRC_CSG_IDENTITY_NOT_PRESENT;
|
|
}
|
|
|
|
// Cell Selection Info
|
|
q_rx_lev_min_offset_opt = liblte_bits_2_value(&msg_ptr, 1);
|
|
liblte_rrc_unpack_q_rx_lev_min_ie(&msg_ptr, &sib1->q_rx_lev_min);
|
|
if(true == q_rx_lev_min_offset_opt)
|
|
{
|
|
sib1->q_rx_lev_min_offset = (liblte_bits_2_value(&msg_ptr, 3) + 1) * 2;
|
|
}else{
|
|
sib1->q_rx_lev_min_offset = 0;
|
|
}
|
|
|
|
// P Max
|
|
if(true == sib1->p_max_present)
|
|
{
|
|
liblte_rrc_unpack_p_max_ie(&msg_ptr, &sib1->p_max);
|
|
}
|
|
|
|
// Freq Band Indicator
|
|
sib1->freq_band_indicator = liblte_bits_2_value(&msg_ptr, 6) + 1;
|
|
|
|
// Scheduling Info List
|
|
sib1->N_sched_info = liblte_bits_2_value(&msg_ptr, 5) + 1;
|
|
for(i=0; i<sib1->N_sched_info; i++)
|
|
{
|
|
sib1->sched_info[i].si_periodicity = (LIBLTE_RRC_SI_PERIODICITY_ENUM)liblte_bits_2_value(&msg_ptr, 3);
|
|
sib1->sched_info[i].N_sib_mapping_info = liblte_bits_2_value(&msg_ptr, 5);
|
|
for(j=0; j<sib1->sched_info[i].N_sib_mapping_info; j++)
|
|
{
|
|
extension = liblte_bits_2_value(&msg_ptr, 1);
|
|
sib1->sched_info[i].sib_mapping_info[j].sib_type = (LIBLTE_RRC_SIB_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4);
|
|
}
|
|
}
|
|
|
|
// TDD Config
|
|
if(true == tdd_config_opt)
|
|
{
|
|
sib1->tdd = true;
|
|
liblte_rrc_unpack_tdd_config_ie(&msg_ptr, &sib1->tdd_cnfg);
|
|
}else{
|
|
sib1->tdd = false;
|
|
}
|
|
|
|
// SI Window Length
|
|
sib1->si_window_length = (LIBLTE_RRC_SI_WINDOW_LENGTH_ENUM)liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
// System Info Value Tag
|
|
sib1->system_info_value_tag = liblte_bits_2_value(&msg_ptr, 5);
|
|
|
|
// Non Critical Extension
|
|
liblte_rrc_consume_noncrit_extension(non_crit_ext_opt, __func__, &msg_ptr);
|
|
|
|
// N_bits_used
|
|
*N_bits_used = msg_ptr - (msg->msg);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: System Information
|
|
|
|
Description: Conveys one or more System Information Blocks
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_sys_info_msg(LIBLTE_RRC_SYS_INFO_MSG_STRUCT *sibs,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 *length_ptr;
|
|
uint32 length;
|
|
uint32 pad_bits;
|
|
uint32 i;
|
|
|
|
if(sibs != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Critical extensions choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Number of SIBs present
|
|
liblte_value_2_bits(sibs->N_sibs - 1, &msg_ptr, 5);
|
|
|
|
for(i=0; i<sibs->N_sibs; i++)
|
|
{
|
|
if(sibs->sibs[i].sib_type < LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
liblte_value_2_bits(sibs->sibs[i].sib_type, &msg_ptr, 4);
|
|
switch(sibs->sibs[i].sib_type)
|
|
{
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2:
|
|
err = liblte_rrc_pack_sys_info_block_type_2_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3:
|
|
err = liblte_rrc_pack_sys_info_block_type_3_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4:
|
|
err = liblte_rrc_pack_sys_info_block_type_4_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8:
|
|
err = liblte_rrc_pack_sys_info_block_type_8_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9:
|
|
err = liblte_rrc_pack_sys_info_block_type_9_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5:
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6:
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7:
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_10:
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_11:
|
|
default:
|
|
printf("ERROR: Not handling sib type %u\n", sibs->sibs[i].sib_type);
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
break;
|
|
}
|
|
}else{
|
|
// Extension indicator
|
|
liblte_value_2_bits(1, &msg_ptr, 1);
|
|
|
|
liblte_value_2_bits(sibs->sibs[i].sib_type - 10, &msg_ptr, 7);
|
|
length_ptr = msg_ptr;
|
|
liblte_value_2_bits(0, &msg_ptr, 8);
|
|
switch(sibs->sibs[i].sib_type)
|
|
{
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13:
|
|
err = liblte_rrc_pack_sys_info_block_type_13_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12:
|
|
default:
|
|
printf("ERROR: Not handling extended sib type %s\n", liblte_rrc_sys_info_block_type_text[sibs->sibs[i].sib_type]);
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
break;
|
|
}
|
|
length = ((msg_ptr - length_ptr) / 8) - 1;
|
|
pad_bits = (msg_ptr - length_ptr) % 8;
|
|
if(0 != pad_bits)
|
|
{
|
|
length++;
|
|
}
|
|
if(length < 128)
|
|
{
|
|
liblte_value_2_bits(0, &length_ptr, 1);
|
|
liblte_value_2_bits(length, &length_ptr, 7);
|
|
}else{
|
|
msg_ptr = length_ptr;
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
liblte_value_2_bits(length, &msg_ptr, 14);
|
|
switch(sibs->sibs[i].sib_type)
|
|
{
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13:
|
|
err = liblte_rrc_pack_sys_info_block_type_13_ie((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *)&sibs->sibs[i].sib,
|
|
&msg_ptr);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12:
|
|
default:
|
|
printf("ERROR: Not handling extended sib type %s\n", liblte_rrc_sys_info_block_type_text[sibs->sibs[i].sib_type]);
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
break;
|
|
}
|
|
}
|
|
liblte_value_2_bits(0, &msg_ptr, pad_bits);
|
|
}
|
|
|
|
if(LIBLTE_SUCCESS != err)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_sys_info_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_SYS_INFO_MSG_STRUCT *sibs)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 *head_ptr;
|
|
uint32 i;
|
|
uint32 length_determinant_octets;
|
|
uint8 non_crit_ext_opt;
|
|
|
|
if(msg != NULL &&
|
|
sibs != NULL)
|
|
{
|
|
// Critical extensions choice
|
|
if(0 == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
// Optional indicator
|
|
non_crit_ext_opt = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Number of SIBs present
|
|
sibs->N_sibs = liblte_bits_2_value(&msg_ptr, 5) + 1;
|
|
|
|
for(i=0; i<sibs->N_sibs; i++)
|
|
{
|
|
// Extension indicator
|
|
if(0 == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
sibs->sibs[i].sib_type = (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4);
|
|
switch(sibs->sibs[i].sib_type)
|
|
{
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2:
|
|
err = liblte_rrc_unpack_sys_info_block_type_2_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3:
|
|
err = liblte_rrc_unpack_sys_info_block_type_3_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4:
|
|
err = liblte_rrc_unpack_sys_info_block_type_4_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_4_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5:
|
|
err = liblte_rrc_unpack_sys_info_block_type_5_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_5_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6:
|
|
err = liblte_rrc_unpack_sys_info_block_type_6_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_6_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7:
|
|
err = liblte_rrc_unpack_sys_info_block_type_7_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_7_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8:
|
|
err = liblte_rrc_unpack_sys_info_block_type_8_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_8_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9:
|
|
err = liblte_rrc_unpack_sys_info_block_type_9_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_10:
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_11:
|
|
default:
|
|
printf("ERROR: Not handling sib type %u\n", sibs->sibs[i].sib_type);
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
break;
|
|
}
|
|
}else{
|
|
sibs->sibs[i].sib_type = (LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_ENUM)(liblte_bits_2_value(&msg_ptr, 7) + 10);
|
|
length_determinant_octets = 0;
|
|
if(0 == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
length_determinant_octets = liblte_bits_2_value(&msg_ptr, 7);
|
|
}else{
|
|
if(0 == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
length_determinant_octets = liblte_bits_2_value(&msg_ptr, 14);
|
|
}else{
|
|
printf("ERROR: Not handling fragmented length determinants\n");
|
|
}
|
|
}
|
|
head_ptr = msg_ptr;
|
|
switch(sibs->sibs[i].sib_type)
|
|
{
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13:
|
|
err = liblte_rrc_unpack_sys_info_block_type_13_ie(&msg_ptr,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *)&sibs->sibs[i].sib);
|
|
break;
|
|
case LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_12:
|
|
default:
|
|
printf("ERROR: Not handling extended sib type %s\n", liblte_rrc_sys_info_block_type_text[sibs->sibs[i].sib_type]);
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
break;
|
|
}
|
|
liblte_bits_2_value(&msg_ptr, (msg_ptr - head_ptr) % 8);
|
|
}
|
|
|
|
if(LIBLTE_SUCCESS != err)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(non_crit_ext_opt, __func__, &msg_ptr);
|
|
|
|
}else{
|
|
printf("ERROR: Not handling critical extensions in system information message\n");
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Mode Failure
|
|
|
|
Description: Used to indicate an unsuccessful completion of a
|
|
security mode command
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_failure_msg(LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *security_mode_failure,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(security_mode_failure != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(security_mode_failure->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_failure_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *security_mode_failure)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
security_mode_failure != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&security_mode_failure->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Mode Complete
|
|
|
|
Description: Used to confirm the successful completion of a
|
|
security mode command
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_complete_msg(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *security_mode_complete,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(security_mode_complete != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(security_mode_complete->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_complete_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *security_mode_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
security_mode_complete != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&security_mode_complete->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Security Mode Command
|
|
|
|
Description: Used to command the activation of AS security
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_security_mode_command_msg(LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *security_mode_cmd,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(security_mode_cmd != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(security_mode_cmd->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Security Algorithms Config
|
|
liblte_rrc_pack_security_algorithm_config_ie(&security_mode_cmd->sec_algs,
|
|
&msg_ptr);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_security_mode_command_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *security_mode_cmd)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg_ptr != NULL &&
|
|
security_mode_cmd != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&security_mode_cmd->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Extension indicator
|
|
bool ext2 = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext2, __func__, &msg_ptr);
|
|
|
|
// Security Algorithms Config
|
|
liblte_rrc_unpack_security_algorithm_config_ie(&msg_ptr,
|
|
&security_mode_cmd->sec_algs);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Setup Complete
|
|
|
|
Description: Used to confirm the successful completion of an RRC
|
|
connection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_complete_msg(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *con_setup_complete,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_setup_complete != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_setup_complete->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(con_setup_complete->registered_mme_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Selected PLMN identity
|
|
liblte_value_2_bits(con_setup_complete->selected_plmn_id - 1, &msg_ptr, 3);
|
|
|
|
// Registered MME
|
|
if(con_setup_complete->registered_mme_present)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(con_setup_complete->registered_mme.plmn_id_present, &msg_ptr, 1);
|
|
|
|
// PLMN identity
|
|
if(con_setup_complete->registered_mme.plmn_id_present)
|
|
{
|
|
liblte_rrc_pack_plmn_identity_ie(&con_setup_complete->registered_mme.plmn_id, &msg_ptr);
|
|
}
|
|
|
|
// MMEGI
|
|
liblte_value_2_bits(con_setup_complete->registered_mme.mmegi, &msg_ptr, 16);
|
|
|
|
// MMEC
|
|
liblte_rrc_pack_mmec_ie(con_setup_complete->registered_mme.mmec, &msg_ptr);
|
|
}
|
|
|
|
// Dedicated info NAS
|
|
liblte_rrc_pack_dedicated_info_nas_ie(&con_setup_complete->dedicated_info_nas,
|
|
&msg_ptr);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_setup_complete_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *con_setup_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_setup_complete != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&con_setup_complete->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicators
|
|
con_setup_complete->registered_mme_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Selected PLMN identity
|
|
con_setup_complete->selected_plmn_id = liblte_bits_2_value(&msg_ptr, 3) + 1;
|
|
|
|
// Registered MME
|
|
if(con_setup_complete->registered_mme_present)
|
|
{
|
|
// Optional indicator
|
|
con_setup_complete->registered_mme.plmn_id_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// PLMN identity
|
|
if(con_setup_complete->registered_mme.plmn_id_present)
|
|
{
|
|
liblte_rrc_unpack_plmn_identity_ie(&msg_ptr, &con_setup_complete->registered_mme.plmn_id);
|
|
}
|
|
|
|
// MMEGI
|
|
con_setup_complete->registered_mme.mmegi = liblte_bits_2_value(&msg_ptr, 16);
|
|
|
|
// MMEC
|
|
liblte_rrc_unpack_mmec_ie(&msg_ptr, &con_setup_complete->registered_mme.mmec);
|
|
}
|
|
|
|
// Dedicated info NAS
|
|
liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr,
|
|
&con_setup_complete->dedicated_info_nas);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Setup
|
|
|
|
Description: Used to establish SRB1
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_setup_msg(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *con_setup,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_setup != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_setup->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 3);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Radio Resource Config Dedicated
|
|
liblte_rrc_pack_rr_config_dedicated_ie(&con_setup->rr_cnfg, &msg_ptr);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_setup_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_SETUP_STRUCT *con_setup)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_setup != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&con_setup->rrc_transaction_id);
|
|
|
|
// Critical extension indicator
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Radio Resource Config Dedicated
|
|
liblte_rrc_unpack_rr_config_dedicated_ie(&msg_ptr, &con_setup->rr_cnfg);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Request
|
|
|
|
Description: Used to request the establishment of an RRC
|
|
connection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_request_msg(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *con_req,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(con_req != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
// UE Identity Type
|
|
liblte_value_2_bits(con_req->ue_id_type, &msg_ptr, 1);
|
|
|
|
// UE Identity
|
|
if(LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI == con_req->ue_id_type)
|
|
{
|
|
liblte_rrc_pack_s_tmsi_ie((LIBLTE_RRC_S_TMSI_STRUCT *)&con_req->ue_id,
|
|
&msg_ptr);
|
|
}else{ // LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE == con_req->ue_id_type
|
|
liblte_value_2_bits((uint32)(con_req->ue_id.random >> 32), &msg_ptr, 8);
|
|
liblte_value_2_bits((uint32)(con_req->ue_id.random), &msg_ptr, 32);
|
|
}
|
|
|
|
// Establishment Cause
|
|
liblte_value_2_bits(con_req->cause, &msg_ptr, 3);
|
|
|
|
// Spare
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_request_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *con_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_req != NULL)
|
|
{
|
|
// Extension Choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// UE Identity Type
|
|
con_req->ue_id_type = (LIBLTE_RRC_CON_REQ_UE_ID_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// UE Identity
|
|
if(LIBLTE_RRC_CON_REQ_UE_ID_TYPE_S_TMSI == con_req->ue_id_type)
|
|
{
|
|
liblte_rrc_unpack_s_tmsi_ie(&msg_ptr,
|
|
(LIBLTE_RRC_S_TMSI_STRUCT *)&con_req->ue_id);
|
|
}else{ // LIBLTE_RRC_CON_REQ_UE_ID_TYPE_RANDOM_VALUE == con_req->ue_id_type
|
|
con_req->ue_id.random = (uint64)liblte_bits_2_value(&msg_ptr, 8) << 32;
|
|
con_req->ue_id.random |= liblte_bits_2_value(&msg_ptr, 32);
|
|
}
|
|
|
|
// Establishment Cause
|
|
con_req->cause = (LIBLTE_RRC_CON_REQ_EST_CAUSE_ENUM)liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Release
|
|
|
|
Description: Used to command the release of an RRC connection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_release_msg(LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *con_release,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_release != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_release->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Release cause
|
|
liblte_value_2_bits(con_release->release_cause, &msg_ptr, 2);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_release_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *con_release)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_release != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&con_release->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicators
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Release cause
|
|
con_release->release_cause = (LIBLTE_RRC_RELEASE_CAUSE_ENUM)liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reject
|
|
|
|
Description: Used to reject the RRC connection establishment
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reject_msg(LIBLTE_RRC_CONNECTION_REJECT_STRUCT *con_rej,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_rej != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Wait Time
|
|
liblte_value_2_bits(con_rej->wait_time, &msg_ptr, 4);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reject_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_REJECT_STRUCT *con_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_rej != NULL)
|
|
{
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Wait Time
|
|
con_rej->wait_time = liblte_bits_2_value(&msg_ptr, 4);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reestablishment Request
|
|
|
|
Description: Used to request the reestablishment of an RRC
|
|
connection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_request_msg(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *con_reest_req,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(con_reest_req != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
if(!ext)
|
|
{
|
|
// UE Identity
|
|
liblte_rrc_pack_c_rnti_ie((uint16)con_reest_req->ue_id.c_rnti, &msg_ptr);
|
|
liblte_rrc_pack_phys_cell_id_ie((uint16)con_reest_req->ue_id.phys_cell_id, &msg_ptr);
|
|
liblte_rrc_pack_short_mac_i_ie((uint16)con_reest_req->ue_id.short_mac_i, &msg_ptr);
|
|
|
|
// Reestablishment Cause
|
|
liblte_value_2_bits(con_reest_req->cause, &msg_ptr, 2);
|
|
|
|
// Spare
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_request_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *con_reest_req)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_reest_req != NULL)
|
|
{
|
|
// Extension Choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// UE Identity
|
|
liblte_rrc_unpack_c_rnti_ie(&msg_ptr, &con_reest_req->ue_id.c_rnti);
|
|
liblte_rrc_unpack_phys_cell_id_ie(&msg_ptr, &con_reest_req->ue_id.phys_cell_id);
|
|
liblte_rrc_unpack_short_mac_i_ie(&msg_ptr, &con_reest_req->ue_id.short_mac_i);
|
|
|
|
// Reestablishment Cause
|
|
con_reest_req->cause = (LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM)liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reestablishment Reject
|
|
|
|
Description: Used to indicate the rejection of an RRC connection
|
|
reestablishment request
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_reject_msg(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REJECT_STRUCT *con_reest_rej,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_reest_rej != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_reject_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REJECT_STRUCT *con_reest_rej)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_reest_rej != NULL)
|
|
{
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reestablishment Complete
|
|
|
|
Description: Used to confirm the successful completion of an RRC
|
|
connection reestablishment
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_complete_msg(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_COMPLETE_STRUCT *con_reest_complete,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_reest_complete != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_reest_complete->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_complete_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_REESTABLISHMENT_COMPLETE_STRUCT *con_reest_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_reest_complete != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&con_reest_complete->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reestablishment
|
|
|
|
Description: Used to resolve contention and to re-establish SRB1
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reestablishment_msg(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *con_reest,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_reest != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_reest->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 3);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Radio Resource Config Dedicated
|
|
liblte_rrc_pack_rr_config_dedicated_ie(&con_reest->rr_cnfg, &msg_ptr);
|
|
|
|
// Next Hop Chaining Count
|
|
liblte_rrc_pack_next_hop_chaining_count_ie(con_reest->next_hop_chaining_count, &msg_ptr);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reestablishment_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *con_reest)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_reest != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&con_reest->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Radio Resource Config Dedicated
|
|
liblte_rrc_unpack_rr_config_dedicated_ie(&msg_ptr, &con_reest->rr_cnfg);
|
|
|
|
// Next Hop Chaining Count
|
|
liblte_rrc_unpack_next_hop_chaining_count_ie(&msg_ptr, &con_reest->next_hop_chaining_count);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reconfiguration Complete
|
|
|
|
Description: Used to confirm the successful completion of an RRC
|
|
connection reconfiguration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *con_reconfig_complete,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(con_reconfig_complete != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_reconfig_complete->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *con_reconfig_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
con_reconfig_complete != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&con_reconfig_complete->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RRC Connection Reconfiguration
|
|
|
|
Description: Modifies an RRC connection
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rrc_connection_reconfiguration_msg(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *con_reconfig,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
|
|
if(con_reconfig != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(con_reconfig->rrc_transaction_id, &msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 3);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(con_reconfig->meas_cnfg_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(con_reconfig->mob_ctrl_info_present, &msg_ptr, 1);
|
|
if(0 == con_reconfig->N_ded_info_nas)
|
|
{
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(1, &msg_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(con_reconfig->rr_cnfg_ded_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(con_reconfig->sec_cnfg_ho_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Meas Config
|
|
if(con_reconfig->meas_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_meas_config_ie(&con_reconfig->meas_cnfg, &msg_ptr);
|
|
}
|
|
|
|
// Mobility Control Info
|
|
if(con_reconfig->mob_ctrl_info_present)
|
|
{
|
|
liblte_rrc_pack_mobility_control_info_ie(&con_reconfig->mob_ctrl_info, &msg_ptr);
|
|
}
|
|
|
|
// Dedicated Info NAS List
|
|
if(0 != con_reconfig->N_ded_info_nas)
|
|
{
|
|
liblte_value_2_bits(con_reconfig->N_ded_info_nas - 1, &msg_ptr, 4);
|
|
}
|
|
for(i=0; i<con_reconfig->N_ded_info_nas; i++)
|
|
{
|
|
liblte_rrc_pack_dedicated_info_nas_ie(&con_reconfig->ded_info_nas_list[i], &msg_ptr);
|
|
}
|
|
|
|
// Radio Resource Config Dedicated
|
|
if(con_reconfig->rr_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_pack_rr_config_dedicated_ie(&con_reconfig->rr_cnfg_ded, &msg_ptr);
|
|
}
|
|
|
|
// Security Config HO
|
|
if(con_reconfig->sec_cnfg_ho_present)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Handover Type
|
|
liblte_value_2_bits(con_reconfig->sec_cnfg_ho.ho_type, &msg_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_HANDOVER_TYPE_INTRA_LTE == con_reconfig->sec_cnfg_ho.ho_type)
|
|
{
|
|
// Optional indicator
|
|
liblte_value_2_bits(con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present, &msg_ptr, 1);
|
|
|
|
// Security Algorithm Config
|
|
if(con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present)
|
|
{
|
|
liblte_rrc_pack_security_algorithm_config_ie(&con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg, &msg_ptr);
|
|
}
|
|
|
|
// Key Change Indicator
|
|
liblte_value_2_bits(con_reconfig->sec_cnfg_ho.intra_lte.key_change_ind, &msg_ptr, 1);
|
|
|
|
// Next Hop Chaining Count
|
|
liblte_rrc_pack_next_hop_chaining_count_ie(con_reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count, &msg_ptr);
|
|
}else{
|
|
// Security Algorithm Config
|
|
liblte_rrc_pack_security_algorithm_config_ie(&con_reconfig->sec_cnfg_ho.inter_rat.sec_alg_cnfg, &msg_ptr);
|
|
|
|
// NAS Security Params To EUTRA
|
|
for(i=0; i<6; i++)
|
|
{
|
|
liblte_value_2_bits(con_reconfig->sec_cnfg_ho.inter_rat.nas_sec_param_to_eutra[i], &msg_ptr, 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rrc_connection_reconfiguration_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *con_reconfig)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
bool ded_info_nas_list_present;
|
|
|
|
if(msg != NULL &&
|
|
con_reconfig != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr, &con_reconfig->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
// Optional indicators
|
|
con_reconfig->meas_cnfg_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
con_reconfig->mob_ctrl_info_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
ded_info_nas_list_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
con_reconfig->rr_cnfg_ded_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
con_reconfig->sec_cnfg_ho_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Meas Config
|
|
if(con_reconfig->meas_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_meas_config_ie(&msg_ptr, &con_reconfig->meas_cnfg);
|
|
}
|
|
|
|
// Mobility Control Info
|
|
if(con_reconfig->mob_ctrl_info_present)
|
|
{
|
|
liblte_rrc_unpack_mobility_control_info_ie(&msg_ptr, &con_reconfig->mob_ctrl_info);
|
|
}
|
|
|
|
// Dedicated Info NAS List
|
|
if(ded_info_nas_list_present)
|
|
{
|
|
con_reconfig->N_ded_info_nas = liblte_bits_2_value(&msg_ptr, 4) + 1;
|
|
for(i=0; i<con_reconfig->N_ded_info_nas; i++)
|
|
{
|
|
liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr, &con_reconfig->ded_info_nas_list[i]);
|
|
}
|
|
}else{
|
|
con_reconfig->N_ded_info_nas = 0;
|
|
}
|
|
|
|
// Radio Resource Config Dedicated
|
|
if(con_reconfig->rr_cnfg_ded_present)
|
|
{
|
|
liblte_rrc_unpack_rr_config_dedicated_ie(&msg_ptr, &con_reconfig->rr_cnfg_ded);
|
|
}
|
|
|
|
// Security Config HO
|
|
if(con_reconfig->sec_cnfg_ho_present)
|
|
{
|
|
// Extension indicator
|
|
bool ext2 = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Handover Type
|
|
con_reconfig->sec_cnfg_ho.ho_type = (LIBLTE_RRC_HANDOVER_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_HANDOVER_TYPE_INTRA_LTE == con_reconfig->sec_cnfg_ho.ho_type)
|
|
{
|
|
// Optional indicator
|
|
con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Security Algorithm Config
|
|
if(con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg_present)
|
|
{
|
|
liblte_rrc_unpack_security_algorithm_config_ie(&msg_ptr, &con_reconfig->sec_cnfg_ho.intra_lte.sec_alg_cnfg);
|
|
}
|
|
|
|
// Key Change Indicator
|
|
con_reconfig->sec_cnfg_ho.intra_lte.key_change_ind = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Next Hop Chaining Count
|
|
liblte_rrc_unpack_next_hop_chaining_count_ie(&msg_ptr, &con_reconfig->sec_cnfg_ho.intra_lte.next_hop_chaining_count);
|
|
}else{
|
|
// Security Algorithm Config
|
|
liblte_rrc_unpack_security_algorithm_config_ie(&msg_ptr, &con_reconfig->sec_cnfg_ho.inter_rat.sec_alg_cnfg);
|
|
|
|
// NAS Security Params To EUTRA
|
|
for(i=0; i<6; i++)
|
|
{
|
|
con_reconfig->sec_cnfg_ho.inter_rat.nas_sec_param_to_eutra[i] = liblte_bits_2_value(&msg_ptr, 8);
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext2, __func__, &msg_ptr);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RN Reconfiguration Complete
|
|
|
|
Description: Used to confirm the successful completion of an RN
|
|
reconfiguration
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_rn_reconfiguration_complete_msg(LIBLTE_RRC_RN_RECONFIGURATION_COMPLETE_STRUCT *rn_reconfig_complete,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(rn_reconfig_complete != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(rn_reconfig_complete->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicators
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_rn_reconfiguration_complete_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_RN_RECONFIGURATION_COMPLETE_STRUCT *rn_reconfig_complete)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
rn_reconfig_complete != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&rn_reconfig_complete->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicators
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: RN Reconfiguration
|
|
|
|
Description: Modifies the RRC connection between the RN and the
|
|
E-UTRAN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: Proximity Indication
|
|
|
|
Description: Used to indicate that the UE is entering or leaving
|
|
the proximity of one or more cells whose CSG IDs are
|
|
in the UEs CSG whitelist
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_proximity_indication_msg(LIBLTE_RRC_PROXIMITY_INDICATION_STRUCT *proximity_ind,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(proximity_ind != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Proximity indication type
|
|
liblte_value_2_bits(proximity_ind->type, &msg_ptr, 1);
|
|
|
|
// Carrier frequency type extension indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Carrier frequency choice
|
|
liblte_value_2_bits(proximity_ind->carrier_freq_type, &msg_ptr, 1);
|
|
|
|
// Carrier frequency
|
|
if(LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_EUTRA == proximity_ind->carrier_freq_type)
|
|
{
|
|
liblte_rrc_pack_arfcn_value_eutra_ie(proximity_ind->carrier_freq,
|
|
&msg_ptr);
|
|
}else{
|
|
liblte_rrc_pack_arfcn_value_utra_ie(proximity_ind->carrier_freq,
|
|
&msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_proximity_indication_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_PROXIMITY_INDICATION_STRUCT *proximity_ind)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
proximity_ind != NULL)
|
|
{
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Proximity indication type
|
|
proximity_ind->type = (LIBLTE_RRC_PROXIMITY_INDICATION_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Carrier frequency type extension indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Carrier frequency type
|
|
proximity_ind->carrier_freq_type = (LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Carrier frequency
|
|
if(LIBLTE_RRC_PROXIMITY_INDICATION_CARRIER_FREQ_TYPE_EUTRA == proximity_ind->carrier_freq)
|
|
{
|
|
liblte_rrc_unpack_arfcn_value_eutra_ie(&msg_ptr,
|
|
&proximity_ind->carrier_freq);
|
|
}else{
|
|
liblte_rrc_unpack_arfcn_value_utra_ie(&msg_ptr,
|
|
&proximity_ind->carrier_freq);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Paging
|
|
|
|
Description: Used for the notification of one or more UEs
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_paging_msg(LIBLTE_RRC_PAGING_STRUCT *page,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
uint32 j;
|
|
|
|
if(page != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Optional indicators
|
|
if(page->paging_record_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(1, &msg_ptr, 1);
|
|
}else{
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
}
|
|
liblte_value_2_bits(page->system_info_modification_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(page->etws_indication_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(page->non_crit_ext_present, &msg_ptr, 1);
|
|
|
|
if(page->paging_record_list_size != 0)
|
|
{
|
|
liblte_value_2_bits(page->paging_record_list_size - 1, &msg_ptr, 4);
|
|
for(i=0; i<page->paging_record_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Paging UE identity
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
liblte_value_2_bits(page->paging_record_list[i].ue_identity.ue_identity_type, &msg_ptr, 1);
|
|
if(LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_S_TMSI == page->paging_record_list[i].ue_identity.ue_identity_type)
|
|
{
|
|
liblte_rrc_pack_s_tmsi_ie(&page->paging_record_list[i].ue_identity.s_tmsi,
|
|
&msg_ptr);
|
|
}else{
|
|
liblte_value_2_bits(page->paging_record_list[i].ue_identity.imsi_size - 6, &msg_ptr, 4);
|
|
for(j=0; j<page->paging_record_list[i].ue_identity.imsi_size; j++)
|
|
{
|
|
liblte_value_2_bits(page->paging_record_list[i].ue_identity.imsi[j], &msg_ptr, 4);
|
|
}
|
|
}
|
|
}
|
|
|
|
liblte_value_2_bits(page->paging_record_list[i].cn_domain, &msg_ptr, 1);
|
|
}
|
|
}
|
|
|
|
if(page->system_info_modification_present)
|
|
{
|
|
liblte_value_2_bits(page->system_info_modification, &msg_ptr, 1);
|
|
}
|
|
|
|
if(page->etws_indication_present)
|
|
{
|
|
liblte_value_2_bits(page->etws_indication, &msg_ptr, 1);
|
|
}
|
|
|
|
if(page->non_crit_ext_present)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(page->non_crit_ext.late_non_crit_ext_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(page->non_crit_ext.non_crit_ext_present, &msg_ptr, 1);
|
|
|
|
if(page->non_crit_ext.late_non_crit_ext_present)
|
|
{
|
|
// FIXME
|
|
}
|
|
|
|
if(page->non_crit_ext.non_crit_ext_present)
|
|
{
|
|
// Optional indicators
|
|
liblte_value_2_bits(page->non_crit_ext.non_crit_ext.cmas_ind_present, &msg_ptr, 1);
|
|
liblte_value_2_bits(page->non_crit_ext.non_crit_ext.non_crit_ext_present, &msg_ptr, 1);
|
|
|
|
if(page->non_crit_ext.non_crit_ext.cmas_ind_present)
|
|
{
|
|
liblte_value_2_bits(page->non_crit_ext.non_crit_ext.cmas_ind_r9, &msg_ptr, 1);
|
|
}
|
|
|
|
if(page->non_crit_ext.non_crit_ext.non_crit_ext_present)
|
|
{
|
|
// FIXME
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_PAGING_STRUCT *page)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 i;
|
|
uint32 j;
|
|
uint8 paging_record_list_present;
|
|
|
|
if(msg != NULL &&
|
|
page != NULL)
|
|
{
|
|
// Optional indicators
|
|
paging_record_list_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
page->system_info_modification_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
page->etws_indication_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
page->non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
if(paging_record_list_present)
|
|
{
|
|
page->paging_record_list_size = liblte_bits_2_value(&msg_ptr, 4) + 1;
|
|
for(i=0; i<page->paging_record_list_size; i++)
|
|
{
|
|
// Extension indicator
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Paging UE identity
|
|
{
|
|
// Extension indicator
|
|
bool ext2 = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
page->paging_record_list[i].ue_identity.ue_identity_type = (LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
if(LIBLTE_RRC_PAGING_UE_IDENTITY_TYPE_S_TMSI == page->paging_record_list[i].ue_identity.ue_identity_type)
|
|
{
|
|
liblte_rrc_unpack_s_tmsi_ie(&msg_ptr,
|
|
&page->paging_record_list[i].ue_identity.s_tmsi);
|
|
}else{
|
|
page->paging_record_list[i].ue_identity.imsi_size = liblte_bits_2_value(&msg_ptr, 4) + 6;
|
|
for(j=0; j<page->paging_record_list[i].ue_identity.imsi_size; j++)
|
|
{
|
|
page->paging_record_list[i].ue_identity.imsi[j] = liblte_bits_2_value(&msg_ptr, 4);
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext2, __func__, &msg_ptr);
|
|
}
|
|
|
|
page->paging_record_list[i].cn_domain = (LIBLTE_RRC_CN_DOMAIN_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
}
|
|
}
|
|
|
|
if(page->system_info_modification_present)
|
|
{
|
|
page->system_info_modification = (LIBLTE_RRC_SYSTEM_INFO_MODIFICATION_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
}
|
|
|
|
if(page->etws_indication_present)
|
|
{
|
|
page->etws_indication = (LIBLTE_RRC_ETWS_INDICATION_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
}
|
|
|
|
if(page->non_crit_ext_present)
|
|
{
|
|
// Optional indicators
|
|
page->non_crit_ext.late_non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
page->non_crit_ext.non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
if(page->non_crit_ext.late_non_crit_ext_present)
|
|
{
|
|
// FIXME
|
|
printf("Warning late non-crit-extension not handled in paging message\n");
|
|
}
|
|
|
|
if(page->non_crit_ext.non_crit_ext_present)
|
|
{
|
|
// Optional indicators
|
|
page->non_crit_ext.non_crit_ext.cmas_ind_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
page->non_crit_ext.non_crit_ext.non_crit_ext_present = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
if(page->non_crit_ext.non_crit_ext.cmas_ind_present)
|
|
{
|
|
page->non_crit_ext.non_crit_ext.cmas_ind_r9 = (LIBLTE_RRC_CMAS_INDICATION_R9_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
}
|
|
|
|
if(page->non_crit_ext.non_crit_ext.non_crit_ext_present)
|
|
{
|
|
// FIXME
|
|
printf("Warning non-crit-extension not handled in paging message\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Mobility From EUTRA Command
|
|
|
|
Description: Used to command handover or a cell change from E-UTRA
|
|
to another RAT, or enhanced CS fallback to CDMA2000
|
|
1xRTT
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: Measurement Report
|
|
|
|
Description: Used for the indication of measurement results
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: MBSFN Area Configuration
|
|
|
|
Description: Contains the MBMS control information applicable for
|
|
an MBSFN area
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: Master Information Block
|
|
|
|
Description: Includes the system information transmitted on BCH
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// Inlined with BCCH BCH Message
|
|
|
|
/*********************************************************************
|
|
Message Name: Logged Measurements Configuration
|
|
|
|
Description: Used by E-UTRAN to configure the UE to perform
|
|
logging of measurement results while in RRC_IDLE
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: Handover From EUTRA Preparation Request (CDMA2000)
|
|
|
|
Description: Used to trigger the handover preparation procedure
|
|
with a CDMA2000 RAT
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: DL Information Transfer
|
|
|
|
Description: Used for the downlink transfer of dedicated NAS
|
|
information
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_information_transfer_msg(LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *dl_info_transfer,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(dl_info_transfer != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_pack_rrc_transaction_identifier_ie(dl_info_transfer->rrc_transaction_id,
|
|
&msg_ptr);
|
|
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_value_2_bits(0, &msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Dedicated info type choice
|
|
liblte_value_2_bits(dl_info_transfer->dedicated_info_type, &msg_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_NAS == dl_info_transfer->dedicated_info_type)
|
|
{
|
|
liblte_rrc_pack_dedicated_info_nas_ie(&dl_info_transfer->dedicated_info,
|
|
&msg_ptr);
|
|
}else{
|
|
liblte_rrc_pack_dedicated_info_cdma2000_ie(&dl_info_transfer->dedicated_info,
|
|
&msg_ptr);
|
|
}
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_information_transfer_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *dl_info_transfer)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
dl_info_transfer != NULL)
|
|
{
|
|
// RRC Transaction ID
|
|
liblte_rrc_unpack_rrc_transaction_identifier_ie(&msg_ptr,
|
|
&dl_info_transfer->rrc_transaction_id);
|
|
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// C1 choice
|
|
liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
// Dedicated info type choice
|
|
dl_info_transfer->dedicated_info_type = (LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_DL_INFORMATION_TRANSFER_TYPE_NAS == dl_info_transfer->dedicated_info_type)
|
|
{
|
|
liblte_rrc_unpack_dedicated_info_nas_ie(&msg_ptr,
|
|
&dl_info_transfer->dedicated_info);
|
|
}else{
|
|
liblte_rrc_unpack_dedicated_info_cdma2000_ie(&msg_ptr,
|
|
&dl_info_transfer->dedicated_info);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: CSFB Parameters Response CDMA2000
|
|
|
|
Description: Used to provide the CDMA2000 1xRTT parameters to the
|
|
UE so the UE can register with the CDMA2000 1xRTT
|
|
network to support CSFB to CDMA2000 1xRTT
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: CSFB Parameters Request CDMA2000
|
|
|
|
Description: Used by the UE to obtain the CDMA2000 1xRTT
|
|
parameters from the network
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_csfb_parameters_request_cdma2000_msg(LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *csfb_params_req_cdma2000,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(csfb_params_req_cdma2000 != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *csfb_params_req_cdma2000)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
csfb_params_req_cdma2000 != NULL)
|
|
{
|
|
// Extension choice
|
|
bool ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Optional indicator
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: Counter Check Response
|
|
|
|
Description: Used by the UE to respond to a Counter Check message
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: Counter Check
|
|
|
|
Description: Used by the E-UTRAN to indicate the current COUNT MSB
|
|
values associated to each DRB and to request the UE
|
|
to compare these to its COUNT MSB values and to
|
|
report the comparison results to E-UTRAN
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.2
|
|
*********************************************************************/
|
|
// FIXME
|
|
|
|
/*********************************************************************
|
|
Message Name: BCCH BCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the E-UTRAN to the UE via BCH on the BCCH
|
|
logical channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Sections 6.2.1 and 6.2.2
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_bcch_bch_msg(LIBLTE_RRC_MIB_STRUCT *mib,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(mib != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// DL Bandwidth
|
|
liblte_value_2_bits(mib->dl_bw, &msg_ptr, 3);
|
|
|
|
// PHICH Config
|
|
liblte_rrc_pack_phich_config_ie(&mib->phich_config, &msg_ptr);
|
|
|
|
// SFN/4
|
|
liblte_value_2_bits(mib->sfn_div_4, &msg_ptr, 8);
|
|
|
|
// Spare
|
|
liblte_value_2_bits(0, &msg_ptr, 10);
|
|
|
|
// Fill in the number of bits used
|
|
msg->N_bits = msg_ptr - msg->msg;
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_bcch_bch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_MIB_STRUCT *mib)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
|
|
if(msg != NULL &&
|
|
mib != NULL)
|
|
{
|
|
// DL Bandwidth
|
|
mib->dl_bw = (LIBLTE_RRC_DL_BANDWIDTH_ENUM)liblte_bits_2_value(&msg_ptr, 3);
|
|
|
|
// PHICH Config
|
|
liblte_rrc_unpack_phich_config_ie(&msg_ptr, &mib->phich_config);
|
|
|
|
// SFN/4
|
|
mib->sfn_div_4 = liblte_bits_2_value(&msg_ptr, 8);
|
|
|
|
err = LIBLTE_SUCCESS;
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: BCCH DLSCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the E-UTRAN to the UE via DLSCH on the BCCH
|
|
logical channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_bcch_dlsch_msg(LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *bcch_dlsch_msg,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(bcch_dlsch_msg != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 == bcch_dlsch_msg->sibs[0].sib_type)
|
|
{
|
|
// SIB1 Choice
|
|
liblte_value_2_bits(1, &msg_ptr, 1);
|
|
|
|
err = liblte_rrc_pack_sys_info_block_type_1_msg((LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *)&bcch_dlsch_msg->sibs[0].sib,
|
|
&global_msg);
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 2))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 2;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}else{
|
|
// SIB1 Choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
err = liblte_rrc_pack_sys_info_msg(bcch_dlsch_msg,
|
|
&global_msg);
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 2))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 2;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_bcch_dlsch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_BCCH_DLSCH_MSG_STRUCT *bcch_dlsch_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 N_bits_used;
|
|
uint8 ext;
|
|
|
|
if(msg != NULL &&
|
|
bcch_dlsch_msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// SIB1 Choice
|
|
if(true == liblte_bits_2_value(&msg_ptr, 1))
|
|
{
|
|
bcch_dlsch_msg->N_sibs = 1;
|
|
bcch_dlsch_msg->sibs[0].sib_type = LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1;
|
|
if((msg->N_bits-(msg_ptr-msg->msg)) <= (LIBLTE_MAX_MSG_SIZE_BITS - 2))
|
|
{
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
global_msg.N_bits = msg->N_bits-(msg_ptr-msg->msg);
|
|
err = liblte_rrc_unpack_sys_info_block_type_1_msg(&global_msg,
|
|
(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT *)&bcch_dlsch_msg->sibs[0].sib,
|
|
&N_bits_used);
|
|
msg_ptr += N_bits_used;
|
|
}
|
|
}else{
|
|
if((msg->N_bits-(msg_ptr-msg->msg)) <= (LIBLTE_MAX_MSG_SIZE_BITS - 2))
|
|
{
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
err = liblte_rrc_unpack_sys_info_msg(&global_msg,
|
|
bcch_dlsch_msg);
|
|
}
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: PCCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the E-UTRAN to the UE on the PCCH logical
|
|
channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_pcch_msg(LIBLTE_RRC_PCCH_MSG_STRUCT *pcch_msg,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(pcch_msg != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Paging choice
|
|
liblte_value_2_bits(0, &msg_ptr, 1);
|
|
|
|
err = liblte_rrc_pack_paging_msg(pcch_msg,
|
|
&global_msg);
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 1))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 1;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_pcch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_PCCH_MSG_STRUCT *pcch_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint32 N_bits_used;
|
|
|
|
if(msg != NULL &&
|
|
pcch_msg != NULL)
|
|
{
|
|
// Paging choice
|
|
liblte_rrc_warning_not_handled(liblte_bits_2_value(&msg_ptr, 1), __func__);;
|
|
|
|
if((msg->N_bits-(msg_ptr-msg->msg)) <= (LIBLTE_MAX_MSG_SIZE_BITS - 1))
|
|
{
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
err = liblte_rrc_unpack_paging_msg(&global_msg,
|
|
pcch_msg);
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: DL CCCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the E-UTRAN to the UE on the downlink CCCH
|
|
logical channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_ccch_msg(LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ccch_msg,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(dl_ccch_msg != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
liblte_value_2_bits(dl_ccch_msg->msg_type, &msg_ptr, 2);
|
|
|
|
if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST == dl_ccch_msg->msg_type)
|
|
{
|
|
err = liblte_rrc_pack_rrc_connection_reestablishment_msg((LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *)&dl_ccch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ == dl_ccch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_reestablishment_reject_msg((LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REJECT_STRUCT *)&dl_ccch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ == dl_ccch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_reject_msg((LIBLTE_RRC_CONNECTION_REJECT_STRUCT *)&dl_ccch_msg->msg,
|
|
&global_msg);
|
|
}else{ // LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP == dl_ccch_msg->msg_type
|
|
err = liblte_rrc_pack_rrc_connection_setup_msg((LIBLTE_RRC_CONNECTION_SETUP_STRUCT *)&dl_ccch_msg->msg,
|
|
&global_msg);
|
|
}
|
|
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 3))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 3;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_ccch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_DL_CCCH_MSG_STRUCT *dl_ccch_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext;
|
|
|
|
if(msg != NULL &&
|
|
dl_ccch_msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
dl_ccch_msg->msg_type = (LIBLTE_RRC_DL_CCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 2);
|
|
|
|
// Message
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
global_msg.N_bits = msg->N_bits-(msg_ptr-msg->msg);
|
|
if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST == dl_ccch_msg->msg_type)
|
|
{
|
|
err = liblte_rrc_unpack_rrc_connection_reestablishment_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *)&dl_ccch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REEST_REJ == dl_ccch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_reestablishment_reject_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REJECT_STRUCT *)&dl_ccch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ == dl_ccch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_reject_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_REJECT_STRUCT *)&dl_ccch_msg->msg);
|
|
}else{ // LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP == dl_ccch_msg->msg_type
|
|
err = liblte_rrc_unpack_rrc_connection_setup_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *)&dl_ccch_msg->msg);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: DL DCCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the E-UTRAN to the UE on the downlink DCCH
|
|
logical channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_dl_dcch_msg(LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(dl_dcch_msg != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
liblte_value_2_bits(dl_dcch_msg->msg_type, &msg_ptr, 4);
|
|
|
|
// Message
|
|
if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_CSFB_PARAMS_RESP_CDMA2000 == dl_dcch_msg->msg_type)
|
|
{
|
|
printf("NOT HANDLING CSFB PARAMETERS RESPONSE CDMA2000\n");
|
|
// err = liblte_rrc_pack_csfb_parameters_response_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT *)&dl_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_dl_information_transfer_msg((LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *)&dl_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_HANDOVER_FROM_EUTRA_PREP_REQ == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING HANDOVER FROM EUTRA PREPARATION REQUEST\n");
|
|
// err = liblte_rrc_pack_handover_from_eutra_preparation_request_msg((LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT *)&dl_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_MOBILITY_FROM_EUTRA_COMMAND == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING MOBILITY FROM EUTRA COMMAND\n");
|
|
// err = liblte_rrc_pack_mobility_from_eutra_command_msg((LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT *)&dl_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_reconfiguration_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RELEASE == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_release_msg((LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *)&dl_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_SECURITY_MODE_COMMAND == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_security_mode_command_msg((LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *)&dl_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_ue_capability_enquiry_msg((LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *)&dl_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_COUNTER_CHECK == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING COUNTER CHECK\n");
|
|
// err = liblte_rrc_pack_counter_check_msg((LIBLTE_RRC_COUNTER_CHECK_STRUCT *)&dl_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_INFO_REQ == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_ue_information_request_msg((LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *)&dl_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_LOGGED_MEASUREMENTS_CONFIG == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING LOGGED MEASUREMENTS CONFIGURATION\n");
|
|
// err = liblte_rrc_pack_logged_measurements_configuration_msg((LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT *)&dl_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else{ // LIBLTE_RRC_DL_DCCH_MSG_TYPE_RN_RECONFIG == dl_dcch_msg->msg_type
|
|
printf("NOT HANDLING RN RECONFIGURATION\n");
|
|
// err = liblte_rrc_pack_rn_reconfiguration_msg((LIBLTE_RRC_RN_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg,
|
|
// &global_msg);
|
|
}
|
|
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 5))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 5;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_dl_dcch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_DL_DCCH_MSG_STRUCT *dl_dcch_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext;
|
|
|
|
if(msg != NULL &&
|
|
dl_dcch_msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
dl_dcch_msg->msg_type = (LIBLTE_RRC_DL_DCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4);
|
|
|
|
// Message
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
global_msg.N_bits = msg->N_bits-(msg_ptr-msg->msg);
|
|
if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_CSFB_PARAMS_RESP_CDMA2000 == dl_dcch_msg->msg_type)
|
|
{
|
|
printf("NOT HANDLING CSFB PARAMETERS RESPONSE CDMA2000\n");
|
|
// err = liblte_rrc_unpack_csfb_parameters_response_cdma2000_msg(&global_msg,
|
|
// (LIBLTE_RRC_CSFB_PARAMETERS_RESPONSE_CDMA2000_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_DL_INFO_TRANSFER == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_dl_information_transfer_msg(&global_msg,
|
|
(LIBLTE_RRC_DL_INFORMATION_TRANSFER_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_HANDOVER_FROM_EUTRA_PREP_REQ == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING HANDOVER FROM EUTRA PREPARATION REQUEST\n");
|
|
// err = liblte_rrc_unpack_handover_from_eutra_preparation_request_msg(&global_msg,
|
|
// (LIBLTE_RRC_HANDOVER_FROM_EUTRA_PREPARATION_REQUEST_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_MOBILITY_FROM_EUTRA_COMMAND == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING MOBILITY FROM EUTRA COMMAND\n");
|
|
// err = liblte_rrc_unpack_mobility_from_eutra_command_msg(&global_msg,
|
|
// (LIBLTE_RRC_MOBILITY_FROM_EUTRA_COMMAND_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RECONFIG == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_reconfiguration_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_RRC_CON_RELEASE == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_release_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_RELEASE_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_SECURITY_MODE_COMMAND == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_security_mode_command_msg(&global_msg,
|
|
(LIBLTE_RRC_SECURITY_MODE_COMMAND_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_CAPABILITY_ENQUIRY == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_ue_capability_enquiry_msg(&global_msg,
|
|
(LIBLTE_RRC_UE_CAPABILITY_ENQUIRY_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_COUNTER_CHECK == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING COUNTER CHECK\n");
|
|
// err = liblte_rrc_unpack_counter_check_msg(&global_msg,
|
|
// (LIBLTE_RRC_COUNTER_CHECK_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_UE_INFO_REQ == dl_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_ue_information_request_msg(&global_msg,
|
|
(LIBLTE_RRC_UE_INFORMATION_REQUEST_STRUCT *)&dl_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_DL_DCCH_MSG_TYPE_LOGGED_MEASUREMENTS_CONFIG == dl_dcch_msg->msg_type){
|
|
printf("NOT HANDLING LOGGED MEASUREMENTS CONFIGURATION\n");
|
|
// err = liblte_rrc_unpack_logged_measurements_configuration_msg(&global_msg,
|
|
// (LIBLTE_RRC_LOGGED_MEASUREMENTS_CONFIGURATION_STRUCT *)&dl_dcch_msg->msg);
|
|
}else{ // LIBLTE_RRC_DL_DCCH_MSG_TYPE_RN_RECONFIG == dl_dcch_msg->msg_type
|
|
printf("NOT HANDLING RN RECONFIGURATION\n");
|
|
// err = liblte_rrc_unpack_rn_reconfiguration_msg(&global_msg,
|
|
// (LIBLTE_RRC_RN_RECONFIGURATION_STRUCT *)&dl_dcch_msg->msg);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: UL CCCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the UE to the E-UTRAN on the uplink CCCH
|
|
logical channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_ccch_msg(LIBLTE_RRC_UL_CCCH_MSG_STRUCT *ul_ccch_msg,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(ul_ccch_msg != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
liblte_value_2_bits(ul_ccch_msg->msg_type, &msg_ptr, 1);
|
|
|
|
if(LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REEST_REQ == ul_ccch_msg->msg_type)
|
|
{
|
|
err = liblte_rrc_pack_rrc_connection_reestablishment_request_msg((LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *)&ul_ccch_msg->msg,
|
|
&global_msg);
|
|
}else{ // LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ == ul_ccch_msg->msg_type
|
|
err = liblte_rrc_pack_rrc_connection_request_msg((LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *)&ul_ccch_msg->msg,
|
|
&global_msg);
|
|
}
|
|
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 2))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 2;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_ccch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_UL_CCCH_MSG_STRUCT *ul_ccch_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext;
|
|
|
|
if(msg != NULL &&
|
|
ul_ccch_msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
ul_ccch_msg->msg_type = (LIBLTE_RRC_UL_CCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Message
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
global_msg.N_bits = msg->N_bits-(msg_ptr-msg->msg);
|
|
if(LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REEST_REQ == ul_ccch_msg->msg_type)
|
|
{
|
|
err = liblte_rrc_unpack_rrc_connection_reestablishment_request_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_REQUEST_STRUCT *)&ul_ccch_msg->msg);
|
|
}else{ // LIBLTE_RRC_UL_CCCH_MSG_TYPE_RRC_CON_REQ == ul_ccch_msg->msg_type
|
|
err = liblte_rrc_unpack_rrc_connection_request_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_REQUEST_STRUCT *)&ul_ccch_msg->msg);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
|
|
/*********************************************************************
|
|
Message Name: UL DCCH Message
|
|
|
|
Description: Contains the set of RRC messages that may be sent
|
|
from the UE to the E-UTRAN on the uplink DCCH
|
|
logical channel
|
|
|
|
Document Reference: 36.331 v10.0.0 Section 6.2.1
|
|
*********************************************************************/
|
|
LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_dcch_msg,
|
|
LIBLTE_BIT_MSG_STRUCT *msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext = false;
|
|
|
|
if(ul_dcch_msg != NULL &&
|
|
msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
liblte_value_2_bits(ext, &msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
liblte_value_2_bits(ul_dcch_msg->msg_type, &msg_ptr, 4);
|
|
|
|
// Message
|
|
if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_CSFB_PARAMS_REQ_CDMA2000 == ul_dcch_msg->msg_type)
|
|
{
|
|
err = liblte_rrc_pack_csfb_parameters_request_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING MEASUREMENT REPORT\n");
|
|
// err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_REEST_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_reestablishment_complete_msg((LIBLTE_RRC_CONNECTION_REESTABLISHMENT_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_SETUP_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_rrc_connection_setup_complete_msg((LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_security_mode_complete_msg((LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_FAILURE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_security_mode_failure_msg((LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_CAPABILITY_INFO == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_ue_capability_information_msg((LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_HANDOVER_PREP_TRANSFER == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING UL HANDOVER PREPARATION TRANSFER\n");
|
|
// err = liblte_rrc_pack_ul_handover_preparation_transfer_msg((LIBLTE_RRC_UL_HANDOVER_PREPARATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_INFO_TRANSFER == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_ul_information_transfer_msg((LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_COUNTER_CHECK_RESP == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING COUNTER CHECK RESPONSE\n");
|
|
// err = liblte_rrc_pack_counter_check_response_msg((LIBLTE_RRC_COUNTER_CHECK_RESPONSE_STRUCT *)&ul_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_INFO_RESP == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING UE INFORMATION RESPONSE\n");
|
|
// err = liblte_rrc_pack_ue_information_response_msg((LIBLTE_RRC_UE_INFORMATION_RESPONSE_STRUCT *)&ul_dcch_msg->msg,
|
|
// &global_msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_PROXIMITY_IND == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_pack_proximity_indication_msg((LIBLTE_RRC_PROXIMITY_INDICATION_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}else{ // LIBLTE_RRC_UL_DCCH_MSG_TYPE_RN_RECONFIG_COMPLETE == ul_dcch_msg->msg_type
|
|
err = liblte_rrc_pack_rn_reconfiguration_complete_msg((LIBLTE_RRC_RN_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg,
|
|
&global_msg);
|
|
}
|
|
|
|
if(global_msg.N_bits <= (LIBLTE_MAX_MSG_SIZE_BITS - 5))
|
|
{
|
|
memcpy(msg_ptr, global_msg.msg, global_msg.N_bits);
|
|
msg->N_bits = global_msg.N_bits + 5;
|
|
}else{
|
|
msg->N_bits = 0;
|
|
err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
}
|
|
}
|
|
|
|
return(err);
|
|
}
|
|
LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *msg,
|
|
LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_dcch_msg)
|
|
{
|
|
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
|
uint8 *msg_ptr = msg->msg;
|
|
uint8 ext;
|
|
|
|
if(msg != NULL &&
|
|
ul_dcch_msg != NULL)
|
|
{
|
|
// Extension indicator
|
|
ext = liblte_bits_2_value(&msg_ptr, 1);
|
|
|
|
// Message type choice
|
|
ul_dcch_msg->msg_type = (LIBLTE_RRC_UL_DCCH_MSG_TYPE_ENUM)liblte_bits_2_value(&msg_ptr, 4);
|
|
|
|
// Message
|
|
memcpy(global_msg.msg, msg_ptr, msg->N_bits-(msg_ptr-msg->msg));
|
|
global_msg.N_bits = msg->N_bits-(msg_ptr-msg->msg);
|
|
if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_CSFB_PARAMS_REQ_CDMA2000 == ul_dcch_msg->msg_type)
|
|
{
|
|
err = liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(&global_msg,
|
|
(LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING MEASUREMENT REPORT\n");
|
|
// err = liblte_rrc_unpack_measurement_report_msg(&global_msg,
|
|
// (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_REEST_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_reestablishment_complete_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_COMPLETE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_SETUP_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_rrc_connection_setup_complete_msg(&global_msg,
|
|
(LIBLTE_RRC_CONNECTION_SETUP_COMPLETE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_COMPLETE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_security_mode_complete_msg(&global_msg,
|
|
(LIBLTE_RRC_SECURITY_MODE_COMPLETE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_SECURITY_MODE_FAILURE == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_security_mode_failure_msg(&global_msg,
|
|
(LIBLTE_RRC_SECURITY_MODE_FAILURE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_CAPABILITY_INFO == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING UE CAPABILITY INFO\n");
|
|
// err = liblte_rrc_unpack_ue_capability_information_msg(&global_msg,
|
|
// (LIBLTE_RRC_UE_CAPABILITY_INFORMATION_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_HANDOVER_PREP_TRANSFER == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING UL HANDOVER PREPARATION TRANSFER\n");
|
|
// err = liblte_rrc_unpack_ul_handover_preparation_transfer_msg(&global_msg,
|
|
// (LIBLTE_RRC_UL_HANDOVER_PREPARATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UL_INFO_TRANSFER == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_ul_information_transfer_msg(&global_msg,
|
|
(LIBLTE_RRC_UL_INFORMATION_TRANSFER_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_COUNTER_CHECK_RESP == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING COUNTER CHECK RESPONSE\n");
|
|
// err = liblte_rrc_unpack_counter_check_response_msg(&global_msg,
|
|
// (LIBLTE_RRC_COUNTER_CHECK_RESPONSE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_UE_INFO_RESP == ul_dcch_msg->msg_type){
|
|
printf("NOT HANDLING UE INFORMATION RESPONSE\n");
|
|
// err = liblte_rrc_unpack_ue_information_response_msg(&global_msg,
|
|
// (LIBLTE_RRC_UE_INFORMATION_RESPONSE_STRUCT *)&ul_dcch_msg->msg);
|
|
}else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_PROXIMITY_IND == ul_dcch_msg->msg_type){
|
|
err = liblte_rrc_unpack_proximity_indication_msg(&global_msg,
|
|
(LIBLTE_RRC_PROXIMITY_INDICATION_STRUCT *)&ul_dcch_msg->msg);
|
|
}else{ // LIBLTE_RRC_UL_DCCH_MSG_TYPE_RN_RECONFIG_COMPLETE == ul_dcch_msg->msg_type
|
|
err = liblte_rrc_unpack_rn_reconfiguration_complete_msg(&global_msg,
|
|
(LIBLTE_RRC_RN_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg);
|
|
}
|
|
|
|
liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr);
|
|
|
|
}
|
|
|
|
return(err);
|
|
}
|