~aleteoryx/muditaos

ref: 6cc2bc9df4ed70d5548f7f4296be4062553b5c7a muditaos/module-services/service-cellular/src/SimCard.hpp -rw-r--r-- 8.1 KiB
6cc2bc9d — Dawid Wojtas [BH-1830] Fix eink crash while refreshing 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <at/response.hpp>
#include <at/SimState.hpp>
#include <service-cellular/api/common.hpp>

#include <module-cellular/at/SimInsertedState.hpp>

namespace at
{
    class Cmd;
    class BaseChannel;
} // namespace at

namespace cellular::service::sim
{
    enum class Pin
    {
        PIN1 = 0,
        PIN2 = 1
    };

    enum class Result
    {
        OK     = 0,
        Ready  = 1,
        Locked = 2, /*!< In case of attempt counters set to 0 */

        AT_ERROR_Begin = 9, /*!< this is only for separate AT SIM errors from new one added, AT errors list end with
                               AT_ERROR_End */

        SIMNotInserted    = 10,
        SIM_PIN_required  = 11,
        SIM_PUKRequired   = 12,
        Failure           = 13,
        Busy              = 14,
        Wrong             = 15,
        IncorrectPassword = 16,

        AT_ERROR_End = 17,

        Unknown = 0xFF /*!< Unknown, any reason (not only AT), in some case AT commends return just error, eg. twice
                                  supply good pin, second AT commend return ERROR */

    };

    enum class LockType
    {
        PIN,
        PUK
    };
} // namespace cellular::service::sim

namespace cellular::internal
{
    service::sim::Result convertErrorFromATResult(const at::Result atres);
    std::string simCodeToString(const cellular::api::SimCode &v);
} // namespace cellular::internal

namespace cellular::service
{
    class SimCard
    {
      public:
        /** Check if cmd channel is set
         * @return true if ready to communicate
         */
        bool ready() const;

        /** Check if card is fully initialized
         * @return true in card is fully operational
         */
        bool initialized() const;

        /** Set cmd channel
         * \param channel channel (or nullptr to block communication)
         */
        void setChannel(at::BaseChannel *channel);

        /**
         * Request message handlers
         */
        bool handleSetActiveSim(api::SimSlot sim);
        std::optional<bool> handleIsPinNeeded() const;
        bool handleChangePin(const api::SimCode &old_pin, const api::SimCode &pin);
        bool handleUnblockWithPuk(const api::SimCode &puk, const api::SimCode &pin);
        bool handleSetPinLock(const api::SimCode &pin, api::SimPinState pinLock);
        bool handlePinUnlock(const api::SimCode &pin);

        /**
         * Notification message handlers
         */
        void handleTrayState();

        /**
         * Internal message handlers
         */
        void handleATSimStateChange(at::SimState state);

        /**
         * Check if sim card is present in slot
         * @return true if sim card is present in slot
         */
        bool isSimCardInserted();

        /**
         * Set new sim inserted status
         * @param newStatus
         */
        void setSimInserted(at::SimInsertedStatus newStatus)
        {
            simInserted = newStatus;
        }

        /**
         * Gets sim inserted status
         * @return actual value of sim inserted status
         */
        std::optional<at::SimInsertedStatus> getSimInsertedStatus()
        {
            return simInserted;
        }

        /**
         * Clears sim inserted status
         */
        void clearSimInsertedStatus()
        {
            simInserted = std::nullopt;
        }

        /**
         * Gets Sim Select progress state
         * @return true if sim selecting is in progres
         */
        bool isSimSelectInProgress()
        {
            return simSelectInProgress;
        }

        /**
         * Sets Sim Select progress state
         * @param inProgress new progress state
         */
        void setSimSelectInProgress(bool inProgress)
        {
            simSelectInProgress = inProgress;
        }

        /**
         * Sim timer event handler
         */
        void handleSimTimer();

        /**
         * Sim Inserted notification handler
         * @param status new Sim Inserted status
         */
        void handleSimInsertionNotification(at::SimInsertedStatus status);

        /**
         * Handles post sim selection actions
         */
        void handleSimCardSelected();
        /**
         * Get Sim selected state
         * @return true when Sim is selected, fail when not
         */
        bool isSimCardSelected()
        {
            return isSimSelected;
        }

        /** Read internal SIM state using CPIN AT commands
         */
        std::optional<at::SimState> simState() const;

        /**
         * Notification events
         */
        std::function<void()> onSimReady;
        std::function<void(unsigned int attempts)> onNeedPin;
        std::function<void(unsigned int attempts)> onNeedPuk;
        std::function<void()> onSimBlocked;
        std::function<void()> onSimEvent;
        std::function<void(unsigned int code)> onUnhandledCME;
        std::function<void()> onSimNotPresent;
        std::function<void()> onSimSelected;

      private:
        /** SIM card initialization sequence
         * \return true on success, false on failure
         */
        bool initSimCard();

        /** Get information about attempts of PIN and PUK for standard sim card (optionally PIN2/PUK2)
         * \return  As optional SimCard::AttemptsCounters, in case of error nullopt. Should be noted that in some case
         * could return SIMFailure which could mean 0 attempts (happen if lock during session, on modem/sim reboot again
         * return 0,0);
         */
        std::optional<at::response::qpinc::AttemptsCounters> getAttemptsCounters(sim::Pin pin = sim::Pin::PIN1) const;

        /** Supply pin for modem
         * \param pin digits as a string from 4-8 digits
         * \return return OK on success in other case see details in SimCardResult
         */
        sim::Result supplyPin(const std::string &pin) const;

        /** Supply pin for modem
         * \param puk puk as standard 8 digits
         * \param pin, new pin digits as a string from 4-8 digits
         * \return return OK on success in other case see details in SimCardResult
         */
        sim::Result supplyPuk(const std::string &puk, const std::string &pin) const;

        /** Set whether to provide pin. Always need to provide actual pin for sim card, only for standard PIN
         * \param lock true for lock SIM card
         * \param pin actual pin for SIM card
         * \return
         */
        sim::Result setPinLock(const std::string &pin, bool lock) const;

        /** Change pin, only for standard pin. To get effect of change pin, SIM cart or modem should be restarted
         * simplest solution is to call AT+CFUN=0/1
         * \param oldPin
         * \param newPin
         * \return return OK on success, else see SimCardResult
         */
        sim::Result changePin(const std::string &oldPin, const std::string &newPin) const;

        /** Check whether the PIN needs to be provided, only for standard PIN.
         * \return true if need PIN to unlock SIM card functionality, false if don't need, std::nullopt if SIM card
         * not ready
         */
        std::optional<bool> isPinNeeded() const;

        /** Process sim::Result from PIN lock/unlock operations
         * \param result result from operation (`sendCommand()`)
         * \result return true on success
         */
        bool processPinResult(sim::Result result);

        sim::Result sendCommand(sim::LockType check, const at::Cmd &cmd) const;

        void handleSimState(at::SimState state);

        /**
         * Read sim card insert status
         * @return sim card inserted status
         */
        std::optional<at::SimInsertedStatus> readSimCardInsertStatus();

        at::BaseChannel *channel                         = nullptr;
        std::optional<api::SimSlot> sim                  = std::nullopt;
        std::optional<at::SimInsertedStatus> simInserted = std::nullopt;
        bool simSelectInProgress                         = false;
        bool isSimSelected                               = false;
    };

} // namespace cellular::service