Bootstrap

SIM卡中IMSI中的MNC是2位还是3位怎么确定?

问题的提出

有前同事咨询我一个问题:

自己写到卡里的IMSI,读出来的PLMN都是6位的;而从正常的联通卡等都出来的PLMN是5位的;

PLMN = MCC + MNC;

MCC是固定3位的;

MNC有2位的,也有3位的;

MNC是几位的如何确定呢?

这个问题困扰了我这位前同事几年了,我也没遇到过,研究下。

基本概念

IMSI:International Mobile Subscriber Identity,国际移动用户识别码。

IMSI由一串十进制数字组成,最大长度为15位。实际使用的IMSI的长度绝大部分都是15位,短于15位的例子少见,例如,南非MTN有一些仍在网络中使用的较旧的IMSI为14位数字。IMSI由移动国家代码(MCC,Mobile Country Code)、移动网络代码(MNC,Mobile Network Code)和移动订户识别代码(MSIN,Mobile subscription identification number)依次连接而成。MCC长度为3位,MNC长度由MCC的值决定,可以是2位(欧洲标准)或3位数字(北美标准),MSIN的值由运营商自行分配。

IMSI的格式由国际电信联盟(ITU)的E.212标准定义。

以上定义摘自百度百科。

IMSI在SIM卡中的存储格式见3GPP 31.102 

4.2.2 EFIMSI (IMSI)

If service n°130 is "available", this file shall not be available.

This EF contains the International Mobile Subscriber Identity (IMSI).

Identifier: '6F07'

Structure: transparent

Optional

SFI: '07'

File size: 9 bytes

Update activity: low

Access Conditions:

            READ                                         PIN

            UPDATE                                    ADM

            DEACTIVATE                            ADM

            ACTIVATE                                 ADM

Bytes

Description

M/O

Length

1

Length of IMSI

M

1 byte

2 to 9

IMSI

M

8 bytes

相关代码

查看代码,相关的函数有:

mmcp\mmode\cm\src\sys.c

/* ==========================================================================
   FUNCTION:      SYS_GET_NUM_OF_MNC_DIGITS

   DESCRIPTION:
     This function returns length of MNC in the IMSI which is store in 4th
     byte of EF-AD.

   DEPENDENCIES:
     None

   LIMITATIONS:
     None

   RETURN VALUE:
     TRUE:  Successful retrieval of number of mnc digits
     FALSE: Null input pointer

   SIDE EFFECTS:
     None
==========================================================================*/
boolean sys_get_num_of_mnc_digits(
  mmgsdi_data_type *imsi_ptr,
  mmgsdi_data_type *ad_ptr,
  uint8             *num_mnc_digits_ptr
)
{
  size_t i                     = 0;
  size_t mcc_value             = 0;
  uint16 mcc_pcs1900_na_list[] = {302, 310, 311, 312, 313,
                                  314, 315, 316, 334, 348
                                 };


  if(imsi_ptr == NULL || imsi_ptr->data_ptr == NULL || num_mnc_digits_ptr == NULL)
  {
    CM_ERR_2("imsi_ptr 0x%x, imsi_ptr->data_ptr or num_mnc_digits_ptr 0x%x is NULL", 
               imsi_ptr, 
               num_mnc_digits_ptr);
    return FALSE;
  }

  /* Old SIM cards had only 2 digits MNC and EF-AD with 3 bytes only.
     Default to 2 digits to keep backward compatibility */
  *num_mnc_digits_ptr = SYS_MNC_2_DIGITS;

  if(ad_ptr == NULL)
  {
    CM_MSG_HIGH_0("EF-AD ptr is NULL, use default 2 digit MNC");
    return TRUE;
  }

  /* 3GPP 23.122 Annex 'A'
     For PCS1900 for North America, regulations mandate that a 3-digit MNC
     shall be used; however during a transition period, a 2 digit MNC may
     be broadcast by the Network and, in this case, the 3rd digit of the
     SIM is stored as 0 (this is the 0 suffix rule).
     For these specific country codes, MNC length shall default to 3. */
  mcc_value  = (size_t)((imsi_ptr->data_ptr[SYS_IMSI_DIGIT_1_OFFSET] >> 4) &
                        SYS_IMSI_LOW_DIGIT_MASK) * 100;
  mcc_value += (size_t)((imsi_ptr->data_ptr[SYS_IMSI_DIGIT_2_OFFSET]) &
                        SYS_IMSI_LOW_DIGIT_MASK) * 10;
  mcc_value += (size_t)((imsi_ptr->data_ptr[SYS_IMSI_DIGIT_2_OFFSET] >> 4) &
                        SYS_IMSI_LOW_DIGIT_MASK);
  for (i = 0; i < sizeof(mcc_pcs1900_na_list) / sizeof(uint16); i++)
  {
    if (mcc_value == (size_t)mcc_pcs1900_na_list[i])
    {
      *num_mnc_digits_ptr = SYS_MNC_3_DIGITS;
      break;
    }
  }

  if (ad_ptr->data_len > SYS_MNC_LEN_BYTE && ad_ptr->data_ptr != NULL)
  {
    if ( ((ad_ptr->data_ptr[SYS_MNC_LEN_BYTE] & 0x0F) == SYS_MNC_2_DIGITS ) ||
         ((ad_ptr->data_ptr[SYS_MNC_LEN_BYTE] & 0x0F) == SYS_MNC_3_DIGITS ) )
    {
      *num_mnc_digits_ptr = ad_ptr->data_ptr[SYS_MNC_LEN_BYTE] & 0x0F;
    }
    else
    {
      CM_ERR_1("EF-AD has invalid MNC length: 0x%x", ad_ptr->data_ptr[SYS_MNC_LEN_BYTE]);
    }
  }

  //CM_MSG_HIGH_1("Number of MNC digits: 0x%x", *num_mnc_digits_ptr );
  return TRUE;
}/* sys_get_num_of_mnc_digits */
\mmcp\mmode\cm\src\cmph.c
/*==========================================================================

FUNCTION cmph_read_imsi_hplmn

DESCRIPTION
  Function that reads EF-IMSI and return HPLMN(MCC-MNC)

RETURN VALUE
  boolean  Flag indicating whether EF-IMSI read
           from the SIM successfully (TRUE) or unsuccessfully(FALSE).

DEPENDENCIES
  None
===========================================================================*/
static boolean cmph_read_imsi_hplmn
(
  sys_plmn_id_s_type *imsi_ptr,

  mmgsdi_session_type_enum_type    session_type

)
{
  boolean                       status    = FALSE;
  mmgsdi_app_enum_type          app_type;
  byte                          imsi[MMGSDI_IMSI_LEN] = {0};
  byte                          admin_data[CMMMGSDI_RPM_AD_SIZE] = {0};
  boolean                       plmn_is_undefined_ptr;
  boolean                       mnc_includes_pcs_digit_ptr;
  sys_mcc_type                  mcc=SYS_WILDCARD_MCC;
  sys_mnc_type                  mnc=SYS_WILDCARD_MNC;
  sys_modem_as_id_e_type        asubs_id= SYS_MODEM_AS_ID_1;


  app_type = cm_mmgsdi_ssn_tbl_get_app_type_for_type(
               session_type);

  /* Read EF-IMSI */
  status = cmmmgsdi_read(session_type,
                         (app_type == MMGSDI_APP_SIM ? MMGSDI_GSM_IMSI : MMGSDI_USIM_IMSI),
                         0,
                         MMGSDI_IMSI_LEN,
                         (uint8 *)imsi,
                         sizeof(imsi),
                         transparent);

  /* Read EF-AD to get MNC length */
  if(status)
  {
    status = cmmmgsdi_read(session_type,
                           (app_type == MMGSDI_APP_SIM ? MMGSDI_GSM_AD : MMGSDI_USIM_AD),
                           0,
                           CMMMGSDI_RPM_AD_SIZE,
                           (uint8 *)admin_data,
                           sizeof(admin_data),
                           transparent);
  }

  /* Extract MCC and MNC */
  if(status)
  {
    /*
    ** Fill MCC Digit 1 and MCC Digit 2
    */
    imsi_ptr->identity[0] = (byte)(( ( imsi[1] & 0xF0 ) / 0x10 ) +
                                   ( ( imsi[2] & 0x0F ) * 0x10 ));

    /*
    ** Fill MCC Digit 3 and MNC Digit 3
    */
    imsi_ptr->identity[1] = (byte)(( ( imsi[2] & 0xF0 ) / 0x10 ) +
                                   ( ( imsi[4] & 0x0F ) * 0x10 ));

    /*
    ** If 2 digits MNC is indicated in EF-AD then set MNC digit 3 to 'F'.
    */
    if ((admin_data[3] & 0x0F) == 0x02)
    {
      CM_MSG_MED_0("2 digit MNC");

      imsi_ptr->identity[1] |= 0xF0;
    }

    /*
    ** Fill MNC Digit 1 and MNC Digit 2
    */
    imsi_ptr->identity[2] = imsi[3];

    CM_MSG_HIGH_3_EXT("Read IMSI - HPLMN : 0x%02x, 0x%02x, 0x%02x",
                      imsi_ptr->identity[0],imsi_ptr->identity[1],imsi_ptr->identity[2],
                      SESSION_TO_AS_ID(session_type));
	
	/*Store MCC/MNC Values*/
    sys_plmn_get_mcc_mnc2(*imsi_ptr,&plmn_is_undefined_ptr,&mnc_includes_pcs_digit_ptr,
                            &mcc,&mnc);

    if(session_type == MMGSDI_GW_PROV_PRI_SESSION)
    {
      asubs_id = SYS_MODEM_AS_ID_1;
    }
    else if(session_type == MMGSDI_GW_PROV_SEC_SESSION)
    {
      asubs_id = SYS_MODEM_AS_ID_2;
    }
    else if(session_type == MMGSDI_GW_PROV_TER_SESSION)
    {
      asubs_id = SYS_MODEM_AS_ID_3;
    }

    if(asubs_id < MAX_SIMS && cmph_ptr()->sub_info[asubs_id] != NULL)
    {
      cmph_ptr()->sub_info[asubs_id]->gwl_mcc=mcc;
      cmph_ptr()->sub_info[asubs_id]->gwl_mnc=mnc;
      sd_misc_update_3gpp_imsi(asubs_id,mcc,mnc);
    }
  }

  return status;

} /* cmph_read_imsi_hplmn() */

确定MNC有几位的参数

通过代码可以看出,确定IMSI中MNC有几位的参数存在SIM卡的EFAD中,具体见:

3GPP 31.102 

4.2.18 EFAD (Administrative Data)

This EF contains information concerning the mode of operation according to the type of USIM, such as normal (to be used by PLMN subscribers for 3G operations), type approval (to allow specific use of the ME during type approval procedures of e.g. the radio equipment), cell testing (to allow testing of a cell before commercial use of this cell), manufacturer specific (to allow the ME manufacturer to perform specific proprietary autotest in its ME during e.g. maintenance phases).

It also provides an indication about how some ME features shall work during normal operation as well as information about the length of the MNC, which is part of the International Mobile Subscriber Identity (IMSI).

Identifier: '6FAD'

Structure: transparent

Mandatory

SFI: '03'

File size: 4+X bytes

Update activity: low

Access Conditions:

            READ                                         ALW

            UPDATE                                    ADM

            DEACTIVATE                            ADM

            ACTIVATE                                 ADM

Bytes

Description

M/O

Length

1

UE operation mode

M

1 byte

2 to 3

Additional information

M

2 bytes

4

length of MNC in the IMSI

M

1 byte

5 to 4+X

RFU

O

X bytes

问题解决验证

我前同事再写卡IMSI时把卡EFAD的length of MNC in the IMSI参数写正确了,再读IMSI得到的PLMN位数就正确了。

;