mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 798000 - Part 1 - Read EF_OPL, EF_PNN files and update network name. r=vicamo
This commit is contained in:
parent
aa11c96fe6
commit
a3cc5f89c2
@ -422,6 +422,7 @@ this.ICC_EF_CBMIR = 0x6f50;
|
||||
this.ICC_EF_AD = 0x6fad;
|
||||
this.ICC_EF_PHASE = 0x6fae;
|
||||
this.ICC_EF_PNN = 0x6fc5;
|
||||
this.ICC_EF_OPL = 0x6fc6;
|
||||
this.ICC_EF_MBDN = 0x6fc7;
|
||||
this.ICC_EF_EXT6 = 0x6fc8; // Ext record for EF[MBDN]
|
||||
this.ICC_EF_MBI = 0x6fc9;
|
||||
@ -581,6 +582,11 @@ this.COMPREHENSIONTLV_TAG_BROADCAST_NETWORK_INFO = 0x7a;
|
||||
this.SPDI_TAG_SPDI = 0xa3;
|
||||
this.SPDI_TAG_PLMN_LIST = 0x80;
|
||||
|
||||
// MM INFORMATION message content IEIs
|
||||
// See 3GPP TS 24.008 table 9.2.18
|
||||
this.PNN_IEI_FULL_NETWORK_NAME = 0x43;
|
||||
this.PNN_IEI_SHORT_NETWORK_NAME = 0x45;
|
||||
|
||||
// Device identifiers, see TS 11.14, clause 12.7
|
||||
this.STK_DEVICE_ID_KEYPAD = 0x01;
|
||||
this.STK_DEVICE_ID_DISPLAY = 0x02;
|
||||
@ -988,6 +994,8 @@ this.GECKO_ICC_SERVICES = {
|
||||
DATA_DOWNLOAD_SMS_PP: 26,
|
||||
CBMIR: 30,
|
||||
BDN: 31,
|
||||
PNN: 51,
|
||||
OPL: 52,
|
||||
SPDI: 56
|
||||
},
|
||||
usim: {
|
||||
@ -998,6 +1006,8 @@ this.GECKO_ICC_SERVICES = {
|
||||
CBMIR: 16,
|
||||
SPN: 19,
|
||||
DATA_DOWNLOAD_SMS_PP: 28,
|
||||
PNN: 45,
|
||||
OPL: 46,
|
||||
SPDI: 51
|
||||
}
|
||||
};
|
||||
|
@ -1671,6 +1671,219 @@ let RIL = {
|
||||
(serviceTable[index] & bitmask)) != 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Choose network names using EF_OPL and EF_PNN
|
||||
* See 3GPP TS 31.102 sec. 4.2.58 and sec. 4.2.59 for USIM,
|
||||
* 3GPP TS 51.011 sec. 10.3.41 and sec. 10.3.42 for SIM.
|
||||
*/
|
||||
updateNetworkName: function updateNetworkName() {
|
||||
let iccInfoPriv = this.iccInfoPrivate;
|
||||
let iccInfo = this.iccInfo;
|
||||
|
||||
// We won't update network name if voice registration isn't ready
|
||||
// or PNN file haven't been retrieved.
|
||||
if (!iccInfoPriv.PNN ||
|
||||
!this.voiceRegistrationState.cell ||
|
||||
this.voiceRegistrationState.cell.gsmLocationAreaCode == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let pnnEntry;
|
||||
let lac = this.voiceRegistrationState.cell.gsmLocationAreaCode;
|
||||
let mcc = this.operator.mcc;
|
||||
let mnc = this.operator.mnc;
|
||||
|
||||
// According to 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
|
||||
// the ME shall use this EF_OPL in association with the EF_PNN in place
|
||||
// of any network name stored within the ME's internal list and any network
|
||||
// name received when registered to the PLMN.
|
||||
if (iccInfoPriv.OPL) {
|
||||
for (let i in iccInfoPriv.OPL) {
|
||||
let opl = iccInfoPriv.OPL[i];
|
||||
// Try to match the MCC/MNC.
|
||||
if (mcc != opl.mcc || mnc != opl.mnc) {
|
||||
continue;
|
||||
}
|
||||
// Try to match the location area code. If current local area code is
|
||||
// covered by lac range that specified in the OPL entry, use the PNN
|
||||
// that specified in the OPL entry.
|
||||
if ((opl.lacTacStart == 0x0 && opl.lacTacEnd == 0xFFFE) ||
|
||||
(opl.lacTacStart <= lac && opl.lacTacEnd >= lac)) {
|
||||
if (opl.pnnRecordId == 0) {
|
||||
// See 3GPP TS 31.102 Sec. 4.2.59 and 3GPP TS 51.011 Sec. 10.3.42,
|
||||
// A value of '00' indicates that the name is to be taken from other
|
||||
// sources.
|
||||
return null;
|
||||
}
|
||||
pnnEntry = iccInfoPriv.PNN[opl.pnnRecordId - 1]
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// According to 3GPP TS 31.102 Sec. 4.2.58 and 3GPP TS 51.011 Sec. 10.3.41,
|
||||
// the first record in this EF is used for the default network name when
|
||||
// registered to the HPLMN.
|
||||
// If we haven't get pnnEntry assigned, we should try to assign default
|
||||
// value to it.
|
||||
if (!pnnEntry && mcc == iccInfo.mcc && mnc == iccInfo.mnc) {
|
||||
pnnEntry = iccInfoPriv.PNN[0]
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
if (pnnEntry) {
|
||||
debug("updateNetworkName: Network names will be overriden: longName = " +
|
||||
pnnEntry.fullName + ", shortName = " + pnnEntry.shortName);
|
||||
} else {
|
||||
debug("updateNetworkName: Network names will not be overriden");
|
||||
}
|
||||
}
|
||||
|
||||
if (pnnEntry) {
|
||||
return [pnnEntry.fullName, pnnEntry.shortName];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read OPL (Operator PLMN List) from USIM.
|
||||
*
|
||||
* See 3GPP TS 31.102 Sec. 4.2.59 for USIM
|
||||
* 3GPP TS 51.011 Sec. 10.3.42 for SIM.
|
||||
*/
|
||||
getOPL: function getOPL() {
|
||||
let opl = [];
|
||||
function callback(options) {
|
||||
let len = Buf.readUint32();
|
||||
// The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
|
||||
// in 3GPP TS 23.003, Sec 4.1
|
||||
// +-------------+---------+
|
||||
// | Octet 1 - 3 | MCC/MNC |
|
||||
// +-------------+---------+
|
||||
// | Octet 4 - 7 | LAC |
|
||||
// +-------------+---------+
|
||||
let mccMnc = [GsmPDUHelper.readHexOctet(),
|
||||
GsmPDUHelper.readHexOctet(),
|
||||
GsmPDUHelper.readHexOctet()];
|
||||
if (mccMnc[0] != 0xFF || mccMnc[1] != 0xFF || mccMnc[2] != 0xFF) {
|
||||
let oplElement = {};
|
||||
let semiOctets = [];
|
||||
for (let i = 0; i < mccMnc.length; i++) {
|
||||
semiOctets.push((mccMnc[i] & 0xf0) >> 4);
|
||||
semiOctets.push(mccMnc[i] & 0x0f);
|
||||
}
|
||||
let reformat = [semiOctets[1], semiOctets[0], semiOctets[3],
|
||||
semiOctets[5], semiOctets[4], semiOctets[2]];
|
||||
let buf = "";
|
||||
for (let i = 0; i < reformat.length; i++) {
|
||||
if (reformat[i] != 0xF) {
|
||||
buf += GsmPDUHelper.semiOctetToBcdChar(reformat[i]);
|
||||
}
|
||||
if (i === 2) {
|
||||
// 0-2: MCC
|
||||
oplElement.mcc = parseInt(buf);
|
||||
buf = "";
|
||||
} else if (i === 5) {
|
||||
// 3-5: MNC
|
||||
oplElement.mnc = parseInt(buf);
|
||||
}
|
||||
}
|
||||
// LAC/TAC
|
||||
oplElement.lacTacStart =
|
||||
(GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
|
||||
oplElement.lacTacEnd =
|
||||
(GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
|
||||
// PLMN Network Name Record Identifier
|
||||
oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
|
||||
if (DEBUG) {
|
||||
debug("OPL: [" + (opl.length + 1) + "]: " + JSON.stringify(oplElement));
|
||||
}
|
||||
opl.push(oplElement);
|
||||
}
|
||||
Buf.readStringDelimiter(len);
|
||||
if (options.p1 < options.totalRecords) {
|
||||
options.p1++;
|
||||
this.iccIO(options);
|
||||
} else {
|
||||
this.iccInfoPrivate.OPL = opl;
|
||||
}
|
||||
}
|
||||
|
||||
this.iccIO({
|
||||
command: ICC_COMMAND_GET_RESPONSE,
|
||||
fileId: ICC_EF_OPL,
|
||||
pathId: this._getPathIdForICCRecord(ICC_EF_OPL),
|
||||
p1: 0, // For GET_RESPONSE, p1 = 0
|
||||
p2: 0, // For GET_RESPONSE, p2 = 0
|
||||
p3: GET_RESPONSE_EF_SIZE_BYTES,
|
||||
data: null,
|
||||
pin2: null,
|
||||
type: EF_TYPE_LINEAR_FIXED,
|
||||
callback: callback,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Read PNN (PLMN Network Name) from USIM.
|
||||
*
|
||||
* See 3GPP TS 31.102 Sec. 4.2.58 for USIM
|
||||
* 3GPP TS 51.011 Sec. 10.3.41 for SIM.
|
||||
*/
|
||||
getPNN: function getPNN() {
|
||||
let pnn = [];
|
||||
function callback(options) {
|
||||
let pnnElement = this.iccInfoPrivate.PNN = {};
|
||||
let len = Buf.readUint32();
|
||||
let readLen = 0;
|
||||
while (len > readLen) {
|
||||
let tlvTag = GsmPDUHelper.readHexOctet();
|
||||
readLen = readLen + 2; // 1 Hex octet
|
||||
if (tlvTag == 0xFF) {
|
||||
// Unused byte
|
||||
continue;
|
||||
}
|
||||
let tlvLen = GsmPDUHelper.readHexOctet();
|
||||
let name;
|
||||
switch (tlvTag) {
|
||||
case PNN_IEI_FULL_NETWORK_NAME:
|
||||
pnnElement.fullName = GsmPDUHelper.readNetworkName(tlvLen);
|
||||
break;
|
||||
case PNN_IEI_SHORT_NETWORK_NAME:
|
||||
pnnElement.shortName = GsmPDUHelper.readNetworkName(tlvLen);
|
||||
break;
|
||||
default:
|
||||
Buf.seekIncoming(PDU_HEX_OCTET_SIZE * tlvLen);
|
||||
}
|
||||
readLen += (tlvLen * 2 + 2);
|
||||
}
|
||||
if (DEBUG) {
|
||||
debug("PNN: [" + (pnn.length + 1) + "]: " + JSON.stringify(pnnElement));
|
||||
}
|
||||
Buf.readStringDelimiter(len);
|
||||
pnn.push(pnnElement);
|
||||
|
||||
if (options.p1 < options.totalRecords) {
|
||||
options.p1++;
|
||||
this.iccIO(options);
|
||||
} else {
|
||||
this.iccInfoPrivate.PNN = pnn;
|
||||
}
|
||||
}
|
||||
|
||||
this.iccIO({
|
||||
command: ICC_COMMAND_GET_RESPONSE,
|
||||
fileId: ICC_EF_PNN,
|
||||
pathId: this._getPathIdForICCRecord(ICC_EF_PNN),
|
||||
p1: 0, // For GET_RESPONSE, p1 = 0
|
||||
p2: 0, // For GET_RESPONSE, p2 = 0
|
||||
p3: GET_RESPONSE_EF_SIZE_BYTES,
|
||||
data: null,
|
||||
pin2: null,
|
||||
type: EF_TYPE_LINEAR_FIXED,
|
||||
callback: callback,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Read the (U)SIM Service Table from the ICC.
|
||||
*/
|
||||
@ -1705,6 +1918,20 @@ let RIL = {
|
||||
if (DEBUG) debug("SPDI: SPDI service is not available");
|
||||
}
|
||||
|
||||
if (this.isICCServiceAvailable("PNN")) {
|
||||
if (DEBUG) debug("PNN: PNN is available");
|
||||
this.getPNN();
|
||||
} else {
|
||||
if (DEBUG) debug("PNN: PNN is not available");
|
||||
}
|
||||
|
||||
if (this.isICCServiceAvailable("OPL")) {
|
||||
if (DEBUG) debug("OPL: OPL is available");
|
||||
this.getOPL();
|
||||
} else {
|
||||
if (DEBUG) debug("OPL: OPL is not available");
|
||||
}
|
||||
|
||||
if (this.isICCServiceAvailable("CBMI")) {
|
||||
this.getCBMI();
|
||||
} else {
|
||||
@ -3643,6 +3870,8 @@ let RIL = {
|
||||
case ICC_EF_SPDI:
|
||||
case ICC_EF_CBMI:
|
||||
case ICC_EF_CBMIR:
|
||||
case ICC_EF_OPL:
|
||||
case ICC_EF_PNN:
|
||||
return EF_PATH_MF_SIM + EF_PATH_ADF_USIM;
|
||||
|
||||
default:
|
||||
@ -3968,8 +4197,15 @@ let RIL = {
|
||||
this.operator.shortName !== shortName ||
|
||||
thisTuple !== networkTuple) {
|
||||
|
||||
this.operator.longName = longName;
|
||||
this.operator.shortName = shortName;
|
||||
let networkName = this.updateNetworkName();
|
||||
if (networkName) {
|
||||
this.operator.longName = networkName[0];
|
||||
this.operator.shortName = networkName[1];
|
||||
} else {
|
||||
this.operator.longName = longName;
|
||||
this.operator.shortName = shortName;
|
||||
}
|
||||
|
||||
this.operator.mcc = 0;
|
||||
this.operator.mnc = 0;
|
||||
|
||||
@ -7848,6 +8084,60 @@ let GsmPDUHelper = {
|
||||
|
||||
return msg;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read network name.
|
||||
*
|
||||
* @param len Length of the information element.
|
||||
* @return
|
||||
* {
|
||||
* networkName: network name.
|
||||
* shouldIncludeCi: Should Country's initials included in text string.
|
||||
* }
|
||||
* @see TS 24.008 clause 10.5.3.5a.
|
||||
*/
|
||||
readNetworkName: function readNetworkName(len) {
|
||||
// According to TS 24.008 Sec. 10.5.3.5a, the first octet is:
|
||||
// bit 8: must be 1.
|
||||
// bit 5-7: Text encoding.
|
||||
// 000 - GSM default alphabet.
|
||||
// 001 - UCS2 (16 bit).
|
||||
// else - reserved.
|
||||
// bit 4: MS should add the letters for Country's Initials and a space
|
||||
// to the text string if this bit is true.
|
||||
// bit 1-3: number of spare bits in last octet.
|
||||
|
||||
let codingInfo = GsmPDUHelper.readHexOctet();
|
||||
if (!(codingInfo & 0x80)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let textEncoding = (codingInfo & 0x70) >> 4,
|
||||
shouldIncludeCountryInitials = !!(codingInfo & 0x08),
|
||||
spareBits = codingInfo & 0x07;
|
||||
let resultString;
|
||||
|
||||
switch (textEncoding) {
|
||||
case 0:
|
||||
// GSM Default alphabet.
|
||||
resultString = GsmPDUHelper.readSeptetsToString(
|
||||
((len - 1) * 8 - spareBits) / 7, 0,
|
||||
PDU_NL_IDENTIFIER_DEFAULT,
|
||||
PDU_NL_IDENTIFIER_DEFAULT);
|
||||
break;
|
||||
case 1:
|
||||
// UCS2 encoded.
|
||||
resultString = this.readUCS2String(len - 1);
|
||||
break;
|
||||
default:
|
||||
// Not an available text coding.
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO - Bug 820286: According to shouldIncludeCountryInitials, add
|
||||
// country initials to the resulting string.
|
||||
return resultString;
|
||||
}
|
||||
};
|
||||
|
||||
let StkCommandParamsFactory = {
|
||||
|
Loading…
Reference in New Issue
Block a user