/src/mm-broadband-modem-qmi.c
C | 7658 lines | 6171 code | 1080 blank | 407 comment | 636 complexity | 5f40a7f99878fcded4c8cbb7d20245ec MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2/* 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation; either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details: 12 * 13 * Copyright (C) 2012 Google Inc. 14 */ 15 16#include <config.h> 17 18#include <stdlib.h> 19#include <stdio.h> 20#include <string.h> 21#include <unistd.h> 22#include <ctype.h> 23 24#include "mm-broadband-modem-qmi.h" 25 26#include "ModemManager.h" 27#include "mm-log.h" 28#include "mm-errors-types.h" 29#include "mm-modem-helpers.h" 30#include "mm-modem-helpers-qmi.h" 31#include "mm-iface-modem.h" 32#include "mm-iface-modem-3gpp.h" 33#include "mm-iface-modem-3gpp-ussd.h" 34#include "mm-iface-modem-cdma.h" 35#include "mm-iface-modem-messaging.h" 36#include "mm-iface-modem-location.h" 37#include "mm-iface-modem-firmware.h" 38#include "mm-sim-qmi.h" 39#include "mm-bearer-qmi.h" 40#include "mm-sms-qmi.h" 41 42static void iface_modem_init (MMIfaceModem *iface); 43static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface); 44static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface); 45static void iface_modem_cdma_init (MMIfaceModemCdma *iface); 46static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); 47static void iface_modem_location_init (MMIfaceModemLocation *iface); 48static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); 49 50static MMIfaceModemLocation *iface_modem_location_parent; 51 52G_DEFINE_TYPE_EXTENDED (MMBroadbandModemQmi, mm_broadband_modem_qmi, MM_TYPE_BROADBAND_MODEM, 0, 53 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init) 54 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init) 55 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP_USSD, iface_modem_3gpp_ussd_init) 56 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init) 57 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init) 58 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init) 59 G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)) 60 61struct _MMBroadbandModemQmiPrivate { 62 /* Cached device IDs, retrieved by the modem interface when loading device 63 * IDs, and used afterwards in the 3GPP and CDMA interfaces. */ 64 gchar *imei; 65 gchar *meid; 66 gchar *esn; 67 68 /* Cached supported frequency bands; in order to handle ANY */ 69 GArray *supported_bands; 70 71 /* 3GPP and CDMA share unsolicited events setup/enable/disable/cleanup */ 72 gboolean unsolicited_events_enabled; 73 gboolean unsolicited_events_setup; 74 guint event_report_indication_id; 75#if defined WITH_NEWEST_QMI_COMMANDS 76 guint signal_info_indication_id; 77#endif /* WITH_NEWEST_QMI_COMMANDS */ 78 79 /* 3GPP/CDMA registration helpers */ 80 gchar *current_operator_id; 81 gchar *current_operator_description; 82 gboolean unsolicited_registration_events_enabled; 83 gboolean unsolicited_registration_events_setup; 84 guint serving_system_indication_id; 85#if defined WITH_NEWEST_QMI_COMMANDS 86 guint system_info_indication_id; 87#endif /* WITH_NEWEST_QMI_COMMANDS */ 88 89 /* Messaging helpers */ 90 gboolean messaging_unsolicited_events_enabled; 91 gboolean messaging_unsolicited_events_setup; 92 guint messaging_event_report_indication_id; 93 94 /* Location helpers */ 95 MMModemLocationSource enabled_sources; 96 guint location_event_report_indication_id; 97 98 /* Firmware helpers */ 99 GList *firmware_list; 100 MMFirmwareProperties *current_firmware; 101}; 102 103/*****************************************************************************/ 104 105static QmiClient * 106peek_qmi_client (MMBroadbandModemQmi *self, 107 QmiService service, 108 GError **error) 109{ 110 MMQmiPort *port; 111 QmiClient *client; 112 113 port = mm_base_modem_peek_port_qmi (MM_BASE_MODEM (self)); 114 if (!port) { 115 g_set_error (error, 116 MM_CORE_ERROR, 117 MM_CORE_ERROR_FAILED, 118 "Couldn't peek QMI port"); 119 return NULL; 120 } 121 122 client = mm_qmi_port_peek_client (port, 123 service, 124 MM_QMI_PORT_FLAG_DEFAULT); 125 if (!client) 126 g_set_error (error, 127 MM_CORE_ERROR, 128 MM_CORE_ERROR_FAILED, 129 "Couldn't peek client for service '%s'", 130 qmi_service_get_string (service)); 131 132 return client; 133} 134 135static gboolean 136ensure_qmi_client (MMBroadbandModemQmi *self, 137 QmiService service, 138 QmiClient **o_client, 139 GAsyncReadyCallback callback, 140 gpointer user_data) 141{ 142 GError *error = NULL; 143 QmiClient *client; 144 145 client = peek_qmi_client (self, service, &error); 146 if (!client) { 147 g_simple_async_report_take_gerror_in_idle ( 148 G_OBJECT (self), 149 callback, 150 user_data, 151 error); 152 return FALSE; 153 } 154 155 *o_client = client; 156 return TRUE; 157} 158 159/*****************************************************************************/ 160/* Create Bearer (Modem interface) */ 161 162static MMBearer * 163modem_create_bearer_finish (MMIfaceModem *self, 164 GAsyncResult *res, 165 GError **error) 166{ 167 MMBearer *bearer; 168 169 bearer = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); 170 mm_dbg ("New bearer created at DBus path '%s'", mm_bearer_get_path (bearer)); 171 172 return g_object_ref (bearer); 173} 174 175static void 176modem_create_bearer (MMIfaceModem *self, 177 MMBearerProperties *properties, 178 GAsyncReadyCallback callback, 179 gpointer user_data) 180{ 181 MMBearer *bearer; 182 GSimpleAsyncResult *result; 183 184 /* Set a new ref to the bearer object as result */ 185 result = g_simple_async_result_new (G_OBJECT (self), 186 callback, 187 user_data, 188 modem_create_bearer); 189 190 /* We just create a MMBearerQmi */ 191 mm_dbg ("Creating QMI bearer in QMI modem"); 192 bearer = mm_bearer_qmi_new (MM_BROADBAND_MODEM_QMI (self), 193 properties); 194 195 g_simple_async_result_set_op_res_gpointer (result, bearer, g_object_unref); 196 g_simple_async_result_complete_in_idle (result); 197 g_object_unref (result); 198} 199 200/*****************************************************************************/ 201/* Current Capabilities loading (Modem interface) */ 202 203typedef struct { 204 MMBroadbandModemQmi *self; 205 QmiClientNas *nas_client; 206 QmiClientDms *dms_client; 207 GSimpleAsyncResult *result; 208 gboolean run_get_system_selection_preference; 209 gboolean run_get_technology_preference; 210 gboolean run_get_capabilities; 211 MMModemCapability capabilities; 212} LoadCurrentCapabilitiesContext; 213 214static MMModemCapability 215modem_load_current_capabilities_finish (MMIfaceModem *self, 216 GAsyncResult *res, 217 GError **error) 218{ 219 MMModemCapability caps; 220 gchar *caps_str; 221 222 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 223 return MM_MODEM_CAPABILITY_NONE; 224 225 caps = ((MMModemCapability) GPOINTER_TO_UINT ( 226 g_simple_async_result_get_op_res_gpointer ( 227 G_SIMPLE_ASYNC_RESULT (res)))); 228 caps_str = mm_modem_capability_build_string_from_mask (caps); 229 mm_dbg ("loaded current capabilities: %s", caps_str); 230 g_free (caps_str); 231 return caps; 232} 233 234static void 235load_current_capabilities_context_complete_and_free (LoadCurrentCapabilitiesContext *ctx) 236{ 237 g_simple_async_result_complete_in_idle (ctx->result); 238 g_object_unref (ctx->result); 239 g_object_unref (ctx->nas_client); 240 g_object_unref (ctx->dms_client); 241 g_object_unref (ctx->self); 242 g_free (ctx); 243} 244 245static void load_current_capabilities_context_step (LoadCurrentCapabilitiesContext *ctx); 246 247static void 248load_current_capabilities_get_capabilities_ready (QmiClientDms *client, 249 GAsyncResult *res, 250 LoadCurrentCapabilitiesContext *ctx) 251{ 252 QmiMessageDmsGetCapabilitiesOutput *output = NULL; 253 GError *error = NULL; 254 255 output = qmi_client_dms_get_capabilities_finish (client, res, &error); 256 if (!output) { 257 g_prefix_error (&error, "QMI operation failed: "); 258 g_simple_async_result_take_error (ctx->result, error); 259 } else if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) { 260 g_prefix_error (&error, "Couldn't get Capabilities: "); 261 g_simple_async_result_take_error (ctx->result, error); 262 } else { 263 guint i; 264 guint mask = MM_MODEM_CAPABILITY_NONE; 265 GArray *radio_interface_list; 266 267 qmi_message_dms_get_capabilities_output_get_info ( 268 output, 269 NULL, /* info_max_tx_channel_rate */ 270 NULL, /* info_max_rx_channel_rate */ 271 NULL, /* info_data_service_capability */ 272 NULL, /* info_sim_capability */ 273 &radio_interface_list, 274 NULL); 275 276 for (i = 0; i < radio_interface_list->len; i++) { 277 mask |= mm_modem_capability_from_qmi_radio_interface (g_array_index (radio_interface_list, 278 QmiDmsRadioInterface, 279 i)); 280 } 281 282 /* Final capabilities are the intersection between the Technology 283 * Preference (ie, allowed modes) or SSP and the device's capabilities. 284 * If the Technology Preference was "auto" or unknown we just fall back 285 * to the Get Capabilities response. 286 */ 287 if (ctx->capabilities == MM_MODEM_CAPABILITY_NONE) 288 ctx->capabilities = mask; 289 else 290 ctx->capabilities &= mask; 291 } 292 293 if (output) 294 qmi_message_dms_get_capabilities_output_unref (output); 295 296 g_simple_async_result_set_op_res_gpointer (ctx->result, GUINT_TO_POINTER (ctx->capabilities), NULL); 297 load_current_capabilities_context_complete_and_free (ctx); 298} 299 300static void 301load_current_capabilities_get_technology_preference_ready (QmiClientNas *client, 302 GAsyncResult *res, 303 LoadCurrentCapabilitiesContext *ctx) 304{ 305 QmiMessageNasGetTechnologyPreferenceOutput *output = NULL; 306 GError *error = NULL; 307 308 output = qmi_client_nas_get_technology_preference_finish (client, res, &error); 309 if (!output) { 310 mm_dbg ("QMI operation failed: %s", error->message); 311 g_error_free (error); 312 } else if (!qmi_message_nas_get_technology_preference_output_get_result (output, &error)) { 313 mm_dbg ("Couldn't get technology preference: %s", error->message); 314 g_error_free (error); 315 } else { 316 QmiNasRadioTechnologyPreference preference_mask; 317 318 qmi_message_nas_get_technology_preference_output_get_active ( 319 output, 320 &preference_mask, 321 NULL, /* duration */ 322 NULL); 323 if (preference_mask != QMI_NAS_RADIO_TECHNOLOGY_PREFERENCE_AUTO) { 324 gchar *str; 325 326 str = qmi_nas_radio_technology_preference_build_string_from_mask (preference_mask); 327 ctx->capabilities = mm_modem_capability_from_qmi_radio_technology_preference (preference_mask); 328 mm_dbg ("%s modes reported in technology preference: '%s'", 329 ctx->capabilities == MM_MODEM_CAPABILITY_NONE ? "Unsupported" : "Valid", 330 str); 331 g_free (str); 332 } 333 } 334 335 if (output) 336 qmi_message_nas_get_technology_preference_output_unref (output); 337 338 /* Mark as TP already run */ 339 ctx->run_get_technology_preference = FALSE; 340 341 /* Get DMS Capabilities too */ 342 load_current_capabilities_context_step (ctx); 343} 344 345static void 346load_current_capabilities_get_system_selection_preference_ready (QmiClientNas *client, 347 GAsyncResult *res, 348 LoadCurrentCapabilitiesContext *ctx) 349{ 350 QmiMessageNasGetSystemSelectionPreferenceOutput *output = NULL; 351 GError *error = NULL; 352 QmiNasRatModePreference mode_preference_mask = 0; 353 354 output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error); 355 if (!output) { 356 mm_dbg ("QMI operation failed: %s", error->message); 357 g_error_free (error); 358 } else if (!qmi_message_nas_get_system_selection_preference_output_get_result (output, &error)) { 359 mm_dbg ("Couldn't get system selection preference: %s", error->message); 360 g_error_free (error); 361 } else if (!qmi_message_nas_get_system_selection_preference_output_get_mode_preference ( 362 output, 363 &mode_preference_mask, 364 NULL)) { 365 QmiNasBandPreference band_preference_mask; 366 367 mm_dbg ("Mode preference not reported in system selection preference"); 368 369 if (qmi_message_nas_get_system_selection_preference_output_get_band_preference ( 370 output, 371 &band_preference_mask, 372 NULL)) { 373 gchar *str; 374 375 str = qmi_nas_band_preference_build_string_from_mask (band_preference_mask); 376 ctx->capabilities = mm_modem_capability_from_qmi_band_preference (band_preference_mask); 377 mm_dbg ("%s bands reported in system selection preference: '%s'", 378 ctx->capabilities == MM_MODEM_CAPABILITY_NONE ? "Unsupported" : "Valid", 379 str); 380 g_free (str); 381 382 /* Just the presence of the LTE band preference tells us it's LTE */ 383 if (qmi_message_nas_get_system_selection_preference_output_get_lte_band_preference ( 384 output, 385 NULL, 386 NULL)) { 387 mm_dbg ("LTE band preference found"); 388 ctx->capabilities |= MM_MODEM_CAPABILITY_LTE; 389 } 390 } else 391 mm_dbg ("Band preference not reported in system selection preference"); 392 } else { 393 gchar *str; 394 395 str = qmi_nas_rat_mode_preference_build_string_from_mask (mode_preference_mask); 396 ctx->capabilities = mm_modem_capability_from_qmi_rat_mode_preference (mode_preference_mask); 397 mm_dbg ("%s capabilities reported in system selection preference: '%s'", 398 ctx->capabilities == MM_MODEM_CAPABILITY_NONE ? "Unsupported" : "Valid", 399 str); 400 g_free (str); 401 } 402 403 if (output) 404 qmi_message_nas_get_system_selection_preference_output_unref (output); 405 406 /* Mark as SSP already run */ 407 ctx->run_get_system_selection_preference = FALSE; 408 409 /* If we got some value, cache it and go on to DMS Get Capabilities */ 410 if (ctx->capabilities != MM_MODEM_CAPABILITY_NONE) 411 ctx->run_get_technology_preference = FALSE; 412 413 load_current_capabilities_context_step (ctx); 414} 415 416static void 417load_current_capabilities_context_step (LoadCurrentCapabilitiesContext *ctx) 418{ 419 if (ctx->run_get_system_selection_preference) { 420 qmi_client_nas_get_system_selection_preference ( 421 ctx->nas_client, 422 NULL, /* no input */ 423 5, 424 NULL, /* cancellable */ 425 (GAsyncReadyCallback)load_current_capabilities_get_system_selection_preference_ready, 426 ctx); 427 return; 428 } 429 430 if (ctx->run_get_technology_preference) { 431 qmi_client_nas_get_technology_preference ( 432 ctx->nas_client, 433 NULL, /* no input */ 434 5, 435 NULL, /* cancellable */ 436 (GAsyncReadyCallback)load_current_capabilities_get_technology_preference_ready, 437 ctx); 438 return; 439 } 440 441 if (ctx->run_get_capabilities) { 442 qmi_client_dms_get_capabilities ( 443 ctx->dms_client, 444 NULL, /* no input */ 445 5, 446 NULL, /* cancellable */ 447 (GAsyncReadyCallback)load_current_capabilities_get_capabilities_ready, 448 ctx); 449 return; 450 } 451 452 g_simple_async_result_set_error ( 453 ctx->result, 454 MM_CORE_ERROR, 455 MM_CORE_ERROR_UNSUPPORTED, 456 "Loading current capabilities is not supported by this device"); 457 load_current_capabilities_context_complete_and_free (ctx); 458} 459 460static void 461modem_load_current_capabilities (MMIfaceModem *self, 462 GAsyncReadyCallback callback, 463 gpointer user_data) 464{ 465 LoadCurrentCapabilitiesContext *ctx; 466 QmiClient *nas_client = NULL; 467 QmiClient *dms_client = NULL; 468 469 /* Best way to get current capabilities (ie, enabled radios) is 470 * Get System Selection Preference's "mode preference" TLV, but that's 471 * only supported by NAS >= 1.1, meaning older Gobi devices don't 472 * implement it. 473 * 474 * On these devices, the DMS Get Capabilities call appears to report 475 * currently enabled radios, but this does not take the user's 476 * technology preference into account. 477 * 478 * So in the absence of System Selection Preference, we check the 479 * Technology Preference first, and if that is "AUTO" we fall back to 480 * Get Capabilities. 481 */ 482 483 mm_dbg ("loading current capabilities..."); 484 485 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 486 QMI_SERVICE_NAS, &nas_client, 487 callback, user_data)) 488 return; 489 490 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 491 QMI_SERVICE_DMS, &dms_client, 492 callback, user_data)) 493 return; 494 495 ctx = g_new0 (LoadCurrentCapabilitiesContext, 1); 496 ctx->self = g_object_ref (self); 497 ctx->nas_client = g_object_ref (nas_client); 498 ctx->dms_client = g_object_ref (dms_client); 499 ctx->result = g_simple_async_result_new (G_OBJECT (self), 500 callback, 501 user_data, 502 modem_load_current_capabilities); 503 ctx->capabilities = MM_MODEM_CAPABILITY_NONE; 504 505 /* System selection preference introduced in NAS 1.1 */ 506 ctx->run_get_system_selection_preference = qmi_client_check_version (nas_client, 1, 1); 507 508 ctx->run_get_technology_preference = TRUE; 509 ctx->run_get_capabilities = TRUE; 510 511 load_current_capabilities_context_step (ctx); 512} 513 514/*****************************************************************************/ 515/* Modem Capabilities loading (Modem interface) */ 516 517static MMModemCapability 518modem_load_modem_capabilities_finish (MMIfaceModem *self, 519 GAsyncResult *res, 520 GError **error) 521{ 522 MMModemCapability caps; 523 gchar *caps_str; 524 525 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 526 return MM_MODEM_CAPABILITY_NONE; 527 528 caps = ((MMModemCapability) GPOINTER_TO_UINT ( 529 g_simple_async_result_get_op_res_gpointer ( 530 G_SIMPLE_ASYNC_RESULT (res)))); 531 caps_str = mm_modem_capability_build_string_from_mask (caps); 532 mm_dbg ("loaded modem capabilities: %s", caps_str); 533 g_free (caps_str); 534 return caps; 535} 536 537static void 538dms_get_capabilities_ready (QmiClientDms *client, 539 GAsyncResult *res, 540 GSimpleAsyncResult *simple) 541{ 542 QmiMessageDmsGetCapabilitiesOutput *output = NULL; 543 GError *error = NULL; 544 545 output = qmi_client_dms_get_capabilities_finish (client, res, &error); 546 if (!output) { 547 g_prefix_error (&error, "QMI operation failed: "); 548 g_simple_async_result_take_error (simple, error); 549 } else if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) { 550 g_prefix_error (&error, "Couldn't get modem capabilities: "); 551 g_simple_async_result_take_error (simple, error); 552 } else { 553 guint i; 554 guint mask = MM_MODEM_CAPABILITY_NONE; 555 GArray *radio_interface_list; 556 557 qmi_message_dms_get_capabilities_output_get_info ( 558 output, 559 NULL, /* info_max_tx_channel_rate */ 560 NULL, /* info_max_rx_channel_rate */ 561 NULL, /* info_data_service_capability */ 562 NULL, /* info_sim_capability */ 563 &radio_interface_list, 564 NULL); 565 566 for (i = 0; i < radio_interface_list->len; i++) { 567 mask |= mm_modem_capability_from_qmi_radio_interface (g_array_index (radio_interface_list, 568 QmiDmsRadioInterface, 569 i)); 570 } 571 572 g_simple_async_result_set_op_res_gpointer (simple, 573 GUINT_TO_POINTER (mask), 574 NULL); 575 } 576 577 if (output) 578 qmi_message_dms_get_capabilities_output_unref (output); 579 580 g_simple_async_result_complete (simple); 581 g_object_unref (simple); 582} 583 584static void 585modem_load_modem_capabilities (MMIfaceModem *self, 586 GAsyncReadyCallback callback, 587 gpointer user_data) 588{ 589 GSimpleAsyncResult *result; 590 QmiClient *client = NULL; 591 592 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 593 QMI_SERVICE_DMS, &client, 594 callback, user_data)) 595 return; 596 597 result = g_simple_async_result_new (G_OBJECT (self), 598 callback, 599 user_data, 600 modem_load_modem_capabilities); 601 602 mm_dbg ("loading modem capabilities..."); 603 qmi_client_dms_get_capabilities (QMI_CLIENT_DMS (client), 604 NULL, 605 5, 606 NULL, 607 (GAsyncReadyCallback)dms_get_capabilities_ready, 608 result); 609} 610 611/*****************************************************************************/ 612/* Manufacturer loading (Modem interface) */ 613 614static gchar * 615modem_load_manufacturer_finish (MMIfaceModem *self, 616 GAsyncResult *res, 617 GError **error) 618{ 619 gchar *manufacturer; 620 621 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 622 return NULL; 623 624 manufacturer = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); 625 mm_dbg ("loaded manufacturer: %s", manufacturer); 626 return manufacturer; 627} 628 629static void 630dms_get_manufacturer_ready (QmiClientDms *client, 631 GAsyncResult *res, 632 GSimpleAsyncResult *simple) 633{ 634 QmiMessageDmsGetManufacturerOutput *output = NULL; 635 GError *error = NULL; 636 637 output = qmi_client_dms_get_manufacturer_finish (client, res, &error); 638 if (!output) { 639 g_prefix_error (&error, "QMI operation failed: "); 640 g_simple_async_result_take_error (simple, error); 641 } else if (!qmi_message_dms_get_manufacturer_output_get_result (output, &error)) { 642 g_prefix_error (&error, "Couldn't get Manufacturer: "); 643 g_simple_async_result_take_error (simple, error); 644 } else { 645 const gchar *str; 646 647 qmi_message_dms_get_manufacturer_output_get_manufacturer (output, &str, NULL); 648 g_simple_async_result_set_op_res_gpointer (simple, 649 g_strdup (str), 650 (GDestroyNotify)g_free); 651 } 652 653 if (output) 654 qmi_message_dms_get_manufacturer_output_unref (output); 655 656 g_simple_async_result_complete (simple); 657 g_object_unref (simple); 658} 659 660static void 661modem_load_manufacturer (MMIfaceModem *self, 662 GAsyncReadyCallback callback, 663 gpointer user_data) 664{ 665 GSimpleAsyncResult *result; 666 QmiClient *client = NULL; 667 668 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 669 QMI_SERVICE_DMS, &client, 670 callback, user_data)) 671 return; 672 673 result = g_simple_async_result_new (G_OBJECT (self), 674 callback, 675 user_data, 676 modem_load_manufacturer); 677 678 mm_dbg ("loading manufacturer..."); 679 qmi_client_dms_get_manufacturer (QMI_CLIENT_DMS (client), 680 NULL, 681 5, 682 NULL, 683 (GAsyncReadyCallback)dms_get_manufacturer_ready, 684 result); 685} 686 687/*****************************************************************************/ 688/* Model loading (Modem interface) */ 689 690static gchar * 691modem_load_model_finish (MMIfaceModem *self, 692 GAsyncResult *res, 693 GError **error) 694{ 695 gchar *model; 696 697 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 698 return NULL; 699 700 model = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); 701 mm_dbg ("loaded model: %s", model); 702 return model; 703} 704 705static void 706dms_get_model_ready (QmiClientDms *client, 707 GAsyncResult *res, 708 GSimpleAsyncResult *simple) 709{ 710 QmiMessageDmsGetModelOutput *output = NULL; 711 GError *error = NULL; 712 713 output = qmi_client_dms_get_model_finish (client, res, &error); 714 if (!output) { 715 g_prefix_error (&error, "QMI operation failed: "); 716 g_simple_async_result_take_error (simple, error); 717 } else if (!qmi_message_dms_get_model_output_get_result (output, &error)) { 718 g_prefix_error (&error, "Couldn't get Model: "); 719 g_simple_async_result_take_error (simple, error); 720 } else { 721 const gchar *str; 722 723 qmi_message_dms_get_model_output_get_model (output, &str, NULL); 724 g_simple_async_result_set_op_res_gpointer (simple, 725 g_strdup (str), 726 (GDestroyNotify)g_free); 727 } 728 729 if (output) 730 qmi_message_dms_get_model_output_unref (output); 731 732 g_simple_async_result_complete (simple); 733 g_object_unref (simple); 734} 735 736static void 737modem_load_model (MMIfaceModem *self, 738 GAsyncReadyCallback callback, 739 gpointer user_data) 740{ 741 GSimpleAsyncResult *result; 742 QmiClient *client = NULL; 743 744 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 745 QMI_SERVICE_DMS, &client, 746 callback, user_data)) 747 return; 748 749 result = g_simple_async_result_new (G_OBJECT (self), 750 callback, 751 user_data, 752 modem_load_model); 753 754 mm_dbg ("loading model..."); 755 qmi_client_dms_get_model (QMI_CLIENT_DMS (client), 756 NULL, 757 5, 758 NULL, 759 (GAsyncReadyCallback)dms_get_model_ready, 760 result); 761} 762 763/*****************************************************************************/ 764/* Revision loading (Modem interface) */ 765 766static gchar * 767modem_load_revision_finish (MMIfaceModem *self, 768 GAsyncResult *res, 769 GError **error) 770{ 771 gchar *revision; 772 773 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 774 return NULL; 775 776 revision = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); 777 mm_dbg ("loaded revision: %s", revision); 778 return revision; 779} 780 781static void 782dms_get_revision_ready (QmiClientDms *client, 783 GAsyncResult *res, 784 GSimpleAsyncResult *simple) 785{ 786 QmiMessageDmsGetRevisionOutput *output = NULL; 787 GError *error = NULL; 788 789 output = qmi_client_dms_get_revision_finish (client, res, &error); 790 if (!output) { 791 g_prefix_error (&error, "QMI operation failed: "); 792 g_simple_async_result_take_error (simple, error); 793 } else if (!qmi_message_dms_get_revision_output_get_result (output, &error)) { 794 g_prefix_error (&error, "Couldn't get Revision: "); 795 g_simple_async_result_take_error (simple, error); 796 } else { 797 const gchar *str; 798 799 qmi_message_dms_get_revision_output_get_revision (output, &str, NULL); 800 g_simple_async_result_set_op_res_gpointer (simple, 801 g_strdup (str), 802 (GDestroyNotify)g_free); 803 } 804 805 if (output) 806 qmi_message_dms_get_revision_output_unref (output); 807 808 g_simple_async_result_complete (simple); 809 g_object_unref (simple); 810} 811 812static void 813modem_load_revision (MMIfaceModem *self, 814 GAsyncReadyCallback callback, 815 gpointer user_data) 816{ 817 GSimpleAsyncResult *result; 818 QmiClient *client = NULL; 819 820 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 821 QMI_SERVICE_DMS, &client, 822 callback, user_data)) 823 return; 824 825 result = g_simple_async_result_new (G_OBJECT (self), 826 callback, 827 user_data, 828 modem_load_revision); 829 830 mm_dbg ("loading revision..."); 831 qmi_client_dms_get_revision (QMI_CLIENT_DMS (client), 832 NULL, 833 5, 834 NULL, 835 (GAsyncReadyCallback)dms_get_revision_ready, 836 result); 837} 838 839/*****************************************************************************/ 840/* Equipment Identifier loading (Modem interface) */ 841 842typedef struct { 843 MMBroadbandModemQmi *self; 844 QmiClient *client; 845 GSimpleAsyncResult *result; 846} LoadEquipmentIdentifierContext; 847 848static void 849load_equipment_identifier_context_complete_and_free (LoadEquipmentIdentifierContext *ctx) 850{ 851 g_simple_async_result_complete (ctx->result); 852 g_object_unref (ctx->result); 853 g_object_unref (ctx->client); 854 g_object_unref (ctx->self); 855 g_free (ctx); 856} 857 858static gchar * 859modem_load_equipment_identifier_finish (MMIfaceModem *self, 860 GAsyncResult *res, 861 GError **error) 862{ 863 gchar *equipment_identifier; 864 865 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 866 return NULL; 867 868 equipment_identifier = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); 869 mm_dbg ("loaded equipment identifier: %s", equipment_identifier); 870 return equipment_identifier; 871} 872 873static void 874dms_get_ids_ready (QmiClientDms *client, 875 GAsyncResult *res, 876 LoadEquipmentIdentifierContext *ctx) 877{ 878 QmiMessageDmsGetIdsOutput *output = NULL; 879 GError *error = NULL; 880 const gchar *str; 881 882 output = qmi_client_dms_get_ids_finish (client, res, &error); 883 if (!output) { 884 g_prefix_error (&error, "QMI operation failed: "); 885 g_simple_async_result_take_error (ctx->result, error); 886 load_equipment_identifier_context_complete_and_free (ctx); 887 return; 888 } 889 890 if (!qmi_message_dms_get_ids_output_get_result (output, &error)) { 891 g_prefix_error (&error, "Couldn't get IDs: "); 892 g_simple_async_result_take_error (ctx->result, error); 893 qmi_message_dms_get_ids_output_unref (output); 894 load_equipment_identifier_context_complete_and_free (ctx); 895 return; 896 } 897 898 /* In order: 899 * If we have a IMEI, use it... 900 * Otherwise, if we have a ESN, use it... 901 * Otherwise, if we have a MEID, use it... 902 * Otherwise, 'unknown' 903 */ 904 905 if (qmi_message_dms_get_ids_output_get_imei (output, &str, NULL) && 906 str[0] != '\0' && str[0] != '0') { 907 g_free (ctx->self->priv->imei); 908 ctx->self->priv->imei = g_strdup (str); 909 } 910 911 if (qmi_message_dms_get_ids_output_get_esn (output, &str, NULL) && 912 str[0] != '\0' && str[0] != '0') { 913 g_free (ctx->self->priv->esn); 914 ctx->self->priv->esn = g_strdup (str); 915 } 916 917 if (qmi_message_dms_get_ids_output_get_meid (output, &str, NULL) && 918 str[0] != '\0' && str[0] != '0') { 919 g_free (ctx->self->priv->meid); 920 ctx->self->priv->meid = g_strdup (str); 921 } 922 923 if (ctx->self->priv->imei) 924 str = ctx->self->priv->imei; 925 else if (ctx->self->priv->esn) 926 str = ctx->self->priv->esn; 927 else if (ctx->self->priv->meid) 928 str = ctx->self->priv->meid; 929 else 930 str = "unknown"; 931 932 g_simple_async_result_set_op_res_gpointer (ctx->result, 933 g_strdup (str), 934 (GDestroyNotify)g_free); 935 936 qmi_message_dms_get_ids_output_unref (output); 937 load_equipment_identifier_context_complete_and_free (ctx); 938} 939 940static void 941modem_load_equipment_identifier (MMIfaceModem *self, 942 GAsyncReadyCallback callback, 943 gpointer user_data) 944{ 945 LoadEquipmentIdentifierContext *ctx; 946 QmiClient *client = NULL; 947 948 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 949 QMI_SERVICE_DMS, &client, 950 callback, user_data)) 951 return; 952 953 ctx = g_new (LoadEquipmentIdentifierContext, 1); 954 ctx->self = g_object_ref (self); 955 ctx->client = g_object_ref (client); 956 ctx->result = g_simple_async_result_new (G_OBJECT (self), 957 callback, 958 user_data, 959 modem_load_equipment_identifier); 960 961 mm_dbg ("loading equipment identifier..."); 962 qmi_client_dms_get_ids (QMI_CLIENT_DMS (client), 963 NULL, 964 5, 965 NULL, 966 (GAsyncReadyCallback)dms_get_ids_ready, 967 ctx); 968} 969 970/*****************************************************************************/ 971/* Device identifier loading (Modem interface) */ 972 973static gchar * 974modem_load_device_identifier_finish (MMIfaceModem *self, 975 GAsyncResult *res, 976 GError **error) 977{ 978 gchar *device_identifier; 979 980 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 981 return NULL; 982 983 device_identifier = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); 984 mm_dbg ("loaded device identifier: %s", device_identifier); 985 return device_identifier; 986} 987 988static void 989modem_load_device_identifier (MMIfaceModem *self, 990 GAsyncReadyCallback callback, 991 gpointer user_data) 992{ 993 GSimpleAsyncResult *result; 994 gchar *device_identifier; 995 996 mm_dbg ("loading device identifier..."); 997 result = g_simple_async_result_new (G_OBJECT (self), 998 callback, 999 user_data, 1000 modem_load_device_identifier); 1001 1002 /* Just use dummy ATI/ATI1 replies, all the other internal info should be 1003 * enough for uniqueness */ 1004 device_identifier = mm_broadband_modem_create_device_identifier (MM_BROADBAND_MODEM (self), "", ""); 1005 g_simple_async_result_set_op_res_gpointer (result, 1006 device_identifier, 1007 (GDestroyNotify)g_free); 1008 g_simple_async_result_complete_in_idle (result); 1009 g_object_unref (result); 1010} 1011 1012/*****************************************************************************/ 1013/* Own Numbers loading (Modem interface) */ 1014 1015static GStrv 1016modem_load_own_numbers_finish (MMIfaceModem *self, 1017 GAsyncResult *res, 1018 GError **error) 1019{ 1020 gchar **own_numbers; 1021 1022 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 1023 return NULL; 1024 1025 own_numbers = g_new0 (gchar *, 2); 1026 own_numbers[0] = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res))); 1027 mm_dbg ("loaded own numbers: %s", own_numbers[0]); 1028 return own_numbers; 1029} 1030 1031static void 1032dms_get_msisdn_ready (QmiClientDms *client, 1033 GAsyncResult *res, 1034 GSimpleAsyncResult *simple) 1035{ 1036 QmiMessageDmsGetMsisdnOutput *output = NULL; 1037 GError *error = NULL; 1038 1039 output = qmi_client_dms_get_msisdn_finish (client, res, &error); 1040 if (!output) { 1041 g_prefix_error (&error, "QMI operation failed: "); 1042 g_simple_async_result_take_error (simple, error); 1043 } else if (!qmi_message_dms_get_msisdn_output_get_result (output, &error)) { 1044 g_prefix_error (&error, "Couldn't get MSISDN: "); 1045 g_simple_async_result_take_error (simple, error); 1046 } else { 1047 const gchar *str = NULL; 1048 1049 qmi_message_dms_get_msisdn_output_get_msisdn (output, &str, NULL); 1050 g_simple_async_result_set_op_res_gpointer (simple, 1051 g_strdup (str), 1052 (GDestroyNotify)g_free); 1053 } 1054 1055 if (output) 1056 qmi_message_dms_get_msisdn_output_unref (output); 1057 1058 g_simple_async_result_complete (simple); 1059 g_object_unref (simple); 1060} 1061 1062static void 1063modem_load_own_numbers (MMIfaceModem *self, 1064 GAsyncReadyCallback callback, 1065 gpointer user_data) 1066{ 1067 GSimpleAsyncResult *result; 1068 QmiClient *client = NULL; 1069 1070 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 1071 QMI_SERVICE_DMS, &client, 1072 callback, user_data)) 1073 return; 1074 1075 result = g_simple_async_result_new (G_OBJECT (self), 1076 callback, 1077 user_data, 1078 modem_load_own_numbers); 1079 1080 mm_dbg ("loading own numbers..."); 1081 qmi_client_dms_get_msisdn (QMI_CLIENT_DMS (client), 1082 NULL, 1083 5, 1084 NULL, 1085 (GAsyncReadyCallback)dms_get_msisdn_ready, 1086 result); 1087} 1088 1089/*****************************************************************************/ 1090/* Check if unlock required (Modem interface) */ 1091 1092static MMModemLock 1093modem_load_unlock_required_finish (MMIfaceModem *self, 1094 GAsyncResult *res, 1095 GError **error) 1096{ 1097 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 1098 return MM_MODEM_LOCK_UNKNOWN; 1099 1100 return (MMModemLock) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer ( 1101 G_SIMPLE_ASYNC_RESULT (res))); 1102} 1103 1104static void 1105dms_uim_get_pin_status_ready (QmiClientDms *client, 1106 GAsyncResult *res, 1107 GSimpleAsyncResult *simple) 1108{ 1109 QmiMessageDmsUimGetPinStatusOutput *output; 1110 GError *error = NULL; 1111 1112 output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error); 1113 if (!output) { 1114 g_prefix_error (&error, "QMI operation failed: "); 1115 g_simple_async_result_take_error (simple, error); 1116 } else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) { 1117 /* When no SIM inserted, an internal error when checking PIN status 1118 * needs to be fatal so that we mark the modem unusable. */ 1119 if (g_error_matches (error, 1120 QMI_PROTOCOL_ERROR, 1121 QMI_PROTOCOL_ERROR_INTERNAL)) { 1122 g_simple_async_result_set_error (simple, 1123 MM_MOBILE_EQUIPMENT_ERROR, 1124 MM_MOBILE_EQUIPMENT_ERROR_SIM_FAILURE, 1125 "Couldn't get PIN status: %s", 1126 error->message); 1127 g_error_free (error); 1128 } else { 1129 g_prefix_error (&error, "Couldn't get PIN status: "); 1130 g_simple_async_result_take_error (simple, error); 1131 } 1132 } else { 1133 MMModemLock lock = MM_MODEM_LOCK_UNKNOWN; 1134 QmiDmsUimPinStatus current_status; 1135 1136 if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status ( 1137 output, 1138 ¤t_status, 1139 NULL, /* verify_retries_left */ 1140 NULL, /* unblock_retries_left */ 1141 NULL)) 1142 lock = mm_modem_lock_from_qmi_uim_pin_status (current_status, TRUE); 1143 1144 if (lock == MM_MODEM_LOCK_NONE && 1145 qmi_message_dms_uim_get_pin_status_output_get_pin2_status ( 1146 output, 1147 ¤t_status, 1148 NULL, /* verify_retries_left */ 1149 NULL, /* unblock_retries_left */ 1150 NULL)) 1151 lock = mm_modem_lock_from_qmi_uim_pin_status (current_status, FALSE); 1152 1153 g_simple_async_result_set_op_res_gpointer (simple, GUINT_TO_POINTER (lock), NULL); 1154 } 1155 1156 if (output) 1157 qmi_message_dms_uim_get_pin_status_output_unref (output); 1158 1159 g_simple_async_result_complete (simple); 1160 g_object_unref (simple); 1161} 1162 1163static void 1164modem_load_unlock_required (MMIfaceModem *self, 1165 GAsyncReadyCallback callback, 1166 gpointer user_data) 1167{ 1168 GSimpleAsyncResult *result; 1169 QmiClient *client = NULL; 1170 1171 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 1172 QMI_SERVICE_DMS, &client, 1173 callback, user_data)) 1174 return; 1175 1176 result = g_simple_async_result_new (G_OBJECT (self), 1177 callback, 1178 user_data, 1179 modem_load_unlock_required); 1180 1181 /* CDMA-only modems don't need this */ 1182 if (mm_iface_modem_is_cdma_only (self)) { 1183 mm_dbg ("Skipping unlock check in CDMA-only modem..."); 1184 g_simple_async_result_set_op_res_gpointer (result, 1185 GUINT_TO_POINTER (MM_MODEM_LOCK_NONE), 1186 NULL); 1187 g_simple_async_result_complete_in_idle (result); 1188 g_object_unref (result); 1189 return; 1190 } 1191 1192 mm_dbg ("loading unlock required..."); 1193 qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client), 1194 NULL, 1195 5, 1196 NULL, 1197 (GAsyncReadyCallback)dms_uim_get_pin_status_ready, 1198 result); 1199} 1200 1201/*****************************************************************************/ 1202/* Check if unlock retries (Modem interface) */ 1203 1204static MMUnlockRetries * 1205modem_load_unlock_retries_finish (MMIfaceModem *self, 1206 GAsyncResult *res, 1207 GError **error) 1208{ 1209 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 1210 return NULL; 1211 1212 return MM_UNLOCK_RETRIES (g_object_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)))); 1213} 1214 1215static void 1216retry_count_dms_uim_get_pin_status_ready (QmiClientDms *client, 1217 GAsyncResult *res, 1218 GSimpleAsyncResult *simple) 1219{ 1220 QmiMessageDmsUimGetPinStatusOutput *output; 1221 GError *error = NULL; 1222 1223 output = qmi_client_dms_uim_get_pin_status_finish (client, res, &error); 1224 if (!output) { 1225 g_prefix_error (&error, "QMI operation failed: "); 1226 g_simple_async_result_take_error (simple, error); 1227 } else if (!qmi_message_dms_uim_get_pin_status_output_get_result (output, &error)) { 1228 g_prefix_error (&error, "Couldn't get unlock retries: "); 1229 g_simple_async_result_take_error (simple, error); 1230 } else { 1231 MMUnlockRetries *retries; 1232 guint8 verify_retries_left; 1233 guint8 unblock_retries_left; 1234 1235 retries = mm_unlock_retries_new (); 1236 1237 if (qmi_message_dms_uim_get_pin_status_output_get_pin1_status ( 1238 output, 1239 NULL, /* current_status */ 1240 &verify_retries_left, 1241 &unblock_retries_left, 1242 NULL)) { 1243 mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN, verify_retries_left); 1244 mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK, unblock_retries_left); 1245 } 1246 1247 if (qmi_message_dms_uim_get_pin_status_output_get_pin2_status ( 1248 output, 1249 NULL, /* current_status */ 1250 &verify_retries_left, 1251 &unblock_retries_left, 1252 NULL)) { 1253 mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PIN2, verify_retries_left); 1254 mm_unlock_retries_set (retries, MM_MODEM_LOCK_SIM_PUK2, unblock_retries_left); 1255 } 1256 1257 g_simple_async_result_set_op_res_gpointer (simple, retries, g_object_unref); 1258 } 1259 1260 if (output) 1261 qmi_message_dms_uim_get_pin_status_output_unref (output); 1262 1263 g_simple_async_result_complete (simple); 1264 g_object_unref (simple); 1265} 1266 1267static void 1268modem_load_unlock_retries (MMIfaceModem *self, 1269 GAsyncReadyCallback callback, 1270 gpointer user_data) 1271{ 1272 GSimpleAsyncResult *result; 1273 QmiClient *client = NULL; 1274 1275 if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self), 1276 QMI_SERVICE_DMS, &client, 1277 callback, user_data)) 1278 return; 1279 1280 result = g_simple_async_result_new (G_OBJECT (self), 1281 callback, 1282 user_data, 1283 modem_load_unlock_retries); 1284 1285 mm_dbg ("loading unlock retries..."); 1286 qmi_client_dms_uim_get_pin_status (QMI_CLIENT_DMS (client), 1287 NULL, 1288 5, 1289 NULL, 1290 (GAsyncReadyCallback)retry_count_dms_uim_get_pin_status_ready, 1291 result); 1292} 1293 1294/*****************************************************************************/ 1295/* Load supported bands (Modem interface) */ 1296 1297static GArray * 1298modem_load_supported_bands_finish (MMIfaceModem *_self, 1299 GAsyncResult *res, 1300 GError **error) 1301{ 1302 MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self); 1303 1304 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) 1305 return NULL; 1306 1307 if (self->priv->supported_bands) 1308 g_array_unref (self->priv->supported_bands); 1309 1310 /* Cache the supported bands value */ 1311 self->priv->supported_bands = g_array_ref (g_simple_async_result_get_op_res_gpointer ( 1312 G_SIMPLE_ASYNC_RESULT (res))); 1313 1314 return g_array_ref (self->priv->supported_bands); 1315} 1316 1317static void 1318dms_get_band_capabilities_ready (QmiClientDms *client, 1319 GAsyncResult *res, 1320 GSimpleAsyncResult *simple) 1321{ 1322 QmiMessageDmsGetBandCapabilitiesOutput *output; 1323 GError *error = NULL; 1324 1325 output = qmi_client_dms_get_band_capabilities_finish (client, res, &error); 1326 if (!output) { 1327 g_prefix_error (&error, "QMI operation failed: "); 1328 g_simple_async_result_take_error (simple, error); 1329 } else if (!qmi_message_dms_get_band_capabilities_output_get_result (output, &error)) { 1330 g_prefix_error (&error, "Couldn't get band capabilities: "); 1331 g_simple_async_result_take_error (simple, error); 1332 } else { 1333 GArray *mm_bands; 1334 QmiDmsBandCapability qmi_bands = 0; 1335 QmiDmsLteBandCapability qmi_lte_bands = 0; 1336 1337 qmi_message_dms_get_band_capabilities_output_get_band_capability ( 1338 output, 1339 &qmi_bands, 1340 NULL); 1341 qmi_message_dms_get_band_capabilities_output_get_lte_band_capability ( 1342 output, 1343 &qmi_lte_bands, 1344 NULL); 1345 1346 mm_bands = mm_modem_bands_from_qmi_band_capabilities (qmi_bands, qmi_lte_bands); 1347 1348 if (mm_bands->len == 0) { 1349 g_array_unref (mm_bands); 1350 g_simple_async_result_set_error (simple, 1351 MM_CORE_ERROR, 1352 MM_CORE_ERROR…
Large files files are truncated, but you can click here to view the full file