1/*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef GSM_CB_CODEC_H
17#define GSM_CB_CODEC_H
18
19#include <ctime>
20#include <string>
21
22#include "gsm_cb_pdu_decode_buffer.h"
23
24namespace OHOS {
25namespace Telephony {
26class GsmCbCodec : public std::enable_shared_from_this<GsmCbCodec> {
27public:
28    static constexpr uint8_t CB_IOS639_LANG_SIZE = 3;
29    /**
30     * from 3GPP TS 23.041 V4.1.0 (2001-06) 5 section Network Architecture
31     * GSM Cell broadcast message 0x01
32     * UMTSCell broadcast message 0x02
33     * CDMA broadcast message 0x03
34     */
35    enum CBNetType {
36        GSM_NET_CB = 1,
37        UMTS_NET_CB,
38        CDMA_NET_CB,
39    };
40
41    /**
42     * Primary ETWS message
43     * GSM Secondary ETWS message
44     * UMTS Secondary ETWS message
45     * CDMA Seconday ETWS message
46     */
47    enum EtwsCBType {
48        ETWS_PRIMARY = 0,
49        ETWS_GSM,
50        ETWS_UMTS,
51        ETWS_CDMA,
52    };
53
54    /**
55     * CBS Message
56     * Schedule Message
57     * CBS41 Message
58     * JAVA-CB Message
59     */
60    enum GsmCbMsgType {
61        GSM_UNKNOWN = 0,
62        GSM_CBS,
63        GSM_SCHEDULE,
64        GSM_CBS41,
65        GSM_JAVACBS,
66        GSM_ETWS,
67    };
68
69    /**
70     * from 3GPP TS 23.038 V4.3.0 (2001-09) 5 section
71     * CBS Data Coding Scheme
72     */
73    enum GsmCbMsgLangType {
74        CB_LANG_GERMAN = 0x00,
75        CB_LANG_ENGLISH = 0x01,
76        CB_LANG_ITALIAN = 0x02,
77        CB_LANG_FRENCH = 0x03,
78        CB_LANG_SPANISH = 0x04,
79        CB_LANG_DUTCH = 0x05,
80        CB_LANG_SWEDISH = 0x06,
81        CB_LANG_DANISH = 0x07,
82        CB_LANG_PORTUGUESE = 0x08,
83        CB_LANG_FINNISH = 0x09,
84        CB_LANG_NORWEGIAN = 0x0a,
85        CB_LANG_GREEK = 0x0b,
86        CB_LANG_TURKISH = 0x0c,
87        CB_LANG_HUNGARIAN = 0x0d,
88        CB_LANG_POLISH = 0x0e,
89        CB_MSG_UNSPECIFIED = 0x0f,
90
91        CB_LANG_ISO639 = 0x10,
92
93        CB_LANG_CZECH = 0x20,
94        CB_LANG_HEBREW = 0x21,
95        CB_LANG_ARABIC = 0x22,
96        CB_LANG_RUSSIAN = 0x23,
97        CB_LANG_ICELANDIC = 0x24,
98        CB_LANG_RESERVED_25 = 0x25,
99        CB_LANG_RESERVED_26 = 0x26,
100        CB_LANG_RESERVED_27 = 0x27,
101        CB_LANG_RESERVED_28 = 0x28,
102        CB_LANG_RESERVED_29 = 0x29,
103        CB_LANG_RESERVED_2A = 0x2a,
104        CB_LANG_RESERVED_2B = 0x2b,
105        CB_LANG_RESERVED_2C = 0x2c,
106        CB_LANG_RESERVED_2D = 0x2d,
107        CB_LANG_RESERVED_2E = 0x2e,
108        CB_LANG_RESERVED_2F = 0x2f,
109
110        CB_LANG_DUMMY = 0xFF
111    };
112
113    enum GSMCbMsgSubType {
114        /* SMS Specific Message Type */
115        NORMAL_MSG = 0, /** Text SMS message */
116        CB_SMS, /** Cell Broadcasting  message */
117        JAVACB_SMS, /** JAVA Cell Broadcasting  message */
118
119        CMAS_PRESIDENTIAL, /** CMAS CLASS */
120        CMAS_EXTREME,
121        CMAS_SEVERE,
122        CMAS_AMBER,
123        CMAS_TEST,
124        CMAS_EXERCISE,
125        CMAS_OPERATOR_DEFINED,
126    };
127
128    /**
129     * CMAS(Commercial Mobile Alert System) 4370-4399 (0x1112-0x112F)
130     */
131    enum CmasMsgType : unsigned short {
132        PRESIDENTIAL = 4370,
133        PRESIDENTIAL_SPANISH = 4383,
134
135        EXTREME_OBSERVED = 4371,
136        EXTREME_OBSERVED_SPANISH = 4384,
137        EXTREME_LIKELY = 4372,
138        EXTREME_LIKELY_SPANISH = 4385,
139
140        SEVERE_OBSERVED = 4373,
141        SEVERE_OBSERVED_SPANISH = 4386,
142        SEVERE_LIKELY = 4374,
143        SEVERE_LIKELY_SPANISH = 4387,
144        ALERT_OBSERVED_DEFUALT = 4375,
145        ALERT_OBSERVED_SPANISH = 4388,
146        ALERT_LIKELY = 4376,
147        ALERT_LIKELY_SPANISH = 4389,
148        EXPECTED_OBSERVED = 4377,
149        EXPECTED_OBSERVED_SPANISH = 4390,
150        EXPECTED_LIKELY = 4378,
151        EXPECTED_LIKELY_SPANISH = 4391,
152
153        AMBER_ALERT = 4379,
154        AMBER_ALERT_SPANISH = 4392,
155        MONTHLY_ALERT = 4380,
156        MONTHLY_ALERT_SPANISH = 4393,
157        EXERCISE_ALERT = 4381,
158        EXERCISE_ALERT_SPANISH = 4394,
159
160        OPERATOR_ALERT = 4382,
161        OPERATOR_ALERT_SPANISH = 4395,
162    };
163
164    enum SmsCbCodingGroupType {
165        SMS_CBMSG_CODGRP_GENERAL_DCS, /** Bits 7..4 00xx */
166        SMS_CBMSG_CODGRP_WAP, /** 1110 Cell Broadcast */
167        SMS_CBMSG_CODGRP_CLASS_CODING, /** 1111 Cell Broadcast */
168    };
169
170    enum GsmCbLangType : unsigned short {
171        LANG_UNKNOWN = 0x00,
172        LANG_ENGLISH = 0x01,
173        LANG_FRENCH = 0x02,
174        LANG_SPANISH = 0x03,
175        LANG_JAPANESE = 0x04,
176        LANG_KOREAN = 0x05,
177        LANG_CHINESE = 0x06,
178        LANG_HEBREW = 0x07,
179    };
180
181    /**
182     * from 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.1.2.1 section
183     * Serial Number
184     */
185    struct GsmCBMsgSerialNum {
186        uint8_t geoScope = 0;
187        uint8_t updateNum = 0;
188        unsigned short msgCode = 0;
189    };
190
191    /**
192     * from 3GPP TS 23.038 V4.3.0 (2001-09) 5 section
193     * CBS Data Coding Scheme
194     */
195    struct GsmCbMsgDcs {
196        uint8_t codingGroup = 0; /**  Coding group, GSM 03.38 */
197        uint8_t classType = 0; /** The message class */
198        bool bCompressed = false; /** if text is compressed this is TRUE */
199        uint8_t codingScheme = 0; /** How to encode a message. */
200        uint8_t langType = 0;
201        uint8_t iso639Lang[GsmCbCodec::CB_IOS639_LANG_SIZE] = { 0 }; /* 2 GSM chars and a CR char */
202        bool bUDH = false;
203        uint8_t rawData = 0;
204    };
205
206    /**
207     * from 3GPP TS 23.041 V4.1.0 (2001-06) 9.4.1.2 section
208     * Message Parameter
209     */
210    struct GsmCbMessageHeader {
211        bool bEtwsMessage;
212        EtwsCBType cbEtwsType;
213        CBNetType cbNetType;
214        uint8_t cbMsgType;
215        unsigned short warningType;
216        GsmCBMsgSerialNum serialNum;
217        unsigned short msgId;
218        uint8_t langType;
219        GsmCbMsgDcs dcs;
220        uint8_t page;
221        uint8_t totalPages;
222        time_t recvTime;
223
224        bool operator==(const GsmCbMessageHeader &other) const
225        {
226            return serialNum.geoScope == other.serialNum.geoScope && serialNum.msgCode == other.serialNum.msgCode &&
227                   msgId == other.msgId;
228        }
229    };
230    GsmCbCodec() = default;
231    ~GsmCbCodec() = default;
232    bool operator==(const GsmCbCodec &other) const;
233    static std::shared_ptr<GsmCbCodec> CreateCbMessage(const std::string &pdu);
234    static std::shared_ptr<GsmCbCodec> CreateCbMessage(const std::vector<uint8_t> &pdu);
235    std::shared_ptr<GsmCbMessageHeader> GetCbHeader() const;
236    void ConvertToUTF8(const std::string &raw, std::string &message) const;
237    void DecodeCbMsgDCS(const uint8_t dcsData, const unsigned short iosData, GsmCbMsgDcs &dcs) const;
238    std::string GetCbMessageRaw() const;
239    unsigned short EncodeCbSerialNum(const GsmCBMsgSerialNum &snFields);
240    bool GetFormat(int8_t &cbFormat) const;
241    bool GetPriority(int8_t &cbPriority) const;
242    bool GetGeoScope(uint8_t &geoScope) const;
243    bool GetSerialNum(uint16_t &cbSerial) const;
244    bool GetServiceCategory(uint16_t &cbCategoty) const;
245    bool GetWarningType(uint16_t &type) const;
246    bool GetCmasSeverity(uint8_t &severity) const;
247    bool GetCmasUrgency(uint8_t &urgency) const;
248    bool GetCmasCertainty(uint8_t &certainty) const;
249    bool GetCmasCategory(uint8_t &cmasCategory) const;
250    bool GetCmasResponseType(uint8_t &cmasRes) const;
251    bool GetMessageId(uint16_t &msgId) const;
252    bool GetCmasMessageClass(uint8_t &cmasClass) const;
253    bool GetMsgType(uint8_t &msgType) const;
254    bool GetLangType(uint8_t &lan) const;
255    bool GetDcs(uint8_t &dcs) const;
256    bool GetReceiveTime(int64_t &receiveTime) const;
257    int64_t GetRecvTime() const;
258    void GetPduData(std::vector<uint8_t> &dataPdu);
259
260    bool IsEtwsPrimary(bool &primary) const;
261    bool IsEtwsMessage(bool &etws) const;
262    bool IsCmasMessage(bool &cmas) const;
263    bool IsEtwsEmergencyUserAlert(bool &alert) const;
264    bool IsEtwsPopupAlert(bool &alert) const;
265    bool IsSinglePageMsg() const;
266    void SetCbMessageRaw(std::string &raw);
267    std::string ToString() const;
268
269private:
270    bool PduAnalysis(const std::vector<uint8_t> &pdu);
271    void DecodeIos639Dcs(const uint8_t dcsData, const unsigned short iosData, GsmCbMsgDcs &dcs) const;
272    void DecodeGeneralDcs(const uint8_t dcsData, GsmCbMsgDcs &dcs) const;
273    uint8_t CMASClass(const uint16_t messageId) const;
274    bool ParamsCheck(const std::vector<uint8_t> &pdu);
275
276private:
277    std::shared_ptr<GsmCbMessageHeader> cbHeader_ { nullptr };
278    std::string messageRaw_;
279    std::shared_ptr<GsmCbPduDecodeBuffer> cbPduBuffer_ { nullptr };
280};
281} // namespace Telephony
282} // namespace OHOS
283#endif // GSM_CB_CODEC_H