Bug 778093 - Part 5/9: support base GSM CBS message, r=hsinyi

This commit is contained in:
Vicamo Yang 2012-12-04 10:41:28 +08:00
parent 94efa23152
commit edebfa589d
2 changed files with 251 additions and 1 deletions

View File

@ -937,7 +937,33 @@ this.CB_FORMAT_ETWS = 1;
this.CB_FORMAT_CMAS = 2;
this.CB_FORMAT_UMTS = 3;
// CBS Data Coding Scheme: Language groups
// see 3GPP TS 23.038 section 5
this.CB_DCS_LANG_GROUP_1 = [
"de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi",
"no", "el", "tr", "hu", "pl", null
];
this.CB_DCS_LANG_GROUP_2 = [
"cs", "he", "ar", "ru", "is", null, null, null, null, null,
null, null, null, null, null, null
];
// User Data max length in septets
this.CB_MAX_CONTENT_7BIT = 93;
// User Data max length in octets
this.CB_MAX_CONTENT_8BIT = 82;
// User Data max length in chars
this.CB_MAX_CONTENT_UCS2 = 41;
this.CB_MESSAGE_SIZE_ETWS = 56;
this.CB_MESSAGE_SIZE_GSM = 88;
// GSM Cell Broadcast Geographical Scope
// See 3GPP TS 23.041 clause 9.4.1.2.1
this.CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0;
this.CB_GSM_GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1;
this.CB_GSM_GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2;
this.CB_GSM_GEOGRAPHICAL_SCOPE_CELL_WIDE = 3;
// GSM Cell Broadcast Geographical Scope
// See 3GPP TS 23.041 clause 9.4.1.2.1
@ -948,6 +974,11 @@ this.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES = [
"cell"
];
// GSM Cell Broadcast Message Identifiers
// see 3GPP TS 23.041 clause 9.4.1.2.2
this.CB_GSM_MESSAGEID_ETWS_BEGIN = 0x1100;
this.CB_GSM_MESSAGEID_ETWS_END = 0x1107;
// ETWS Warning-Type
// see 3GPP TS 23.041 clause 9.3.24
this.CB_ETWS_WARNING_TYPE_NAMES = [
@ -1141,6 +1172,8 @@ this.PDU_DCS_MSG_CLASS_0 = 0x00;
this.PDU_DCS_MSG_CLASS_1 = 0x01;
this.PDU_DCS_MSG_CLASS_2 = 0x02;
this.PDU_DCS_MSG_CLASS_3 = 0x03;
this.PDU_DCS_MSG_CLASS_USER_1 = 0x04;
this.PDU_DCS_MSG_CLASS_USER_2 = 0x05;
this.PDU_DCS_CODING_GROUP_BITS = 0xF0;
this.PDU_DCS_MSG_CLASS_BITS = 0x03;
this.PDU_DCS_MWI_ACTIVE_BITS = 0x08;
@ -1157,6 +1190,8 @@ GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_0] = "class-0";
GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_1] = "class-1";
GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2] = "class-2";
GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_3] = "class-3";
GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_1] = "user-1";
GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_USER_2] = "user-2";
// Because service center timestamp omit the century. Yay.
this.PDU_TIMESTAMP_YEAR_OFFSET = 2000;

View File

@ -270,6 +270,21 @@ let Buf = {
return this.readUint8Unchecked();
},
readUint8Array: function readUint8Array(length) {
// Translate to 0..currentParcelSize
let last = this.currentParcelSize - this.readAvailable;
last += (length - 1);
this.ensureIncomingAvailable(last);
let array = new Uint8Array(length);
for (let i = 0; i < length; i++) {
array[i] = this.readUint8Unchecked();
}
this.readAvailable -= length;
return array;
},
readUint16: function readUint16() {
return this.readUint8() | this.readUint8() << 8;
},
@ -6434,7 +6449,7 @@ let GsmPDUHelper = {
*/
readDataCodingScheme: function readDataCodingScheme(msg) {
let dcs = this.readHexOctet();
if (DEBUG) debug("PDU: read dcs: " + dcs);
if (DEBUG) debug("PDU: read SMS dcs: " + dcs);
// No message class by default.
let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
@ -6965,6 +6980,122 @@ let GsmPDUHelper = {
*/
readCbMessageIdentifier: function readCbMessageIdentifier(msg) {
msg.messageId = Buf.readUint8() << 8 | Buf.readUint8();
if ((msg.format != CB_FORMAT_ETWS)
&& (msg.messageId >= CB_GSM_MESSAGEID_ETWS_BEGIN)
&& (msg.messageId <= CB_GSM_MESSAGEID_ETWS_END)) {
// `In the case of transmitting CBS message for ETWS, a part of
// Message Code can be used to command mobile terminals to activate
// emergency user alert and message popup in order to alert the users.`
msg.etws = {
emergencyUserAlert: msg.messageCode & 0x0200 ? true : false,
popup: msg.messageCode & 0x0100 ? true : false
};
let warningType = msg.messageId - CB_GSM_MESSAGEID_ETWS_BEGIN;
if (warningType < CB_ETWS_WARNING_TYPE_NAMES.length) {
msg.etws.warningType = warningType;
}
}
},
/**
* Read CBS Data Coding Scheme.
*
* @param msg
* message object for output.
*
* @see 3GPP TS 23.038 section 5.
*/
readCbDataCodingScheme: function readCbDataCodingScheme(msg) {
let dcs = Buf.readUint8();
if (DEBUG) debug("PDU: read CBS dcs: " + dcs);
let language = null, hasLanguageIndicator = false;
// `Any reserved codings shall be assumed to be the GSM 7bit default
// alphabet.`
let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
case 0x00: // 0000
language = CB_DCS_LANG_GROUP_1[dcs & 0x0F];
break;
case 0x10: // 0001
switch (dcs & 0x0F) {
case 0x00:
hasLanguageIndicator = true;
break;
case 0x01:
encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
hasLanguageIndicator = true;
break;
}
break;
case 0x20: // 0010
language = CB_DCS_LANG_GROUP_2[dcs & 0x0F];
break;
case 0x40: // 01xx
case 0x50:
//case 0x60: Text Compression, not supported
//case 0x70: Text Compression, not supported
case 0x90: // 1001
encoding = (dcs & 0x0C);
if (encoding == 0x0C) {
encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
}
messageClass = (dcs & PDU_DCS_MSG_CLASS_BITS);
break;
case 0xF0:
encoding = (dcs & 0x04) ? PDU_DCS_MSG_CODING_8BITS_ALPHABET
: PDU_DCS_MSG_CODING_7BITS_ALPHABET;
switch(dcs & PDU_DCS_MSG_CLASS_BITS) {
case 0x01: messageClass = PDU_DCS_MSG_CLASS_USER_1; break;
case 0x02: messageClass = PDU_DCS_MSG_CLASS_USER_2; break;
case 0x03: messageClass = PDU_DCS_MSG_CLASS_3; break;
}
break;
case 0x30: // 0011 (Reserved)
case 0x80: // 1000 (Reserved)
case 0xA0: // 1010..1100 (Reserved)
case 0xB0:
case 0xC0:
break;
default:
throw new Error("Unsupported CBS data coding scheme: " + dcs);
}
msg.dcs = dcs;
msg.encoding = encoding;
msg.language = language;
msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
msg.hasLanguageIndicator = hasLanguageIndicator;
},
/**
* Read GSM CBS message page parameter.
*
* @param msg
* message object for output.
*
* @see 3GPP TS 23.041 section 9.4.1.2.4
*/
readCbPageParameter: function readCbPageParameter(msg) {
let octet = Buf.readUint8();
msg.pageIndex = (octet >>> 4) & 0x0F;
msg.numPages = octet & 0x0F;
if (!msg.pageIndex || !msg.numPages) {
// `If a mobile receives the code 0000 in either the first field or the
// second field then it shall treat the CBS message exactly the same as a
// CBS message with page parameter 0001 0001 (i.e. a single page message).`
msg.pageIndex = msg.numPages = 1;
}
},
/**
@ -6984,6 +7115,53 @@ let GsmPDUHelper = {
};
},
/**
* Read CBS-Message-Information-Page
*
* @param msg
* message object for output.
* @param length
* length of cell broadcast data to read in octets.
*
* @see 3GPP TS 23.041 section 9.3.19
*/
readGsmCbData: function readGsmCbData(msg, length) {
let bufAdapter = {
readHexOctet: function readHexOctet() {
return Buf.readUint8();
}
};
msg.body = null;
msg.data = null;
switch (msg.encoding) {
case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
msg.body = this.readSeptetsToString.call(bufAdapter,
(length * 8 / 7), 0,
PDU_NL_IDENTIFIER_DEFAULT,
PDU_NL_IDENTIFIER_DEFAULT);
if (msg.hasLanguageIndicator) {
msg.language = msg.body.substring(0, 2);
msg.body = msg.body.substring(3);
}
break;
case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
msg.data = Buf.readUint8Array(length);
break;
case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
if (msg.hasLanguageIndicator) {
msg.language = this.readSeptetsToString.call(bufAdapter, 2, 0,
PDU_NL_IDENTIFIER_DEFAULT,
PDU_NL_IDENTIFIER_DEFAULT);
length -= 2;
}
msg.body = this.readUCS2String.call(bufAdapter, length);
break;
}
},
/**
* Read Cell GSM/ETWS/UMTS Broadcast Message.
*
@ -6996,11 +7174,21 @@ let GsmPDUHelper = {
// Internally used in ril_worker:
updateNumber: null, // O O O
format: null, // O O O
dcs: 0x0F, // O X O
encoding: PDU_DCS_MSG_CODING_7BITS_ALPHABET, // O X O
hasLanguageIndicator: false, // O X O
data: null, // O X O
body: null, // O X O
pageIndex: 1, // O X X
numPages: 1, // O X X
// DOM attributes:
geographicalScope: null, // O O O
messageCode: null, // O O O
messageId: null, // O O O
language: null, // O X O
fullBody: null, // O X O
fullData: null, // O X O
messageClass: GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL], // O x O
etws: null // ? O ?
/*{
@ -7015,9 +7203,36 @@ let GsmPDUHelper = {
return this.readEtwsCbMessage(msg);
}
if (pduLength <= CB_MESSAGE_SIZE_GSM) {
msg.format = CB_FORMAT_GSM;
return this.readGsmCbMessage(msg, pduLength);
}
return null;
},
/**
* Read GSM Cell Broadcast Message.
*
* @param msg
* message object for output.
* @param pduLength
* total length of the incomint PDU in octets.
*
* @see 3GPP TS 23.041 clause 9.4.1.2
*/
readGsmCbMessage: function readGsmCbMessage(msg, pduLength) {
this.readCbSerialNumber(msg);
this.readCbMessageIdentifier(msg);
this.readCbDataCodingScheme(msg);
this.readCbPageParameter(msg);
// GSM CB message header takes 6 octets.
this.readGsmCbData(msg, pduLength - 6);
return msg;
},
/**
* Read ETWS Primary Notification Message.
*