aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-02-13 14:12:47 -0600
committerDan Williams <dcbw@redhat.com>2013-04-18 10:23:51 -0500
commit31edcdaf9a40714229e54f99e2e9956121ef372f (patch)
treeef3ad0f4bb60fd31769f7804fb96f44d2a486784
parentb54423f6fb6938306fa2c8068855278797e515d9 (diff)
broadband-modem: update HDR signal strength from EVDO Pilot Sets log items
-rw-r--r--src/mm-broadband-modem.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 92b2050b..75c8e6af 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -47,6 +47,7 @@
#include "mm-qcdm-serial-port.h"
#include "libqcdm/src/errors.h"
#include "libqcdm/src/commands.h"
+#include "libqcdm/src/log-items.h"
static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
@@ -58,6 +59,8 @@ static void iface_modem_messaging_init (MMIfaceModemMessaging *iface);
static void iface_modem_time_init (MMIfaceModemTime *iface);
static void iface_modem_firmware_init (MMIfaceModemFirmware *iface);
+static MMIfaceModemCdma *iface_modem_cdma_parent;
+
G_DEFINE_TYPE_EXTENDED (MMBroadbandModem, mm_broadband_modem, MM_TYPE_BASE_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
@@ -152,6 +155,7 @@ struct _MMBroadbandModemPrivate {
gboolean modem_cdma_cdma1x_network_supported;
gboolean modem_cdma_evdo_network_supported;
GCancellable *modem_cdma_pending_registration_cancellable;
+ guint cdma_log_id;
/* Implementation helpers */
gboolean checked_sprint_support;
gboolean has_spservice;
@@ -6048,6 +6052,274 @@ modem_cdma_load_meid (MMIfaceModemCdma *self,
}
/*****************************************************************************/
+/* Unsolicited event handling (CDMA interface) */
+
+#define LOG_ENABLE_TAG "log-enable"
+#define DM_LOG_ITEM_EVDO_PILOT_SETS_V2 0x108B
+
+static void
+cdma_log_handler (MMQcdmSerialPort *port,
+ guint log_code,
+ const GByteArray *data,
+ MMBroadbandModem *self)
+{
+ QcdmResult *result;
+ int err;
+ u_int32_t num = 0;
+ u_int32_t pilot_pn = 0;
+ u_int32_t energy = 0;
+ float db = 0;
+ u_int32_t band_class = 0;
+ u_int32_t channel = 0;
+ u_int32_t window_center = 0;
+
+ if (log_code != DM_LOG_ITEM_EVDO_PILOT_SETS_V2)
+ return;
+
+ result = qcdm_log_item_evdo_pilot_sets_v2_result ((const char *) data->data,
+ data->len,
+ &err);
+ if (!result) {
+ mm_dbg ("Failed to parse QCDM EVDO Pilot Sets V2 log item: %d", err);
+ return;
+ }
+
+ /* We only care about active pilots */
+ if (!qcdm_log_item_evdo_pilot_sets_v2_result_get_num (result,
+ QCDM_LOG_ITEM_PILOT_SET_TYPE_ACTIVE,
+ &num)) {
+ mm_dbg ("Failed to get QCDM EVDO Active Set pilots");
+ goto out;
+ }
+
+ if (num == 0) {
+ mm_dbg ("No QCDM EVDO Active Set pilots");
+ goto out;
+ }
+
+ if (!qcdm_log_item_evdo_pilot_sets_result_get_pilot (result,
+ QCDM_LOG_ITEM_PILOT_SET_TYPE_ACTIVE,
+ 0,
+ &pilot_pn,
+ &energy,
+ &db,
+ &band_class,
+ &channel,
+ &window_center)) {
+ mm_dbg ("Failed to read QCDM EVDO Active Set pilot 0");
+ goto out;
+ }
+
+ mm_dbg ("EVDO Active Set Pilot: PN:%d E:%d dB:%f BC:%d C:%d WC:%d",
+ pilot_pn, energy, db, band_class, channel, window_center);
+
+out:
+ qcdm_result_unref (result);
+}
+
+static gboolean
+modem_cdma_enable_disable_unsolicited_events_finish (MMIfaceModemCdma *cdma,
+ GAsyncResult *res,
+ GError **error)
+{
+ MMBroadbandModem *self = MM_BROADBAND_MODEM (cdma);
+ gboolean enable = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (res), LOG_ENABLE_TAG));
+ MMQcdmSerialPort *port;
+
+ port = mm_base_modem_peek_port_qcdm (MM_BASE_MODEM (self));
+ g_assert (port);
+
+ /* remove any existing log handler */
+ if (self->priv->cdma_log_id) {
+ g_signal_handler_disconnect (port, self->priv->cdma_log_id);
+ self->priv->cdma_log_id = 0;
+ }
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return FALSE;
+
+ /* Enable log handler if log messages are being enabled */
+ if (enable) {
+ self->priv->cdma_log_id = g_signal_connect (port,
+ QCDM_SERIAL_PORT_LOG_ITEM,
+ (GCallback) cdma_log_handler,
+ self);
+ }
+
+ return TRUE;
+}
+
+static void
+cdma_set_log_config_ready (MMQcdmSerialPort *port,
+ GByteArray *response,
+ GError *error,
+ GSimpleAsyncResult *simple)
+{
+ QcdmResult *result;
+ gint err = QCDM_SUCCESS;
+
+ if (error) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ return;
+ }
+
+ /* Parse the response */
+ result = qcdm_cmd_log_config_set_mask_result ((const gchar *) response->data,
+ response->len,
+ &err);
+ if (!result) {
+ g_simple_async_result_set_error (simple,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Failed to parse QCDM log config command result: %d",
+ err);
+ g_simple_async_result_complete (simple);
+ return;
+ }
+
+ g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+ g_simple_async_result_complete (simple);
+}
+
+static void
+cdma_get_log_config_ready (MMQcdmSerialPort *port,
+ GByteArray *response,
+ GError *error,
+ GSimpleAsyncResult *simple)
+{
+ QcdmResult *result;
+ gint err = QCDM_SUCCESS;
+ GByteArray *set_log;
+ u_int32_t num_items;
+ const u_int16_t *items = NULL;
+ size_t items_len = 0;
+ u_int16_t *new_items;
+ gboolean enable;
+ guint i, j;
+
+ if (error) {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete (simple);
+ return;
+ }
+
+ /* Parse the response */
+ result = qcdm_cmd_log_config_get_mask_result ((const gchar *) response->data,
+ response->len,
+ &err);
+ if (!result) {
+ g_simple_async_result_set_error (simple,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Failed to parse QCDM log config command result: %d",
+ err);
+ g_simple_async_result_complete (simple);
+ return;
+ }
+
+ enable = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (simple), LOG_ENABLE_TAG));
+
+ qcdm_result_get_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS, &num_items);
+ new_items = g_new0 (guint16, num_items + 2);
+
+ qcdm_result_get_u16_array (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS, &items, &items_len);
+ for (i = 0, j = 0; i < items_len; i++) {
+ if (enable == FALSE && items[i] != DM_LOG_ITEM_EVDO_PILOT_SETS_V2)
+ new_items[j++] = items[i];
+ }
+
+ if (enable)
+ new_items[j++] = DM_LOG_ITEM_EVDO_PILOT_SETS_V2;
+ new_items[j++] = 0;
+
+ qcdm_result_unref (result);
+
+ /* Send the updated log mask to the modem */
+ set_log = g_byte_array_sized_new (600);
+ set_log->len = qcdm_cmd_log_config_set_mask_new ((gchar *) set_log->data, 600, 0x01, new_items);
+ g_assert (set_log->len);
+ g_free (new_items);
+
+ mm_qcdm_serial_port_queue_command (port,
+ set_log,
+ 3,
+ NULL,
+ (MMQcdmSerialResponseFn) cdma_set_log_config_ready,
+ simple);
+}
+
+static void
+cdma_get_log_config (MMBroadbandModem *self,
+ gboolean enable,
+ GSimpleAsyncResult *simple)
+{
+ GByteArray *get_log;
+ MMQcdmSerialPort *port;
+
+ port = mm_base_modem_peek_port_qcdm (MM_BASE_MODEM (self));
+ g_assert (port);
+
+ g_object_set_data (G_OBJECT (simple), LOG_ENABLE_TAG, GUINT_TO_POINTER (enable));
+
+ /* Get existing mask for CDMA/EVDO equip ID */
+ get_log = g_byte_array_sized_new (550);
+ get_log->len = qcdm_cmd_log_config_get_mask_new ((gchar *) get_log->data, 520, 0x01);
+ g_assert (get_log->len);
+
+ mm_qcdm_serial_port_queue_command (port,
+ get_log,
+ 3,
+ NULL,
+ (MMQcdmSerialResponseFn) cdma_get_log_config_ready,
+ simple);
+}
+
+static void
+modem_cdma_enable_unsolicited_events (MMIfaceModemCdma *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ modem_cdma_enable_unsolicited_events);
+
+ if (mm_base_modem_peek_port_qcdm (MM_BASE_MODEM (self))) {
+ /* Enable CDMA/EVDO related log messages */
+ cdma_get_log_config (MM_BROADBAND_MODEM (self), TRUE, result);
+ } else {
+ g_simple_async_result_set_op_res_gboolean (result, TRUE);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ }
+}
+
+static void
+modem_cdma_disable_unsolicited_events (MMIfaceModemCdma *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ modem_cdma_disable_unsolicited_events);
+
+ if (mm_base_modem_peek_port_qcdm (MM_BASE_MODEM (self))) {
+ /* Disable CDMA/EVDO related log messages */
+ cdma_get_log_config (MM_BROADBAND_MODEM (self), FALSE, result);
+ } else {
+ g_simple_async_result_set_op_res_gboolean (result, TRUE);
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ }
+}
+
+/*****************************************************************************/
/* HDR state check (CDMA interface) */
typedef struct {
@@ -9417,12 +9689,18 @@ iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface)
static void
iface_modem_cdma_init (MMIfaceModemCdma *iface)
{
+ iface_modem_cdma_parent = g_type_interface_peek_parent (iface);
+
/* Initialization steps */
iface->load_esn = modem_cdma_load_esn;
iface->load_esn_finish = modem_cdma_load_esn_finish;
iface->load_meid = modem_cdma_load_meid;
iface->load_meid_finish = modem_cdma_load_meid_finish;
+ /* Enabling steps */
+ iface->enable_unsolicited_events = modem_cdma_enable_unsolicited_events;
+ iface->enable_unsolicited_events_finish = modem_cdma_enable_disable_unsolicited_events_finish;
+
/* Registration check steps */
iface->setup_registration_checks = modem_cdma_setup_registration_checks;
iface->setup_registration_checks_finish = modem_cdma_setup_registration_checks_finish;
@@ -9440,6 +9718,10 @@ iface_modem_cdma_init (MMIfaceModemCdma *iface)
/* Additional actions */
iface->register_in_network = modem_cdma_register_in_network;
iface->register_in_network_finish = modem_cdma_register_in_network_finish;
+
+ /* Disabling steps */
+ iface->disable_unsolicited_events = modem_cdma_disable_unsolicited_events;
+ iface->disable_unsolicited_events_finish = modem_cdma_enable_disable_unsolicited_events_finish;
}
static void