1 2 #include <assert.h> 3 4 #include "osmocom/fsm.h" 5 #include "osmocom/utils.h" 6 7 #include "qmi-enums-dms.h" 8 #include "qmi-errors.h" 9 #include "sim_fsm.h" 10 #include "talloc.h" 11 12 #include "qmi-struct.h" 13 #include "qmi-enums.h" 14 #include "qmi-message.h" 15 #include "qmi-enums-uim.h" 16 17 #include "uqmid.h" 18 #include "logging.h" 19 #include "utils.h" 20 21 #include "modem.h" 22 #include "modem_fsm.h" 23 #include "modem_tx.h" 24 #include "services.h" 25 #include "wwan.h" 26 27 #define S(x) (1 << (x)) 28 29 /* FIXME: if a service "vanished", abort/re-sync with backoff */ 30 /* Timeouts periods in seconds */ 31 #define T_GET_VERSION_S 5 32 #define T_SYNC_S 3 33 /* default timeout */ 34 #define T_DEFAULT_S 5 35 36 /* Timeout number */ 37 38 enum { 39 N_RESEND = 1, 40 N_FAILURE, 41 N_DESTROY, 42 }; 43 44 static const struct value_string modem_event_names[] = { 45 { MODEM_EV_REQ_START, "REQ_START" }, 46 { MODEM_EV_REQ_DESTROY, "REQ_DESTROY" }, 47 { MODEM_EV_REQ_CONFIGURED, "REQ_CONFIGURED"}, 48 { MODEM_EV_RX_SYNC, "RX_SYNC" }, 49 { MODEM_EV_RX_VERSION, "RX_VERSION" }, 50 { MODEM_EV_RX_MODEL, "RX_MODEL" }, 51 { MODEM_EV_RX_MANUFACTURER, "RX_MANUFACTURER" }, 52 { MODEM_EV_RX_REVISION, "RX_REVISION" }, 53 54 { MODEM_EV_RX_POWEROFF, "RX_POWEROFF" }, 55 { MODEM_EV_RX_POWERON, "RX_POWERON" }, 56 { MODEM_EV_RX_POWERSET, "RX_POWERSET" }, 57 58 { MODEM_EV_REQ_SIM_TERM, "RX_SIM_TERM" }, 59 { MODEM_EV_REQ_SIM_FAILURE, "RX_SIM_FAILURE" }, 60 { MODEM_EV_REQ_SIM_READY, "RX_SIM_READY" }, 61 62 { MODEM_EV_RX_GET_PROFILE_LIST, "RX_GET_PROFILE_LIST" }, 63 { MODEM_EV_RX_MODIFIED_PROFILE, "RX_MODIFIED_PROFILE" }, 64 { MODEM_EV_RX_CONFIGURED, "RX_CONFIGURED" }, 65 66 { MODEM_EV_RX_SEARCHING, "RX_SEARCHING" }, 67 { MODEM_EV_RX_UNREGISTERED, "RX_UNREGISTERED" }, 68 { MODEM_EV_RX_REGISTERED, "RX_REGISTERED" }, 69 70 { MODEM_EV_RX_SUBSCRIBED, "RX_SUBSCRIBED" }, 71 { MODEM_EV_RX_SUBSCRIBE_FAILED, "RX_SUBSCRIBE_FAILED" }, 72 73 { MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS, "RX_DISABLE_AUTOCONNECT_SUCCESS"}, 74 75 { MODEM_EV_RX_FAILED, "RX_FAILED" }, 76 { MODEM_EV_RX_SUCCEED, "RX_SUCCEED" }, 77 { 0, NULL } 78 }; 79 80 #define NAS_SERVICE_POLL_TIMEOUT_S 5 81 82 void modem_fsm_start(struct modem *modem) 83 { 84 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_REQ_START, NULL); 85 } 86 87 static void modem_st_unconfigured(struct osmo_fsm_inst *fi, uint32_t event, void *data) 88 { 89 switch (event) { 90 case MODEM_EV_REQ_START: 91 osmo_fsm_inst_state_chg(fi, MODEM_ST_RESYNC, T_SYNC_S, N_FAILURE); 92 break; 93 } 94 } 95 96 static void ctl_sync_request_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 97 { 98 struct modem *modem = req->cb_data; 99 int ret = 0; 100 101 /* transaction aborted or timedout */ 102 if (!msg) { 103 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 104 return; 105 } 106 107 ret = qmi_parse_ctl_sync_response(msg); 108 if (ret != QMI_PROTOCOL_ERROR_NONE) { 109 modem_log(modem, LOGL_ERROR, "Sync Request returned error %d", ret); 110 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 111 return; 112 } 113 114 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SYNC, NULL); 115 } 116 117 static void modem_st_resync_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 118 { 119 struct modem *modem = fi->priv; 120 struct qmi_service *ctl = uqmi_service_find(modem->qmi, QMI_SERVICE_CTL); 121 122 uqmi_service_send_simple(ctl, qmi_set_ctl_sync_request, ctl_sync_request_cb, modem); 123 } 124 125 static void modem_st_resync(struct osmo_fsm_inst *fi, uint32_t event, void *data) 126 { 127 osmo_fsm_inst_state_chg(fi, MODEM_ST_GET_VERSION, T_GET_VERSION_S, 0); 128 } 129 130 static void uqmid_modem_version_cb(struct qmi_service *ctl_service, struct qmi_request *req, struct qmi_msg *msg) 131 { 132 struct modem *modem = req->cb_data; 133 struct qmi_service *service; 134 uint8_t service_id; 135 uint16_t major, minor; 136 137 struct qmi_ctl_get_version_info_response res = {}; 138 qmi_parse_ctl_get_version_info_response(msg, &res); 139 140 for (int i = 0; i < res.data.service_list_n; i++) { 141 service_id = res.data.service_list[i].service; 142 major = res.data.service_list[i].major_version; 143 minor = res.data.service_list[i].minor_version; 144 145 service = uqmi_service_find_or_init(modem->qmi, service_id); 146 if (!service) 147 continue; 148 149 service->major = major; 150 service->minor = minor; 151 } 152 153 /* FIXME: create a list of required services and validate them */ 154 155 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_VERSION, NULL); 156 } 157 158 static void modem_st_get_version_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 159 { 160 struct modem *modem = fi->priv; 161 struct qmi_request *req = talloc_zero(modem->qmi->ctrl, struct qmi_request); 162 struct qmi_msg *msg = talloc_zero_size(req, 1024); 163 164 int ret = qmi_set_ctl_get_version_info_request(msg); 165 if (ret) { 166 LOG_ERROR("Failed to encode get version info"); 167 return; 168 } 169 170 req->msg = msg; 171 req->cb = uqmid_modem_version_cb; 172 req->cb_data = modem; 173 uqmi_service_send_msg(modem->qmi->ctrl, req); 174 } 175 176 static void modem_st_get_version(struct osmo_fsm_inst *fi, uint32_t event, void *data) 177 { 178 struct modem *modem = fi->priv; 179 180 switch (event) { 181 case MODEM_EV_RX_VERSION: 182 osmo_fsm_inst_dispatch(modem->sim.fi, SIM_EV_REQ_START, NULL); 183 osmo_fsm_inst_state_chg(fi, MODEM_ST_GET_MODEL, 0, 0); 184 break; 185 } 186 } 187 188 static void get_manuf_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 189 { 190 struct modem *modem = req->cb_data; 191 int ret = 0; 192 193 struct qmi_dms_get_manufacturer_response res = {}; 194 ret = qmi_parse_dms_get_manufacturer_response(msg, &res); 195 196 if (ret) { 197 /* FIXME: No manufacturer. Ignoring */ 198 modem_log(modem, LOGL_ERROR, "Failed to get a manufacturer."); 199 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MANUFACTURER, NULL); 200 return; 201 } 202 203 if (!res.data.manufacturer) { 204 /* FIXME: No manufacturer */ 205 modem_log(modem, LOGL_ERROR, "Got empty manufacturer."); 206 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MANUFACTURER, NULL); 207 return; 208 } 209 210 if (modem->manuf) 211 talloc_free(modem->manuf); 212 213 modem->manuf = talloc_strdup(modem, res.data.manufacturer); 214 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MANUFACTURER, NULL); 215 } 216 217 static void get_model_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 218 { 219 struct modem *modem = req->cb_data; 220 int ret = 0; 221 222 struct qmi_dms_get_model_response res = {}; 223 ret = qmi_parse_dms_get_model_response(msg, &res); 224 225 if (ret) { 226 /* FIXME: No model. Ignoring */ 227 modem_log(modem, LOGL_ERROR, "Failed to get a model."); 228 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MODEL, NULL); 229 return; 230 } 231 232 if (!res.data.model) { 233 /* FIXME: No model */ 234 modem_log(modem, LOGL_ERROR, "Got empty model."); 235 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MODEL, NULL); 236 return; 237 } 238 239 if (modem->model) 240 talloc_free(modem->model); 241 242 modem->model = talloc_strdup(modem, res.data.model); 243 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MODEL, NULL); 244 } 245 246 static void get_revision_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 247 { 248 struct modem *modem = req->cb_data; 249 int ret = 0; 250 251 struct qmi_dms_get_revision_response res = {}; 252 ret = qmi_parse_dms_get_revision_response(msg, &res); 253 254 if (ret) { 255 /* FIXME: No revision. Ignoring */ 256 modem_log(modem, LOGL_ERROR, "Failed to get a revision."); 257 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_REVISION, NULL); 258 return; 259 } 260 261 if (!res.data.revision) { 262 /* FIXME: No revision */ 263 modem_log(modem, LOGL_ERROR, "Got empty revision."); 264 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_REVISION, NULL); 265 return; 266 } 267 268 if (modem->rev) 269 talloc_free(modem->rev); 270 271 modem->rev = talloc_strdup(modem, res.data.revision); 272 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_REVISION, NULL); 273 } 274 275 static void get_ids_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 276 { 277 struct modem *modem = req->cb_data; 278 int ret = 0; 279 280 struct qmi_dms_get_ids_response res = {}; 281 ret = qmi_parse_dms_get_ids_response(msg, &res); 282 283 if (ret) { 284 /* FIXME: No revision. Ignoring */ 285 modem_log(modem, LOGL_ERROR, "Failed to get a IMEI."); 286 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_IMEI, NULL); 287 return; 288 } 289 290 TALLOC_FREE(modem->meid); 291 TALLOC_FREE(modem->imei); 292 TALLOC_FREE(modem->imeisv); 293 294 if (res.data.meid) 295 modem->meid = talloc_strdup(modem, res.data.meid); 296 297 if (res.data.imei) 298 modem->imei = talloc_strdup(modem, res.data.imei); 299 300 if (res.data.imei_software_version) 301 modem->imeisv = talloc_strdup(modem, res.data.imei_software_version); 302 303 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_IMEI, NULL); 304 } 305 306 static void modem_st_get_model_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 307 { 308 struct modem *modem = fi->priv; 309 struct qmi_service *service = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS); 310 311 if (!service) { 312 modem_log(modem, LOGL_ERROR, "DMS service unavailable"); 313 /* FIXME: fail to perm failure */ 314 } 315 316 uqmi_service_send_simple(service, qmi_set_dms_get_model_request, get_model_cb, modem); 317 } 318 319 static void modem_st_get_model(struct osmo_fsm_inst *fi, uint32_t event, void *data) 320 { 321 struct modem *modem = fi->priv; 322 struct qmi_service *service = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS); 323 324 if (!service) { 325 modem_log(modem, LOGL_ERROR, "DMS service unavailable"); 326 /* FIXME: fail to perm failure */ 327 } 328 329 /* FIXME: enable timeout and check if enough information has been gathered */ 330 331 switch (event) { 332 case MODEM_EV_RX_MODEL: 333 uqmi_service_send_simple(service, qmi_set_dms_get_manufacturer_request, get_manuf_cb, modem); 334 break; 335 case MODEM_EV_RX_MANUFACTURER: 336 uqmi_service_send_simple(service, qmi_set_dms_get_revision_request, get_revision_cb, modem); 337 break; 338 case MODEM_EV_RX_REVISION: 339 uqmi_service_send_simple(service, qmi_set_dms_get_ids_request, get_ids_cb, modem); 340 break; 341 case MODEM_EV_RX_IMEI: 342 osmo_fsm_inst_state_chg(fi, MODEM_ST_POWEROFF, 3, 0); 343 break; 344 } 345 } 346 347 static void dms_get_operating_mode_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 348 { 349 struct modem *modem = req->cb_data; 350 int ret = 0; 351 struct qmi_dms_get_operating_mode_response res = {}; 352 353 if (req->ret) { 354 modem_log(modem, LOGL_INFO, "Failed to get operating mode. Status %d/%s.", req->ret, 355 qmi_get_error_str(req->ret)); 356 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 357 return; 358 } 359 360 ret = qmi_parse_dms_get_operating_mode_response(msg, &res); 361 if (ret) { 362 modem_log(modem, LOGL_INFO, "Failed to get operating mode. Failed to parse message"); 363 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 364 return; 365 } 366 367 if (!res.set.mode) { 368 modem_log(modem, LOGL_INFO, "Failed to get operating mode. Failed to parse message"); 369 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 370 } 371 372 modem_log(modem, LOGL_INFO, "Current in operating mode %d", res.data.mode); 373 switch (res.data.mode) { 374 case QMI_DMS_OPERATING_MODE_ONLINE: 375 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_POWERON, (void *)(long)res.data.mode); 376 break; 377 case QMI_DMS_OPERATING_MODE_LOW_POWER: 378 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_POWEROFF, (void *)(long)res.data.mode); 379 break; 380 default: 381 modem_log(modem, LOGL_ERROR, "Unhandled power mode! (%d) Trying to power off", res.data.mode); 382 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_POWERON, (void *)(long)res.data.mode); 383 } 384 } 385 386 static void dms_set_operating_mode_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 387 { 388 struct modem *modem = req->cb_data; 389 if (req->ret) { 390 modem_log(modem, LOGL_INFO, "Failed to set operating mode. Status %d/%s.", req->ret, 391 qmi_get_error_str(req->ret)); 392 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 393 return; 394 } 395 396 /* TODO: we should request the state again to validate the modem is following our request. */ 397 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_POWERSET, 0); 398 } 399 400 static void modem_st_poweroff_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 401 { 402 struct modem *modem = fi->priv; 403 struct qmi_service *dms = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS); 404 405 /* FIXME: abort when DMS doesn't exist */ 406 if (dms) 407 uqmi_service_send_simple(dms, qmi_set_dms_get_operating_mode_request, dms_get_operating_mode_cb, modem); 408 } 409 static void modem_st_poweroff(struct osmo_fsm_inst *fi, uint32_t event, void *data) 410 { 411 struct modem *modem = fi->priv; 412 struct qmi_service *dms = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS); 413 414 switch (event) { 415 case MODEM_EV_RX_POWERON: 416 tx_dms_set_operating_mode(modem, dms, QMI_DMS_OPERATING_MODE_LOW_POWER, dms_set_operating_mode_cb); 417 break; 418 case MODEM_EV_RX_POWERSET: 419 uqmi_service_send_simple(dms, qmi_set_dms_get_operating_mode_request, dms_get_operating_mode_cb, modem); 420 break; 421 case MODEM_EV_RX_POWEROFF: 422 if (modem->config.configured && !modem->state.error) 423 osmo_fsm_inst_state_chg(fi, MODEM_ST_WAIT_UIM, 0, 0); 424 else /* stop timer and wait for the user to continue */ 425 osmo_timer_del(&fi->timer); 426 break; 427 case MODEM_EV_REQ_CONFIGURED: /* when the modem reach this state, but isn't yet configured, wait for the config */ 428 osmo_fsm_inst_state_chg(fi, MODEM_ST_WAIT_UIM, 0, 0); 429 break; 430 } 431 } 432 433 static void modem_st_wait_uim_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 434 { 435 struct modem *modem = fi->priv; 436 437 if (modem->sim.fi->state == SIM_ST_READY) 438 osmo_fsm_inst_state_chg(fi, MODEM_ST_CONFIGURE_MODEM, 0, 0); 439 } 440 441 static void modem_st_wait_uim(struct osmo_fsm_inst *fi, uint32_t event, void *data) 442 { 443 switch (event) { 444 case MODEM_EV_REQ_SIM_READY: 445 osmo_fsm_inst_state_chg(fi, MODEM_ST_CONFIGURE_MODEM, 0, 0); 446 break; 447 default: 448 break; 449 } 450 } 451 452 static void wds_modify_profile_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 453 { 454 struct modem *modem = req->cb_data; 455 struct qmi_wds_modify_profile_response res = {}; 456 long err = 1; 457 int ret; 458 if (req->ret) { 459 modem_log(modem, LOGL_INFO, "Failed to modify profile list. Status %d/%s.", req->ret, 460 qmi_get_error_str(req->ret)); 461 /* FIXME: add extended profile error */ 462 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MODIFIED_PROFILE, (void *)err); 463 return; 464 } 465 466 ret = qmi_parse_wds_modify_profile_response(msg, &res); 467 if (ret) { 468 modem_log(modem, LOGL_INFO, "Failed to modify profile list. Failed to parse message"); 469 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MODIFIED_PROFILE, (void *)err); 470 return; 471 } 472 473 err = 0; 474 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_MODIFIED_PROFILE, (void *)err); 475 } 476 477 static void wds_get_profile_list_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 478 { 479 struct modem *modem = req->cb_data; 480 struct qmi_wds_get_profile_list_response res = {}; 481 long err = 1; 482 int ret; 483 if (req->ret) { 484 modem_log(modem, LOGL_INFO, "Failed to get profile list. Status %d/%s.", req->ret, 485 qmi_get_error_str(req->ret)); 486 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 487 return; 488 } 489 490 ret = qmi_parse_wds_get_profile_list_response(msg, &res); 491 if (ret) { 492 modem_log(modem, LOGL_INFO, "Failed to get operating mode. Failed to parse message"); 493 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 494 return; 495 } 496 497 for (int i = 0; i < res.data.profile_list_n; i++) { 498 uint8_t type = res.data.profile_list[i].profile_type; 499 uint8_t idx = res.data.profile_list[i].profile_index; 500 /* const char *name = res.data.profile_list[i].profile_name; */ 501 if (type != QMI_WDS_PROFILE_TYPE_3GPP) 502 continue; 503 504 err = 0; 505 /* we're taking the first one and ignoring the rest for now */ 506 modem_log(modem, LOGL_INFO, "Found profile id %d", idx); 507 modem->qmi->wds.profile_id = idx; 508 modem->qmi->wds.valid = 1; 509 } 510 511 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_GET_PROFILE_LIST, (void *)err); 512 } 513 514 static void modem_st_configure_modem_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 515 { 516 struct modem *modem = fi->priv; 517 struct qmi_service *wds = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); 518 519 switch (modem->config.pdp_type) { 520 case QMI_WDS_PDP_TYPE_IPV4: 521 modem->qmi->wds.ip_family = QMI_WDS_IP_FAMILY_IPV4; 522 break; 523 /* FIXME: add support for IPV4/IPV6 dual stack */ 524 case QMI_WDS_PDP_TYPE_IPV4_OR_IPV6: 525 case QMI_WDS_PDP_TYPE_IPV6: 526 modem->qmi->wds.ip_family = QMI_WDS_IP_FAMILY_IPV6; 527 break; 528 default: 529 modem->qmi->wds.ip_family = QMI_WDS_IP_FAMILY_UNSPECIFIED; 530 break; 531 } 532 533 tx_wds_get_profile_list(modem, wds, wds_get_profile_list_cb); 534 } 535 536 static void modem_st_configure_modem(struct osmo_fsm_inst *fi, uint32_t event, void *data) 537 { 538 struct modem *modem = fi->priv; 539 struct qmi_service *wds = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); 540 541 /* get Profile list, if no Profile, 542 * create one () 543 * modify profile () */ 544 545 switch (event) { 546 case MODEM_EV_RX_GET_PROFILE_LIST: 547 /* err */ 548 if (data) { 549 /* failed to get profile list/generate a new profile */ 550 } else { 551 tx_wds_modify_profile(modem, wds, wds_modify_profile_cb, modem->qmi->wds.profile_id, 552 modem->config.apn, modem->config.pdp_type, modem->config.username, 553 modem->config.password); 554 } 555 break; 556 case MODEM_EV_RX_MODIFIED_PROFILE: 557 /* configure the physical kernel interface */ 558 osmo_fsm_inst_state_chg(fi, MODEM_ST_CONFIGURE_KERNEL, T_DEFAULT_S, 0); 559 break; 560 } 561 /* TODO: check if this is the default profile! */ 562 } 563 564 static void wda_set_data_format_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 565 { 566 struct modem *modem = req->cb_data; 567 int ret = 0; 568 struct qmi_wda_set_data_format_response res = {}; 569 570 if (req->ret) { 571 modem_log(modem, LOGL_ERROR, "Failed to set data format. Status %d/%s.", req->ret, 572 qmi_get_error_str(req->ret)); 573 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 574 return; 575 } 576 577 ret = qmi_parse_wda_set_data_format_response(msg, &res); 578 if (ret) { 579 modem_log(modem, LOGL_ERROR, "Failed to set data format. Failed to parse message"); 580 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 581 return; 582 } 583 584 if (!res.set.link_layer_protocol) { 585 modem_log(modem, LOGL_ERROR, "Failed to set data format. Link layer protocol TLV missing"); 586 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 587 return; 588 } 589 590 /* currently uqmid only supports raw-ip */ 591 if (res.data.link_layer_protocol != QMI_WDA_LINK_LAYER_PROTOCOL_RAW_IP) { 592 modem_log(modem, LOGL_ERROR, "Failed to set data format. Link layer protocol TLV missing"); 593 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 594 return; 595 } 596 597 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SUCCEED, (void *)(long)msg->svc.message); 598 } 599 600 /* Configure the kernel network interface */ 601 static void modem_st_configure_kernel_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 602 { 603 struct modem *modem = fi->priv; 604 struct qmi_service *wda = uqmi_service_find(modem->qmi, QMI_SERVICE_WDA); 605 606 if (modem->wwan.skip_configuration) { 607 tx_wda_set_data_format(modem, wda, wda_set_data_format_cb); 608 return; 609 } 610 611 /* when using raw-ip later with QMAP support, ensure the mtu is at the maximum of the USB transfer */ 612 int ret = wwan_refresh_device(modem); 613 if (ret) { 614 modem_log(modem, LOGL_ERROR, "Failed to get wwan device. err %d", ret); 615 return; 616 } 617 618 ret = wwan_ifupdown(modem->wwan.dev, 0); 619 if (ret) { 620 modem_log(modem, LOGL_ERROR, "Failed to bring down wwan device. err %d", ret); 621 return; 622 } 623 624 modem->wwan.config.pass_through = false; 625 modem->wwan.config.raw_ip = false; 626 ret = wwan_set_configuration(modem->wwan.sysfs, &modem->wwan.config); 627 if (ret) { 628 modem_log(modem, LOGL_ERROR, "Failed to set qmi configuration. err %d", ret); 629 return; 630 } 631 632 ret = wwan_set_mtu(modem->wwan.dev, 1500); 633 if (ret) { 634 modem_log(modem, LOGL_ERROR, "Failed to set mtu. err %d", ret); 635 return; 636 } 637 638 modem->wwan.config.pass_through = false; 639 modem->wwan.config.raw_ip = true; 640 ret = wwan_set_configuration(modem->wwan.sysfs, &modem->wwan.config); 641 if (ret) { 642 modem_log(modem, LOGL_ERROR, "Failed to set qmi configuration (final). err %d", ret); 643 return; 644 } 645 646 ret = wwan_ifupdown(modem->wwan.dev, 1); 647 if (ret) { 648 modem_log(modem, LOGL_ERROR, "Failed to bring up wwan device. err %d", ret); 649 return; 650 } 651 652 tx_wda_set_data_format(modem, wda, wda_set_data_format_cb); 653 } 654 655 656 static void modem_st_configure_kernel(struct osmo_fsm_inst *fi, uint32_t event, void *data) 657 { 658 long msg = (long) data; 659 660 switch (event) { 661 case MODEM_EV_RX_SUCCEED: 662 /* Wrong message handler */ 663 /* TODO: generate and use WDA Message defines */ 664 if (msg != 0x0020) 665 break; 666 667 osmo_fsm_inst_state_chg(fi, MODEM_ST_POWERON, 0, 0); 668 break; 669 } 670 } 671 672 static void modem_st_poweron_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 673 { 674 struct modem *modem = fi->priv; 675 struct qmi_service *dms = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS); 676 677 /* FIXME: abort when DMS doesn't exist */ 678 if (dms) 679 uqmi_service_send_simple(dms, qmi_set_dms_get_operating_mode_request, dms_get_operating_mode_cb, modem); 680 } 681 static void modem_st_poweron(struct osmo_fsm_inst *fi, uint32_t event, void *data) 682 { 683 struct modem *modem = fi->priv; 684 struct qmi_service *dms = uqmi_service_find(modem->qmi, QMI_SERVICE_DMS); 685 686 switch (event) { 687 case MODEM_EV_RX_POWEROFF: 688 tx_dms_set_operating_mode(modem, dms, QMI_DMS_OPERATING_MODE_ONLINE, dms_set_operating_mode_cb); 689 break; 690 case MODEM_EV_RX_POWERSET: 691 case MODEM_EV_RX_POWERON: 692 osmo_fsm_inst_state_chg(fi, MODEM_ST_NETSEARCH, NAS_SERVICE_POLL_TIMEOUT_S, 0); 693 break; 694 } 695 } 696 697 static void subscribe_result_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 698 { 699 struct modem *modem = req->cb_data; 700 if (req->ret) { 701 modem_log(modem, LOGL_INFO, "Service %d: Subscribe check failed with %d/%s", service->service, req->ret, 702 qmi_get_error_str(req->ret)); 703 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SUBSCRIBE_FAILED, 704 (void *)(long)le32_to_cpu(msg->svc.message)); 705 return; 706 } 707 708 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SUBSCRIBED, (void *)(long)le32_to_cpu(msg->svc.message)); 709 } 710 711 static void get_serving_system_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 712 { 713 struct modem *modem = req->cb_data; 714 struct qmi_nas_get_serving_system_response res = {}; 715 716 if (req->ret) { 717 modem_log(modem, LOGL_INFO, "Failed to get system info. Status %d/%s", req->ret, 718 qmi_get_error_str(req->ret)); 719 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)(long)1); 720 return; 721 } 722 723 int ret = qmi_parse_nas_get_serving_system_response(msg, &res); 724 if (ret) { 725 modem_log(modem, LOGL_ERROR, "Failed to decode serving system response"); 726 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)(long)1); 727 return; 728 } 729 730 if (!res.set.serving_system) { 731 modem_log(modem, LOGL_ERROR, "No serving system in get serving system"); 732 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)(long)1); 733 return; 734 } 735 736 modem_log(modem, LOGL_INFO, "Network registration state %d", res.data.serving_system.registration_state); 737 738 switch (res.data.serving_system.registration_state) { 739 case QMI_NAS_REGISTRATION_STATE_REGISTERED: 740 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_REGISTERED, NULL); 741 return; 742 case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED: 743 case QMI_NAS_REGISTRATION_STATE_UNKNOWN: 744 case QMI_NAS_REGISTRATION_STATE_REGISTRATION_DENIED: 745 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_UNREGISTERED, NULL); 746 return; 747 case QMI_NAS_REGISTRATION_STATE_NOT_REGISTERED_SEARCHING: 748 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SEARCHING, NULL); 749 return; 750 } 751 } 752 753 static void nas_force_search_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 754 { 755 struct modem *modem = req->cb_data; 756 if (req->ret) { 757 modem_log(modem, LOGL_INFO, "Failed to force a network search. Status %d/%s", req->ret, 758 qmi_get_error_str(req->ret)); 759 /* FIXME: charge timer */ 760 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 761 return; 762 } 763 } 764 765 static void modem_st_netsearch_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 766 { 767 struct modem *modem = fi->priv; 768 struct qmi_service *nas = uqmi_service_find(modem->qmi, QMI_SERVICE_NAS); 769 tx_nas_subscribe_nas_events(modem, nas, 1, subscribe_result_cb); 770 } 771 772 static void modem_st_netsearch(struct osmo_fsm_inst *fi, uint32_t event, void *data) 773 { 774 /* TODO: register to internal indications */ 775 struct modem *modem = fi->priv; 776 struct qmi_service *nas = uqmi_service_find(modem->qmi, QMI_SERVICE_NAS); 777 778 switch (event) { 779 case MODEM_EV_RX_REGISTERED: 780 osmo_fsm_inst_state_chg(fi, MODEM_ST_REGISTERED, 0, 0); 781 break; 782 case MODEM_EV_RX_FAILED: 783 osmo_timer_schedule(&fi->timer, 5, 0); 784 break; 785 case MODEM_EV_RX_SUBSCRIBED: 786 case MODEM_EV_RX_SUBSCRIBE_FAILED: 787 uqmi_service_send_simple(nas, qmi_set_nas_get_serving_system_request, get_serving_system_cb, modem); 788 break; 789 case MODEM_EV_RX_UNREGISTERED: 790 modem_log(modem, LOGL_INFO, "Start network search."); 791 uqmi_service_send_simple(nas, qmi_set_nas_force_network_search_request, nas_force_search_cb, modem); 792 break; 793 } 794 } 795 796 static void modem_st_registered_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 797 { 798 osmo_fsm_inst_state_chg(fi, MODEM_ST_START_IFACE, 5, 0); 799 } 800 static void modem_st_registered(struct osmo_fsm_inst *fi, uint32_t event, void *data) 801 { 802 } 803 804 static void wds_start_network_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 805 { 806 struct modem *modem = req->cb_data; 807 struct qmi_wds_start_network_response res = {}; 808 long err = 1; 809 int ret; 810 811 ret = qmi_parse_wds_start_network_response(msg, &res); 812 if (ret) { 813 modem_log(modem, LOGL_INFO, "Failed to get operating mode. Failed to parse message"); 814 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 815 return; 816 } 817 818 /* to get error causes */ 819 err = ret = req->ret; 820 if (ret && ret == QMI_PROTOCOL_ERROR_NO_EFFECT) { 821 modem_log(modem, LOGL_INFO, "Start network return NO_EFFECT. Trying to continue"); 822 } else if (ret) { 823 modem_log(modem, LOGL_INFO, "Failed start network. QMI Status %d/%s.", req->ret, 824 qmi_get_error_str(req->ret)); 825 if (res.set.call_end_reason) 826 modem_log(modem, LOGL_INFO, "Call End Reason %x", res.data.call_end_reason); 827 828 if (res.set.verbose_call_end_reason) { 829 modem_log(modem, LOGL_INFO, "Verbose End Reason type %x/reason %x", 830 res.data.verbose_call_end_reason.type, res.data.verbose_call_end_reason.reason); 831 } 832 833 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)(long)req->ret); 834 return; 835 } 836 837 if (res.set.packet_data_handle) { 838 modem->qmi->wds.packet_handle = res.data.packet_data_handle; 839 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SUCCEED, (void *)err); 840 } else { 841 modem_log(modem, LOGL_INFO, "No packet data handle. Suspicious..."); 842 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)err); 843 } 844 } 845 846 static void 847 wds_stop_network_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 848 { 849 struct modem *modem = req->cb_data; 850 int ret; 851 852 ret = qmi_parse_wds_stop_network_response(msg); 853 if (ret) { 854 modem_log(modem, LOGL_INFO, "Failed to stop network."); 855 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 856 return; 857 } 858 859 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS, NULL); 860 } 861 862 static void modem_st_start_iface_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 863 { 864 struct modem *modem = fi->priv; 865 struct qmi_service *wds = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); 866 867 fi->N = 0; 868 tx_wds_start_network(modem, wds, wds_start_network_cb, modem->qmi->wds.profile_id, modem->qmi->wds.ip_family); 869 } 870 static void modem_st_start_iface(struct osmo_fsm_inst *fi, uint32_t event, void *data) 871 { 872 struct modem *modem = fi->priv; 873 long reason; 874 bool disable_autoconnect = true; 875 struct qmi_service *wds = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); 876 /* FIXME: ensure essential services "can't" disappear or abort the FSM nicely */ 877 assert(wds); 878 879 switch (event) { 880 case MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS: 881 tx_wds_start_network(modem, wds, wds_start_network_cb, modem->qmi->wds.profile_id, modem->qmi->wds.ip_family); 882 break; 883 case MODEM_EV_RX_FAILED: 884 reason = (long) data; 885 switch (reason) { 886 case QMI_PROTOCOL_ERROR_CALL_FAILED: 887 fi->T = N_RESEND; 888 break; 889 case QMI_PROTOCOL_ERROR_NO_EFFECT: 890 /* No effect means it already started a connection, 891 * but we didn't got packet_data_handle out of it. 892 */ 893 fi->N++; 894 tx_wds_stop_network(modem, wds, wds_stop_network_cb, 0xffffffff, &disable_autoconnect); 895 break; 896 default: 897 uqmid_modem_set_error(modem, "Start Iface/Network failed!"); 898 osmo_fsm_inst_state_chg(fi, MODEM_ST_POWEROFF, 0, 0); 899 break; 900 } 901 break; 902 case MODEM_EV_RX_SUCCEED: 903 osmo_fsm_inst_state_chg(fi, MODEM_ST_LIVE, 0, 0); 904 break; 905 } 906 } 907 908 static void ipv4_to_sockaddr(const uint32_t wds_ip, struct sockaddr_in *addr) 909 { 910 memset(addr, 0, sizeof(*addr)); 911 addr->sin_family = AF_INET; 912 addr->sin_addr.s_addr = htonl(wds_ip); 913 } 914 915 static void ipv6_to_sockaddr(const uint16_t *wds_ip6, struct sockaddr_in6 *addr) 916 { 917 memset(addr, 0, sizeof(*addr)); 918 addr->sin6_family = AF_INET6; 919 memcpy(&addr->sin6_addr, wds_ip6, sizeof(struct in6_addr)); 920 } 921 922 static void wds_get_current_settings_cb(struct qmi_service *service, struct qmi_request *req, struct qmi_msg *msg) 923 { 924 struct modem *modem = req->cb_data; 925 struct qmi_wds_get_current_settings_response res = {}; 926 int ret; 927 928 ret = qmi_parse_wds_get_current_settings_response(msg, &res); 929 if (ret) { 930 modem_log(modem, LOGL_INFO, "Failed to get current settings. Failed to parse message"); 931 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, NULL); 932 return; 933 } 934 935 if (!res.set.ip_family) { 936 modem_log(modem, LOGL_ERROR, "Modem didn't include ip family"); 937 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)1); 938 } 939 940 memset(&modem->brearer.dns1, 0, sizeof(modem->brearer.dns1)); 941 memset(&modem->brearer.dns2, 0, sizeof(modem->brearer.dns2)); 942 943 switch (res.data.ip_family) { 944 case QMI_WDS_IP_FAMILY_IPV4: 945 memset(&modem->brearer.v4_addr, 0, sizeof(modem->brearer.v4_addr)); 946 memset(&modem->brearer.v4_netmask, 0, sizeof(modem->brearer.v4_netmask)); 947 memset(&modem->brearer.v4_gateway, 0, sizeof(modem->brearer.v4_gateway)); 948 949 if (!res.set.ipv4_address) { 950 modem_log(modem, LOGL_ERROR, "Modem didn't include IPv4 Address."); 951 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)2); 952 } 953 ipv4_to_sockaddr(res.data.ipv4_address, &modem->brearer.v4_addr); 954 955 /* Still unsure why there is a this subnet mask. maybe natt'ed by the modem? */ 956 if (res.set.ipv4_gateway_subnet_mask) { 957 ipv4_to_sockaddr(res.data.ipv4_gateway_subnet_mask, 958 (struct sockaddr_in *)&modem->brearer.v4_netmask); 959 } 960 961 if (res.set.ipv4_gateway_address) { 962 ipv4_to_sockaddr(res.data.ipv4_gateway_address, 963 (struct sockaddr_in *)&modem->brearer.v4_gateway); 964 } 965 966 if (res.set.primary_ipv4_dns_address) { 967 ipv4_to_sockaddr(res.data.primary_ipv4_dns_address, (struct sockaddr_in *)&modem->brearer.dns1); 968 } 969 970 if (res.set.secondary_ipv4_dns_address) { 971 ipv4_to_sockaddr(res.data.secondary_ipv4_dns_address, 972 (struct sockaddr_in *)&modem->brearer.dns2); 973 } 974 break; 975 case QMI_WDS_IP_FAMILY_IPV6: 976 if (!res.set.ipv6_address) { 977 modem_log(modem, LOGL_ERROR, "Modem didn't include IPv6 Address."); 978 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)3); 979 } 980 981 if (res.set.ipv6_primary_dns_address) { 982 ipv6_to_sockaddr(res.data.ipv6_primary_dns_address, 983 (struct sockaddr_in6 *)&modem->brearer.dns1); 984 } 985 986 if (res.set.ipv6_secondary_dns_address) { 987 ipv6_to_sockaddr(res.data.ipv6_secondary_dns_address, 988 (struct sockaddr_in6 *)&modem->brearer.dns2); 989 } 990 991 break; 992 default: 993 modem_log(modem, LOGL_ERROR, "Modem reported an unknown ip_family %d.", res.data.ip_family); 994 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_FAILED, (void *)4); 995 break; 996 } 997 998 osmo_fsm_inst_dispatch(modem->fi, MODEM_EV_RX_SUCCEED, NULL); 999 } 1000 1001 static void modem_st_live_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 1002 { 1003 struct modem *modem = fi->priv; 1004 struct qmi_service *wds = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); 1005 1006 tx_wds_get_current_settings(modem, wds, wds_get_current_settings_cb); 1007 /* TODO: register to indications */ 1008 } 1009 1010 static void modem_st_live(struct osmo_fsm_inst *fi, uint32_t event, void *data) 1011 { 1012 switch (event) { 1013 case MODEM_EV_RX_FAILED: 1014 break; 1015 case MODEM_EV_RX_SUCCEED: 1016 break; 1017 } 1018 } 1019 1020 static void modem_st_failed(struct osmo_fsm_inst *fi, uint32_t event, void *data) 1021 { 1022 } 1023 1024 static void modem_st_destroy_onenter(struct osmo_fsm_inst *fi, uint32_t old_state) 1025 { 1026 struct modem *modem = fi->priv; 1027 1028 /* FIXME: try to close the network, poweroff the modem ? */ 1029 qmi_device_close(modem->qmi, 5000); 1030 } 1031 static void modem_st_destroy(struct osmo_fsm_inst *fi, uint32_t event, void *data) 1032 { 1033 } 1034 1035 static int modem_fsm_timer_cb(struct osmo_fsm_inst *fi) 1036 { 1037 struct modem *modem = fi->priv; 1038 struct qmi_service *service; 1039 1040 switch (fi->state) { 1041 case MODEM_ST_NETSEARCH: 1042 service = uqmi_service_find(modem->qmi, QMI_SERVICE_NAS); 1043 if (!service) { 1044 modem_log(modem, LOGL_ERROR, "NAS service doesn't exist"); 1045 return 1; 1046 } 1047 uqmi_service_send_simple(service, qmi_set_nas_get_serving_system_request, get_serving_system_cb, modem); 1048 osmo_timer_schedule(&fi->timer, NAS_SERVICE_POLL_TIMEOUT_S, 0); 1049 break; 1050 case MODEM_ST_START_IFACE: 1051 switch (fi->T) { 1052 case N_RESEND: 1053 /* resend the packet */ 1054 service = uqmi_service_find(modem->qmi, QMI_SERVICE_WDS); 1055 if (!service) { 1056 modem_log(modem, LOGL_ERROR, "WDS service doesn't exist"); 1057 return 1; 1058 } 1059 tx_wds_start_network(modem, service, wds_start_network_cb, modem->qmi->wds.profile_id, 1060 modem->qmi->wds.ip_family); 1061 osmo_timer_schedule(&fi->timer, 5, 0); 1062 break; 1063 default: 1064 /* we timedout ! No answer? */ 1065 modem_log(modem, LOGL_ERROR, "WDS: Couldn't start the interface!"); 1066 /* TODO: enter failure state */ 1067 break; 1068 } 1069 break; 1070 default: 1071 switch (fi->T) { 1072 case N_FAILURE: 1073 modem_log(modem, LOGL_ERROR, "State timedout. Entering failure state"); 1074 osmo_fsm_inst_state_chg(fi, MODEM_ST_FAILED, 0, 0); 1075 break; 1076 } 1077 1078 break; 1079 } 1080 1081 return 0; 1082 } 1083 1084 static void modem_fsm_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data) 1085 { 1086 switch (event) { 1087 case MODEM_EV_REQ_DESTROY: 1088 osmo_fsm_inst_state_chg(fi, MODEM_ST_DESTROY, 0, 0); 1089 break; 1090 } 1091 } 1092 1093 static const struct osmo_fsm_state modem_states[] = { 1094 [MODEM_ST_IDLE] = { 1095 .in_event_mask = S(MODEM_EV_REQ_START), 1096 .out_state_mask = S(MODEM_ST_RESYNC) | S(MODEM_ST_DESTROY), 1097 .name = "UNCONFIGURED", 1098 .action = modem_st_unconfigured, 1099 }, 1100 [MODEM_ST_RESYNC] = { 1101 .in_event_mask = S(MODEM_EV_RX_SYNC), 1102 .out_state_mask = S(MODEM_ST_GET_VERSION) 1103 | S(MODEM_ST_FAILED) 1104 | S(MODEM_ST_DESTROY), 1105 .name = "RESYNC", 1106 .action = modem_st_resync, 1107 .onenter = modem_st_resync_onenter, 1108 }, 1109 [MODEM_ST_GET_VERSION] = { 1110 .in_event_mask = S(MODEM_EV_RX_VERSION), 1111 .out_state_mask = S(MODEM_ST_GET_MODEL) | S(MODEM_ST_DESTROY), 1112 .name = "GET_VERSION", 1113 .action = modem_st_get_version, 1114 .onenter = modem_st_get_version_onenter, 1115 }, 1116 [MODEM_ST_GET_MODEL] = { 1117 .in_event_mask = S(MODEM_EV_RX_MODEL) | 1118 S(MODEM_EV_RX_MANUFACTURER) | 1119 S(MODEM_EV_RX_REVISION) | 1120 S(MODEM_EV_RX_IMEI), 1121 .out_state_mask = S(MODEM_ST_POWEROFF) | S(MODEM_ST_DESTROY), 1122 .name = "GET_MODEL", 1123 .action = modem_st_get_model, 1124 .onenter = modem_st_get_model_onenter, 1125 }, 1126 [MODEM_ST_POWEROFF] = { 1127 .in_event_mask = S(MODEM_EV_RX_POWEROFF) 1128 | S(MODEM_EV_RX_POWERON) 1129 | S(MODEM_EV_RX_POWERSET) 1130 | S(MODEM_EV_REQ_CONFIGURED), 1131 .out_state_mask = S(MODEM_ST_CONFIGURE_MODEM) 1132 | S(MODEM_ST_DESTROY) 1133 | S(MODEM_ST_WAIT_UIM), 1134 .name = "POWEROFF", 1135 .action = modem_st_poweroff, 1136 .onenter = modem_st_poweroff_onenter, 1137 }, 1138 [MODEM_ST_WAIT_UIM] = { 1139 .in_event_mask = S(MODEM_EV_REQ_SIM_READY), 1140 .out_state_mask = S(MODEM_ST_CONFIGURE_MODEM) | S(MODEM_ST_DESTROY), 1141 .name = "WAIT_UIM", 1142 .action = modem_st_wait_uim, 1143 .onenter = modem_st_wait_uim_onenter, 1144 }, 1145 [MODEM_ST_CONFIGURE_MODEM] = { 1146 .in_event_mask = S(MODEM_EV_RX_CONFIGURED) 1147 | S(MODEM_EV_RX_GET_PROFILE_LIST) 1148 | S(MODEM_EV_RX_MODIFIED_PROFILE), 1149 .out_state_mask = S(MODEM_ST_CONFIGURE_KERNEL) | S(MODEM_ST_DESTROY), 1150 .name = "CONFIGURE_MODEM", 1151 .action = modem_st_configure_modem, 1152 .onenter = modem_st_configure_modem_onenter, 1153 }, 1154 [MODEM_ST_CONFIGURE_KERNEL] = { 1155 .in_event_mask = S(MODEM_EV_RX_SUCCEED), 1156 .out_state_mask = S(MODEM_ST_POWERON) | S(MODEM_ST_DESTROY), 1157 .name = "CONFIGURE_KERNEL", 1158 .action = modem_st_configure_kernel, 1159 .onenter = modem_st_configure_kernel_onenter, 1160 }, 1161 [MODEM_ST_POWERON] = { 1162 .in_event_mask = S(MODEM_EV_RX_POWEROFF) 1163 | S(MODEM_EV_RX_POWERON) 1164 | S(MODEM_EV_RX_POWERSET), 1165 .out_state_mask = S(MODEM_ST_NETSEARCH) | S(MODEM_ST_DESTROY), 1166 .name = "POWERON", 1167 .action = modem_st_poweron, 1168 .onenter = modem_st_poweron_onenter, 1169 }, 1170 [MODEM_ST_NETSEARCH] = { 1171 .in_event_mask = S(MODEM_EV_RX_REGISTERED) 1172 | S(MODEM_EV_RX_UNREGISTERED) 1173 | S(MODEM_EV_RX_SEARCHING) 1174 | S(MODEM_EV_RX_FAILED) 1175 | S(MODEM_EV_RX_SUBSCRIBED) 1176 | S(MODEM_EV_RX_SUBSCRIBE_FAILED), 1177 .out_state_mask = S(MODEM_ST_REGISTERED) | S(MODEM_ST_DESTROY), 1178 .name = "NETSEARCH", 1179 .action = modem_st_netsearch, 1180 .onenter = modem_st_netsearch_onenter, 1181 }, 1182 [MODEM_ST_REGISTERED] = { 1183 .in_event_mask = 0, 1184 .out_state_mask = S(MODEM_ST_START_IFACE) | S(MODEM_ST_DESTROY), 1185 .name = "REGISTERED", 1186 .action = modem_st_registered, 1187 .onenter = modem_st_registered_onenter, 1188 }, 1189 [MODEM_ST_START_IFACE] = { 1190 .in_event_mask = S(MODEM_EV_RX_SUCCEED) 1191 | S(MODEM_EV_RX_FAILED) 1192 | S(MODEM_EV_RX_DISABLE_AUTOCONNECT_SUCCESS), 1193 .out_state_mask = S(MODEM_ST_LIVE) | S(MODEM_ST_DESTROY) | S(MODEM_ST_POWEROFF), 1194 .name = "START_IFACE", 1195 .action = modem_st_start_iface, 1196 .onenter = modem_st_start_iface_onenter, 1197 }, 1198 [MODEM_ST_LIVE] = { 1199 .in_event_mask = S(MODEM_EV_RX_SUCCEED) | S(MODEM_EV_RX_FAILED), 1200 .out_state_mask = S(MODEM_ST_DESTROY), 1201 .name = "LIVE", 1202 .action = modem_st_live, 1203 .onenter = modem_st_live_onenter, 1204 }, 1205 [MODEM_ST_FAILED] = { 1206 .in_event_mask = 0, 1207 .out_state_mask = S(MODEM_ST_DESTROY), 1208 .name = "FAILED", 1209 .action = modem_st_failed, 1210 // .onenter = modem_st_live_onenter,s 1211 }, 1212 [MODEM_ST_DESTROY] = { 1213 .in_event_mask = 0, 1214 .out_state_mask = 0, 1215 .name = "DESTROY", 1216 .action = modem_st_destroy, 1217 .onenter = modem_st_destroy_onenter, 1218 }, 1219 }; 1220 1221 static struct osmo_fsm modem_fsm = { 1222 .name = "MODEM", 1223 .states = modem_states, 1224 .num_states = ARRAY_SIZE(modem_states), 1225 .allstate_event_mask = S(MODEM_EV_REQ_DESTROY), 1226 .allstate_action = modem_fsm_allstate_action, 1227 // .cleanup = modem_fsm_cleanup, 1228 .timer_cb = modem_fsm_timer_cb, 1229 .event_names = modem_event_names, 1230 .pre_term = NULL, 1231 }; 1232 1233 struct osmo_fsm_inst *modem_fsm_alloc(struct modem *modem) 1234 { 1235 return osmo_fsm_inst_alloc(&modem_fsm, modem, modem, LOGL_DEBUG, modem->name); 1236 } 1237 1238 static __attribute__((constructor)) void on_dso_load_ctx(void) 1239 { 1240 OSMO_ASSERT(osmo_fsm_register(&modem_fsm) == 0); 1241 } 1242
This page was automatically generated by LXR 0.3.1. • OpenWrt