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