PageRenderTime 57ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 2ms

/src/mm-broadband-modem-qmi.c

https://bitbucket.org/accelecon/modemmanager
C | 7658 lines | 6171 code | 1080 blank | 407 comment | 636 complexity | 5f40a7f99878fcded4c8cbb7d20245ec MD5 | raw file
Possible License(s): GPL-2.0

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

Large files files are truncated, but you can click here to view the full file