• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uqmi/uqmid/sim_fsm.c

  1 /*
  2  * uqmi -- tiny QMI support implementation
  3  *
  4  * Copyright (C) 2024 Alexander Couzens <lynxis@fe80.eu>
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  */
 17 
 18 /* SIM/UIM card FSM
 19  *
 20  * tracks the state of the sim and notifies the parent on hard events.
 21  * e.g. removal of the sim
 22  *
 23  * The general concept is:
 24  * Get information about (IMSI should not be available _before_ PIN/PUK valildation if enabled:
 25  *  - ICCID
 26  *  - PIN/PUK state
 27  *  - SPN, PNN (provider name)
 28  *
 29  * Unlock if locked by PIN if enough tries are available (more than 1 try).
 30  * Enter a failed state if not enough PIN tries are available
 31  * Enter a failed state if locked by PUK
 32  * If unlocked, read IMSI.
 33  *
 34  * Further add user interface to:
 35  * - unlock PIN/PUK via ubus
 36  * - read/write transparent files
 37  * - rx/tx APDU (e.g. for eSIM interface)
 38  *
 39  * See 3GPP TS 31.102 for USIM
 40  */
 41 
 42 #include "logging.h"
 43 #include "modem.h"
 44 #include "modem_tx.h"
 45 #include "osmocom/fsm.h"
 46 #include "osmocom/utils.h"
 47 #include "sim_fsm.h"
 48 #include "modem_fsm.h"
 49 #include "qmi-enums.h"
 50 #include "qmi-message.h"
 51 #include "qmi-enums-uim.h"
 52 #include "services.h"
 53 #include "utils.h"
 54 
 55 #include <talloc.h>
 56 
 57 #define S(x) (1 << (x))
 58 
 59 #define SIM_DEFAULT_TIMEOUT_S 5
 60 
 61 // move the sim configuration
 62 // child fsm
 63 // what happens when the sim goes down?
 64 
 65 #define MAX_PATH 3
 66 struct uim_file {
 67         uint16_t file_id;
 68         uint8_t path_n; /* count of elements in path */
 69         uint16_t path[MAX_PATH]; /* a path is a 16 bit integer */
 70 };
 71 
 72 enum uim_file_names {
 73         UIM_FILE_IMSI,
 74         UIM_FILE_ICCID,
 75 };
 76 
 77 /* 3GPP TS 31.102 */
 78 static const struct uim_file uim_files[] = {
 79         [UIM_FILE_IMSI] = { 0x6f07, 2, { 0x3f00, 0x7fff } },
 80         [UIM_FILE_ICCID] = { 0x2fe2, 1, { 0x3f00 } },
 81 };
 82 
 83 static int _tx_uim_read_transparent_file(struct modem *modem, struct qmi_service *uim, request_cb cb,
 84                                          enum uim_file_names file_name)
 85 {
 86         uint8_t path[MAX_PATH * 2];
 87         const struct uim_file *file = &uim_files[file_name];
 88 
 89         for (int i = 0, j = 0; i < file->path_n; i++, j += 2) {
 90                 path[j] = file->path[i] & 0xff;
 91                 path[j + 1] = file->path[i] >> 8;
 92         }
 93 
 94         return tx_uim_read_transparent_file(modem, uim, cb, file->file_id, &path[0], file->path_n * 2);
 95 }
 96 
 97 static void sim_st_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 98 {
 99         switch (event) {
100         case SIM_EV_REQ_START:
101                 osmo_fsm_inst_state_chg(fi, SIM_ST_GET_INFO, SIM_DEFAULT_TIMEOUT_S, 0);
102                 break;
103         default:
104                 break;
105         }
106 }
107 
108 static void sim_st_wait_uim_present(struct osmo_fsm_inst *fi, uint32_t event, void *data)
109 {
110 }
111 
112 static void uim_get_slot_status_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg)
113 {
114         struct modem *modem = req->cb_data;
115         int ret = 0, i = 0;
116         char *iccid_str;
117 
118         if (req->ret) {
119                 modem_log(modem, LOGL_INFO, "Failed to get slot status. Returned %d/%s. Trying next card status",
120                           req->ret, qmi_get_error_str(req->ret));
121                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_GET_SLOT_FAILED, NULL);
122                 return;
123         }
124 
125         struct qmi_uim_get_slot_status_response res = {};
126         ret = qmi_parse_uim_get_slot_status_response(msg, &res);
127         if (ret) {
128                 modem_log(modem, LOGL_INFO, "Failed to get slot status.");
129                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_GET_SLOT_FAILED, NULL);
130                 return;
131         }
132 
133         for (i = 0; i < res.data.physical_slot_status_n; ++i) {
134                 uint32_t physical_card_status = res.data.physical_slot_status[i].physical_card_status;
135                 uint32_t physical_slot_status = res.data.physical_slot_status[i].physical_slot_status;
136                 /* ignoring uint8_t logical_slot */
137                 unsigned int iccid_n = res.data.physical_slot_status[i].iccid_n;
138                 uint8_t *iccid_bcd = res.data.physical_slot_status[i].iccid;
139 
140                 if (physical_card_status != QMI_UIM_PHYSICAL_CARD_STATE_PRESENT)
141                         continue;
142 
143                 if (physical_slot_status != QMI_UIM_SLOT_STATE_ACTIVE)
144                         continue;
145 
146                 if (iccid_n == 0) {
147                         modem_log(modem, LOGL_INFO, "slot %d: Empty ICCID. UIM not yet ready? Or an EUICC?", i);
148                         continue;
149                 }
150 
151                 /* FIXME: check for uneven number .. */
152                 int iccid_str_len = iccid_n * 2;
153                 iccid_str = talloc_zero_size(modem, iccid_n * 2);
154                 ret = osmo_bcd2str(iccid_str, iccid_str_len, iccid_bcd, 0, iccid_n, 1);
155 
156                 if (ret) {
157                         modem_log(modem, LOGL_INFO, "Couldn't decode ICCID of slot %d", i);
158                         talloc_free(iccid_str);
159                         continue;
160                 }
161 
162                 if (modem->iccid) {
163                         modem_log(modem, LOGL_INFO, "Modem already contains an ICCID. Replacing old entry %s with %s",
164                                   modem->iccid, iccid_str);
165                         talloc_free(modem->iccid);
166                 }
167                 modem->iccid = iccid_str;
168                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_VALID_ICCID, NULL);
169         }
170 
171         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_NO_UIM_FOUND, NULL);
172 }
173 
174 static void uim_get_card_status_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg)
175 {
176         struct modem *modem = req->cb_data;
177         int ret = 0, i = 0, found = 0;
178         bool found_card_state = false;
179 
180         if (req->ret) {
181                 modem_log(modem, LOGL_INFO, "Failed to get card status %d/%s.", req->ret, qmi_get_error_str(req->ret));
182                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_FAILED, NULL);
183                 return;
184         }
185 
186         struct qmi_uim_get_card_status_response res = {};
187         ret = qmi_parse_uim_get_card_status_response(msg, &res);
188         if (ret) {
189                 modem_log(modem, LOGL_INFO, "Failed to get card status. Decoder failed.");
190                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_FAILED, NULL);
191                 return;
192         }
193 
194         for (i = 0; i < res.data.card_status.cards_n; ++i) {
195                 found_card_state = true;
196                 if (res.data.card_status.cards[i].card_state != QMI_UIM_CARD_STATE_PRESENT)
197                         continue;
198 
199                 for (int j = 0; j < res.data.card_status.cards[i].applications_n; ++j) {
200                         /* TODO: We should prioritize the USIM application. If not found, fallback to SIM -> ISIM -> CSIM */
201                         if (res.data.card_status.cards[i].applications[j].type == QMI_UIM_CARD_APPLICATION_TYPE_UNKNOWN)
202                                 continue;
203 
204                         modem_log(modem, LOGL_INFO, "Found valid card application type %x",
205                                   res.data.card_status.cards[i].applications[j].type);
206                         modem->sim.use_upin = res.data.card_status.cards[i].applications[i].upin_replaces_pin1;
207 
208                         /* check if pin1 or upin is the correct method */
209                         if (modem->sim.use_upin) {
210                                 modem->sim.state = uim_pin_to_uqmi_state(res.data.card_status.cards[i].upin_state);
211                                 modem->sim.pin_retries = res.data.card_status.cards[i].upin_retries;
212                                 modem->sim.puk_retries = res.data.card_status.cards[i].upuk_retries;
213                         } else {
214                                 modem->sim.state =
215                                         uim_pin_to_uqmi_state(res.data.card_status.cards[i].applications[i].pin1_state);
216                                 modem->sim.pin_retries = res.data.card_status.cards[i].applications[i].pin1_retries;
217                                 modem->sim.puk_retries = res.data.card_status.cards[i].applications[i].puk1_retries;
218                         }
219 
220                         found = 1;
221                         break; /* handle first application only for now */
222                 }
223 
224                 if (found) {
225                         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_CARD_STATUS_VALID, NULL);
226                         return;
227                 }
228         }
229 
230         if (found_card_state) {
231                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_NO_UIM_FOUND, (void *) 1);
232         } else {
233                 modem_log(modem, LOGL_INFO, "Failed to find a valid UIM in get_status. Failing UIM.");
234                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_FAILED, NULL);
235         }
236 }
237 
238 static void uim_read_imsi_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg)
239 {
240         struct modem *modem = req->cb_data;
241         int ret = 0;
242 
243         if (req->ret) {
244                 modem_log(modem, LOGL_INFO, "Failed to read imsi. Qmi Ret %d/%s.", req->ret,
245                           qmi_get_error_str(req->ret));
246                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_GET_IMSI_FAILED, NULL);
247                 return;
248         }
249 
250         struct qmi_uim_read_record_response res = {};
251         ret = qmi_parse_uim_read_record_response(msg, &res);
252         if (ret) {
253                 modem_log(modem, LOGL_INFO, "Failed to read imsi. Decoder failed. %d", ret);
254                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_GET_IMSI_FAILED, NULL);
255                 return;
256         }
257 
258         /* TODO: card result on 5g without imsi? */
259         // if (res.set.card_result) {
260         //     modem_log(modem, LOGL_INFO, "Failed to read imsi. Card Result.");
261         //     return;
262         // }
263 
264         if (!res.data.read_result_n) {
265                 modem_log(modem, LOGL_INFO, "Failed to read imsi. No Read Data");
266                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_FAILED, NULL);
267                 return;
268         }
269 
270         // where to get a BCD decoder?
271         ret = uqmi_sim_decode_imsi(res.data.read_result, res.data.read_result_n, modem->imsi, sizeof(modem->imsi));
272         if (ret < 0)
273                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_GET_IMSI_FAILED, NULL);
274 
275         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_GET_IMSI_SUCCESS, NULL);
276 }
277 
278 static void sim_st_get_info_on_enter(struct osmo_fsm_inst *fi, uint32_t old_state)
279 {
280         struct modem *modem = fi->priv;
281 
282         struct qmi_service *uim = uqmi_service_find(modem->qmi, QMI_SERVICE_UIM);
283         // struct qmi_service *dms = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS);
284 
285         // should we use uim and have it available?
286         if (uim && modem->sim.use_uim) {
287                 modem_log(modem, LOGL_INFO, "Trying to query UIM for slot status.");
288                 uqmi_service_send_simple(uim, qmi_set_uim_get_slot_status_request, uim_get_slot_status_cb, modem);
289                 return;
290         } else {
291                 // dms
292         }
293 }
294 
295 static void sim_st_get_info(struct osmo_fsm_inst *fi, uint32_t event, void *_data)
296 {
297         struct modem *modem = fi->priv;
298         long data = (long) _data;
299 
300         struct qmi_service *uim = uqmi_service_find(modem->qmi, QMI_SERVICE_UIM);
301 
302         switch (event) {
303         case SIM_EV_RX_UIM_GET_SLOT_FAILED:
304         case SIM_EV_RX_UIM_VALID_ICCID:
305                 /* Get Slot Status succeeded? */
306                 if (uim && modem->sim.use_uim)
307                         uqmi_service_send_simple(uim, qmi_set_uim_get_card_status_request, uim_get_card_status_cb,
308                                                  modem);
309                 break;
310         case SIM_EV_RX_UIM_NO_UIM_FOUND:
311                 if (uim && modem->sim.use_uim) {
312                         /* Get Slot Status failed, try Get Card Status */
313                         if (data == 0)
314                                 uqmi_service_send_simple(uim, qmi_set_uim_get_card_status_request, uim_get_card_status_cb,
315                                                          modem);
316                         /* Get Card Status also failed to get one */
317                         else if (data == 1)
318                                 osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_NO_SIM_PRESENT, 0, 0);
319                 }
320                 break;
321         case SIM_EV_RX_UIM_CARD_STATUS_VALID:
322                 /* We found a valid SIM card via card status */
323                 if (uim && modem->sim.use_uim)
324                         _tx_uim_read_transparent_file(modem, uim, uim_read_imsi_cb, UIM_FILE_IMSI);
325                 break;
326         case SIM_EV_RX_UIM_GET_IMSI_FAILED:
327         case SIM_EV_RX_UIM_GET_IMSI_SUCCESS:
328                 switch (modem->sim.state) {
329                 case UQMI_SIM_PIN_REQUIRED:
330                         osmo_fsm_inst_state_chg(fi, SIM_ST_CHV_PIN, SIM_DEFAULT_TIMEOUT_S, 0);
331                         break;
332                 case UQMI_SIM_PUK_REQUIRED:
333                         osmo_fsm_inst_state_chg(fi, SIM_ST_CHV_PUK, SIM_DEFAULT_TIMEOUT_S, 0);
334                         break;
335                 case UQMI_SIM_READY:
336                         osmo_fsm_inst_state_chg(fi, SIM_ST_READY, 0, 0);
337                         break;
338                 case UQMI_SIM_UNKNOWN:
339                         modem_log(modem, LOGL_ERROR, "Got unknown SIM state by UIM. Is a SIM present?");
340                         osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_NO_SIM_PRESENT, 0, 0);
341                         break;
342                 case UQMI_SIM_BLOCKED:
343                         modem_log(modem, LOGL_ERROR, "SIM is blocked. Can't do anythings");
344                         osmo_fsm_inst_state_chg(fi, SIM_ST_FAILED, 0, 0);
345                         break;
346                 default:
347                         /* FIXME: default case */
348                         break;
349                 }
350                 break;
351         }
352 }
353 
354 static void uim_verify_pin_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg)
355 {
356         struct modem *modem = req->cb_data;
357         int ret = 0;
358 
359         struct qmi_uim_verify_pin_response res = {};
360         ret = qmi_parse_uim_verify_pin_response(msg, &res);
361 
362         if (req->ret) {
363                 modem_log(modem, LOGL_INFO, "Failed to verify PIN. Qmi Ret %d/%s.", req->ret,
364                           qmi_get_error_str(req->ret));
365                 if (!ret && res.set.retries_remaining) {
366                         modem->sim.pin_retries = res.data.retries_remaining.verify_retries_left;
367                         modem->sim.puk_retries = res.data.retries_remaining.unblock_retries_left;
368                         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_PIN_INVALID, (void *) 1);
369                 } else
370                         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_PIN_INVALID, (void *) 0);
371                 return;
372         }
373 
374         if (ret) {
375                 modem_log(modem, LOGL_INFO, "Failed to verify pin. Decoder failed. %d", ret);
376                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_REFRESH, NULL);
377                 return;
378         }
379 
380         if (res.set.retries_remaining) {
381                 modem->sim.pin_retries = res.data.retries_remaining.verify_retries_left;
382                 modem->sim.puk_retries = res.data.retries_remaining.unblock_retries_left;
383         }
384 
385         if (res.set.card_result && res.data.card_result.sw1 == 0x63) {
386                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_PIN_VERIFIED, NULL);
387                 return;
388         }
389 
390         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_REFRESH, NULL);
391 }
392 
393 static void pin_verify(struct modem *modem, char *pin)
394 {
395         QmiUimPinId pin_id;
396         struct qmi_service *uim = uqmi_service_find(modem->qmi, QMI_SERVICE_UIM);
397 
398         modem->sim.pin_tried = true;
399 
400         if (modem->sim.use_upin)
401                 pin_id = QMI_UIM_PIN_ID_UPIN;
402         else
403                 pin_id = QMI_UIM_PIN_ID_PIN1;
404 
405         tx_uim_verify_pin(modem, uim, &uim_verify_pin_cb, pin_id, pin);
406 }
407 
408 static void sim_st_chv_pin_on_enter(struct osmo_fsm_inst *fi, uint32_t old_state)
409 {
410         struct modem *modem = fi->priv;
411 
412         if (modem->sim.pin_retries < 2 || modem->sim.pin_tried || !modem->config.pin) {
413                 osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_PIN_REQUIRED, SIM_DEFAULT_TIMEOUT_S, 0);
414                 return;
415         }
416 
417         pin_verify(modem, modem->config.pin);
418 }
419 
420 static void sim_st_chv_pin(struct osmo_fsm_inst *fi, uint32_t event, void *data)
421 {
422         switch (event) {
423         case SIM_EV_RX_UIM_REFRESH:
424         case SIM_EV_RX_UIM_PIN_VERIFIED:
425                 osmo_fsm_inst_state_chg(fi, SIM_ST_GET_INFO, SIM_DEFAULT_TIMEOUT_S, 0);
426                 break;
427         case SIM_EV_RX_UIM_PIN_INVALID:
428                 osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_PIN_REQUIRED, SIM_DEFAULT_TIMEOUT_S, 0);
429                 break;
430         }
431 }
432 
433 static void uim_unblock_pin_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg)
434 {
435         struct modem *modem = req->cb_data;
436         int ret = 0;
437 
438         struct qmi_uim_unblock_pin_response res = {};
439         ret = qmi_parse_uim_unblock_pin_response(msg, &res);
440 
441         if (req->ret) {
442                 modem_log(modem, LOGL_INFO, "Failed to unblock PIN by PUK. Qmi Ret %d/%s.", req->ret,
443                           qmi_get_error_str(req->ret));
444                 if (!ret && res.set.retries_remaining) {
445                         modem->sim.pin_retries = res.data.retries_remaining.verify_retries_left;
446                         modem->sim.puk_retries = res.data.retries_remaining.unblock_retries_left;
447                         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_PUK_INVALID, (void *) 1);
448                 } else
449                         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_PUK_INVALID, (void *) 0);
450                 return;
451         }
452 
453         if (ret) {
454                 modem_log(modem, LOGL_INFO, "Failed to unblock pin/puk. Decoder failed. %d", ret);
455                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_REFRESH, NULL);
456                 return;
457         }
458 
459         if (res.set.retries_remaining) {
460                 modem->sim.pin_retries = res.data.retries_remaining.verify_retries_left;
461                 modem->sim.puk_retries = res.data.retries_remaining.unblock_retries_left;
462         }
463 
464         if (res.set.card_result && res.data.card_result.sw1 == 0x63) {
465                 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_PUK_VERIFIED, NULL);
466                 return;
467         }
468 
469         osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_RX_UIM_REFRESH, NULL);
470 }
471 
472 static int pin_unblock(struct modem *modem, char *new_pin, char *puk)
473 {
474         QmiUimPinId pin_id;
475         struct qmi_service *uim = uqmi_service_find(modem->qmi, QMI_SERVICE_UIM);
476 
477         modem->sim.puk_tried = true;
478         if (modem->sim.use_upin)
479                 pin_id = QMI_UIM_PIN_ID_UPIN;
480         else
481                 pin_id = QMI_UIM_PIN_ID_PIN1;
482 
483         return tx_uim_unblock_pin(modem, uim, &uim_unblock_pin_cb, pin_id, new_pin, puk);
484 }
485 
486 static void sim_st_chv_puk_on_enter(struct osmo_fsm_inst *fi, uint32_t old_state)
487 {
488         struct modem *modem = fi->priv;
489 
490         if (modem->sim.puk_retries < 2 || modem->sim.puk_tried || !modem->config.puk || !modem->config.pin) {
491                 osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_PUK_REQUIRED, SIM_DEFAULT_TIMEOUT_S, 0);
492                 return;
493         }
494 
495 
496         if (pin_unblock(modem, modem->config.pin, modem->config.puk))
497                 osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_PUK_REQUIRED, 0, 0);
498 }
499 
500 static void sim_st_chv_puk(struct osmo_fsm_inst *fi, uint32_t event, void *data)
501 {
502         switch (event) {
503         case SIM_EV_RX_UIM_REFRESH:
504         case SIM_EV_RX_UIM_PIN_VERIFIED:
505                 osmo_fsm_inst_state_chg(fi, SIM_ST_GET_INFO, SIM_DEFAULT_TIMEOUT_S, 0);
506                 break;
507         case SIM_EV_RX_UIM_PIN_INVALID:
508                 osmo_fsm_inst_state_chg(fi, SIM_ST_FAIL_PIN_REQUIRED, SIM_DEFAULT_TIMEOUT_S, 0);
509                 break;
510         }
511 }
512 
513 static void sim_st_ready_on_enter(struct osmo_fsm_inst *fi, uint32_t old_state)
514 {
515         struct modem *modem = fi->priv;
516 
517         osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_REQ_SIM_READY, NULL);
518 }
519 
520 static void sim_st_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data)
521 {
522 }
523 
524 static void sim_st_fail_pin_required(struct osmo_fsm_inst *fi, uint32_t event, void *data)
525 {
526 }
527 
528 static void sim_st_fail_puk_required(struct osmo_fsm_inst *fi, uint32_t event, void *data)
529 {
530 }
531 
532 static void sim_st_fail_no_sim_present(struct osmo_fsm_inst *fi, uint32_t event, void *data)
533 {
534 }
535 
536 static void sim_st_failed(struct osmo_fsm_inst *fi, uint32_t event, void *data)
537 {
538 }
539 
540 static void sim_st_destroy_on_enter(struct osmo_fsm_inst *fi, uint32_t old_state)
541 {
542         // TODO: deregister indications?, wait x seconds, then terminate
543         // in theory we don't have to because the modem should close the registration when closing
544         // the uim service
545 }
546 
547 static void sim_st_destroy(struct osmo_fsm_inst *fi, uint32_t event, void *data)
548 {
549         switch (event) {
550         case SIM_EV_RX_FAILED:
551                 break;
552         case SIM_EV_RX_SUCCEED:
553                 break;
554         }
555         // terminate here when the derg
556 }
557 
558 static int sim_fsm_timer_cb(struct osmo_fsm_inst *fi)
559 {
560         // struct modem *modem = fi->priv;
561         // struct qmi_service *service;
562 
563         switch (fi->state) {
564         default:
565                 switch (fi->T) {
566                 default:
567                         break;
568                 }
569                 break;
570         }
571 
572         return 0;
573 }
574 
575 static void sim_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
576 {
577         switch (event) {
578         case SIM_EV_REQ_DESTROY:
579                 osmo_fsm_inst_state_chg(fi, SIM_ST_DESTROY, 0, 0);
580                 break;
581         }
582 }
583 
584 static const struct value_string sim_event_names[] = {
585         { SIM_EV_REQ_START,                     "REQ_START" },
586         { SIM_EV_REQ_CONFIGURED,                "REQ_CONFIGURED" },
587         { SIM_EV_REQ_DESTROY,           "REQ_DESTROY" },
588         { SIM_EV_RX_UIM_FAILED,         "RX_UIM_FAILED" },
589         { SIM_EV_RX_UIM_GET_SLOT_FAILED,        "RX_UIM_GET_SLOT_FAILED" },
590         { SIM_EV_RX_UIM_NO_UIM_FOUND,   "RX_UIM_NO_UIM_FOUND" },
591         { SIM_EV_RX_UIM_VALID_ICCID,    "RX_UIM_VALID_ICCID" },
592         { SIM_EV_RX_UIM_CARD_STATUS_VALID,      "RX_UIM_CARD_STATUS_VALID" },
593         { SIM_EV_RX_UIM_GET_IMSI_SUCCESS,       "RX_UIM_GET_IMSI_SUCCESS" },
594         { SIM_EV_RX_UIM_GET_IMSI_FAILED,        "RX_UIM_GET_IMSI_FAILED" },
595         { SIM_EV_RX_UIM_PIN_REQUIRED,   "RX_UIM_PIN_REQUIRED" },
596         { SIM_EV_RX_UIM_PUK_REQUIRED,   "RX_UIM_PUK_REQUIRED" },
597         { SIM_EV_RX_UIM_READY,          "RX_UIM_READY" },
598         { SIM_EV_RX_FAILED,                     "RX_FAILED" },
599         { SIM_EV_RX_SUCCEED,            "RX_SUCCEED" },
600         { 0, NULL },
601 };
602 
603 static const struct osmo_fsm_state sim_states[] = {
604         [SIM_ST_IDLE] = {
605                 .in_event_mask = S(SIM_EV_REQ_START),
606                 .out_state_mask = S(SIM_ST_GET_INFO) | S(SIM_ST_DESTROY),
607                 .name = "IDLE",
608                 .action = sim_st_idle,
609         },
610         [SIM_ST_WAIT_UIM_PRESENT] = {
611                 .in_event_mask = 0,
612                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_GET_INFO),
613                 .name = "WAIT UIM PRESENT",
614                 .action = sim_st_wait_uim_present,
615         },
616         [SIM_ST_GET_INFO] = {
617                 .in_event_mask = S(SIM_EV_RX_UIM_GET_SLOT_FAILED) |
618                                  S(SIM_EV_RX_UIM_VALID_ICCID) |
619                                  S(SIM_EV_RX_UIM_NO_UIM_FOUND) |
620                                  S(SIM_EV_RX_UIM_CARD_STATUS_VALID) |
621                                  S(SIM_EV_RX_UIM_GET_IMSI_SUCCESS) |
622                                  S(SIM_EV_RX_UIM_GET_IMSI_FAILED),
623                 .out_state_mask = S(SIM_ST_READY) |
624                                   S(SIM_ST_CHV_PIN) |
625                                   S(SIM_ST_CHV_PUK) |
626                                   S(SIM_ST_FAIL_NO_SIM_PRESENT) |
627                                   S(SIM_ST_DESTROY),
628                 .name = "GET_INFO",
629                 .onenter = sim_st_get_info_on_enter,
630                 .action = sim_st_get_info,
631         },
632         [SIM_ST_READY] = {
633                 .in_event_mask = 0,
634                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_GET_INFO),
635                 .name = "READY",
636                 .onenter = sim_st_ready_on_enter,
637                 .action = sim_st_ready,
638         },
639         [SIM_ST_CHV_PIN] = {
640                 .in_event_mask = 0,
641                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_CHV_PUK) | S(SIM_ST_GET_INFO),
642                 .name = "CHV_PIN",
643                 .onenter = sim_st_chv_pin_on_enter,
644                 .action = sim_st_chv_pin,
645         },
646         [SIM_ST_CHV_PUK] = {
647                 .in_event_mask = 0,
648                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_CHV_PIN) | S(SIM_ST_GET_INFO),
649                 .name = "CHV_PIN",
650                 .onenter = sim_st_chv_puk_on_enter,
651                 .action = sim_st_chv_puk,
652         },
653         [SIM_ST_FAIL_PIN_REQUIRED] = {
654                 .in_event_mask = 0,
655                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_GET_INFO),
656                 .name = "FAIL_PIN_REQUIRED",
657                 .action = sim_st_fail_pin_required,
658         },
659         [SIM_ST_FAIL_PUK_REQUIRED] = {
660                 .in_event_mask = 0,
661                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_GET_INFO),
662                 .name = "FAIL_PUK_REQUIRED",
663                 .action = sim_st_fail_puk_required,
664         },
665         [SIM_ST_FAIL_NO_SIM_PRESENT] = {
666                 .in_event_mask = 0,
667                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_GET_INFO),
668                 .name = "NO_SIM_PRESENT",
669                 .action = sim_st_fail_no_sim_present,
670         },
671         [SIM_ST_FAILED] = {
672                 .in_event_mask = 0,
673                 .out_state_mask = S(SIM_ST_DESTROY) | S(SIM_ST_GET_INFO),
674                 .name = "FAILED",
675                 .action = sim_st_failed,
676         },
677         [SIM_ST_DESTROY] = {
678                 .in_event_mask = 0,
679                 .out_state_mask = 0,
680                 .name = "DESTROY",
681                 .action = sim_st_destroy,
682                 .onenter = sim_st_destroy_on_enter,
683         },
684 };
685 
686 static struct osmo_fsm sim_fsm = {
687         .name = "SIM",
688         .states = sim_states,
689         .num_states = ARRAY_SIZE(sim_states),
690         .allstate_event_mask = S(SIM_EV_REQ_DESTROY),
691         .allstate_action = sim_fsm_allstate_action,
692         .timer_cb = sim_fsm_timer_cb,
693         .event_names = sim_event_names,
694         .pre_term = NULL,
695 };
696 
697 struct osmo_fsm_inst *sim_fsm_alloc(struct modem *modem)
698 {
699         struct osmo_fsm_inst *fi = osmo_fsm_inst_alloc_child(&sim_fsm, modem->fi, MODEM_EV_REQ_SIM_TERM);
700         if (fi)
701                 fi->priv = modem;
702 
703         return fi;
704 }
705 
706 static __attribute__((constructor)) void on_dso_load_ctx(void)
707 {
708         OSMO_ASSERT(osmo_fsm_register(&sim_fsm) == 0);
709 }
710 
711 // just to be removed later
712 
713 // static void
714 // dms_get_imsi_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg)
715 // {
716 //     struct modem *modem = req->cb_data;
717 //     int ret = 0;
718 
719 //     struct qmi_dms_uim_get_imsi_response res = {};
720 //     ret = qmi_parse_dms_uim_get_imsi_response(msg, &res);
721 
722 //     if (ret) {
723 //         modem_log(modem, LOGL_INFO, "Failed to get imsi via dms. Failed to parse message");
724 //         osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_IMSI_DMS_FAILED, NULL);
725 //         return;
726 //     }
727 
728 //     if (!res.data.imsi || strlen(res.data.imsi)) {
729 //         modem_log(modem, LOGL_INFO, "Received empty IMSI");
730 //         osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_IMSI_DMS_FAILED, (void *) 1);
731 //         return;
732 //     }
733 
734 //     strncpy(modem->imsi, res.data.imsi, 15);
735 //     osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_IMSI, NULL);
736 // }
737 
738 // static void tx_get_imsi_req(struct osmo_fsm_inst *fi, uint32_t old_state)
739 // {
740 //     struct modem *modem = fi->priv;
741 //     struct qmi_service *uim = uqmi_service_find(modem->qmi, QMI_SERVICE_UIM);
742 
743 //     /* FIXME: register for indication of removed uims
744 //      * - register_physical_slot_status_events
745 //      * - Physical Slot Status?
746 //      */
747 //     if (uim) {
748 //         modem_log(modem, LOGL_INFO, "Trying to query UIM for slot status.");
749 //         uqmi_service_send_simple(uim, qmi_set_uim_get_slot_status_request, uim_get_slot_status_cb, modem);
750 //         return;
751 //     }
752 
753 //     /* Retrieve it via DMS */
754 //     struct qmi_service *dms = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS);
755 //     if (dms) {
756 //         modem_log(modem, LOGL_INFO, "Trying to query UIM for IMSI.");
757 //         uqmi_service_send_simple(dms, qmi_set_dms_uim_get_imsi_request, dms_get_imsi_cb, modem);
758 //         return;
759 //     }
760 // }
761 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt