~aleteoryx/muditaos

ref: 39a09e862722d241acd1897ed913b710b198002b muditaos/module-services/service-cellular/src/SimCard.hpp -rw-r--r-- 5.3 KiB
39a09e86 — Wiktor S. Ovalle Correa [EGD-6746] New SimCard implementation 4 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
// Copyright (c) 2017-2021, 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>

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 sim card slot has been selected and cmd channel is set
         * @return true if ready to communicate
         */
        bool ready() const;

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

        /**
         * Request message handlers
         */
        bool handleSetActiveSim(api::SimSlot sim);
        bool handleIsPinLocked() 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::SimLockState lock);
        bool handlePinUnlock(const api::SimCode &pin);

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

        /**
         * Notification events
         */
        std::function<void(bool ready)> 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;

      private:
        /** 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
         */
        bool isPinLocked() const;

        /** Read internal SIM state using CPIN AT commands
         */
        std::optional<at::SimState> simState() 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);

        at::BaseChannel *channel        = nullptr;
        std::optional<api::SimSlot> sim = std::nullopt;
    };

} // namespace cellular::service