summaryrefslogtreecommitdiff
path: root/libqcdm/src/logs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqcdm/src/logs.c')
-rw-r--r--libqcdm/src/logs.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/libqcdm/src/logs.c b/libqcdm/src/logs.c
new file mode 100644
index 00000000..91152c42
--- /dev/null
+++ b/libqcdm/src/logs.c
@@ -0,0 +1,183 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <endian.h>
+
+#include "log-items.h"
+#include "logs.h"
+#include "errors.h"
+#include "dm-commands.h"
+#include "result-private.h"
+#include "utils.h"
+
+
+/**********************************************************************/
+
+static qcdmbool
+check_log_item (const char *buf, size_t len, uint16_t log_code, size_t min_len, int *out_error)
+{
+ DMCmdLog *log_cmd = (DMCmdLog *) buf;
+
+ if (len < sizeof (DMCmdLog)) {
+ qcdm_err (0, "DM log item malformed (must be at least %zu bytes in length)", sizeof (DMCmdLog));
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_MALFORMED;
+ return FALSE;
+ }
+
+ if (buf[0] != DIAG_CMD_LOG) {
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_UNEXPECTED;
+ return FALSE;
+ }
+
+ if (le16toh (log_cmd->log_code) != log_code) {
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_UNEXPECTED;
+ return FALSE;
+ }
+
+ if (len < sizeof (DMCmdLog) + min_len) {
+ qcdm_err (0, "DM log item response not long enough (got %zu, expected "
+ "at least %zu).", len, sizeof (DMCmdLog) + min_len);
+ if (out_error)
+ *out_error = -QCDM_ERROR_RESPONSE_BAD_LENGTH;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**********************************************************************/
+
+#define PILOT_SETS_LOG_ACTIVE_SET "active-set"
+#define PILOT_SETS_LOG_CANDIDATE_SET "candidate-set"
+#define PILOT_SETS_LOG_REMAINING_SET "remaining-set"
+
+static const char *
+set_num_to_str (uint32_t num)
+{
+ if (num == QCDM_LOG_ITEM_EVDO_PILOT_SETS_V2_TYPE_ACTIVE)
+ return PILOT_SETS_LOG_ACTIVE_SET;
+ if (num == QCDM_LOG_ITEM_EVDO_PILOT_SETS_V2_TYPE_CANDIDATE)
+ return PILOT_SETS_LOG_CANDIDATE_SET;
+ if (num == QCDM_LOG_ITEM_EVDO_PILOT_SETS_V2_TYPE_REMAINING)
+ return PILOT_SETS_LOG_REMAINING_SET;
+ return NULL;
+}
+
+QcdmResult *
+qcdm_log_item_evdo_pilot_sets_v2_new (const char *buf, size_t len, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMLogItemEvdoPilotSetsV2 *pilot_sets;
+ DMCmdLog *log_cmd = (DMCmdLog *) buf;
+ size_t sets_len;
+
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_log_item (buf, len, DM_LOG_ITEM_EVDO_PILOT_SETS_V2, sizeof (DMLogItemEvdoPilotSetsV2), out_error))
+ return NULL;
+
+ pilot_sets = (DMLogItemEvdoPilotSetsV2 *) log_cmd->data;
+
+ result = qcdm_result_new ();
+
+ sets_len = pilot_sets->active_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot);
+ if (sets_len > 0) {
+ qcdm_result_add_u8_array (result,
+ PILOT_SETS_LOG_ACTIVE_SET,
+ (const uint8_t *) &pilot_sets->sets[0],
+ sets_len);
+ }
+
+ sets_len = pilot_sets->candidate_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot);
+ if (sets_len > 0) {
+ qcdm_result_add_u8_array (result,
+ PILOT_SETS_LOG_CANDIDATE_SET,
+ (const uint8_t *) &pilot_sets->sets[pilot_sets->active_count],
+ sets_len);
+ }
+
+ sets_len = pilot_sets->remaining_count * sizeof (DMLogItemEvdoPilotSetsV2Pilot);
+ if (sets_len > 0) {
+ qcdm_result_add_u8_array (result,
+ PILOT_SETS_LOG_REMAINING_SET,
+ (const uint8_t *) &pilot_sets->sets[pilot_sets->active_count + pilot_sets->candidate_count],
+ sets_len);
+ }
+
+ return result;
+
+}
+
+qcdmbool
+qcdm_log_item_evdo_pilot_sets_v2_get_num (QcdmResult *result,
+ uint32_t set_type,
+ uint32_t *out_num)
+{
+ const char *set_name;
+ const uint8_t *array = NULL;
+ size_t array_len = 0;
+
+ qcdm_return_val_if_fail (result != NULL, FALSE);
+
+ set_name = set_num_to_str (set_type);
+ qcdm_return_val_if_fail (set_name != NULL, FALSE);
+
+ if (qcdm_result_get_u8_array (result, set_name, &array, &array_len))
+ return FALSE;
+
+ *out_num = array_len / sizeof (DMLogItemEvdoPilotSetsV2Pilot);
+ return TRUE;
+}
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+qcdmbool
+qcdm_log_item_evdo_pilot_sets_v2_get_pilot (QcdmResult *result,
+ uint32_t set_type,
+ uint32_t num,
+ uint32_t *out_pilot_pn,
+ uint32_t *out_pilot_energy,
+ int32_t *out_rssi_dbm)
+{
+ const char *set_name;
+ DMLogItemEvdoPilotSetsV2Pilot *pilot;
+ const uint8_t *array = NULL;
+ size_t array_len = 0;
+
+ qcdm_return_val_if_fail (result != NULL, FALSE);
+
+ set_name = set_num_to_str (set_type);
+ qcdm_return_val_if_fail (set_name != NULL, FALSE);
+
+ if (qcdm_result_get_u8_array (result, set_name, &array, &array_len))
+ return FALSE;
+
+ qcdm_return_val_if_fail (num < array_len / sizeof (DMLogItemEvdoPilotSetsV2Pilot), FALSE);
+
+ pilot = (DMLogItemEvdoPilotSetsV2Pilot *) &array[num * sizeof (DMLogItemEvdoPilotSetsV2Pilot)];
+ *out_pilot_pn = le16toh (pilot->pilot_pn);
+ *out_pilot_energy = le16toh (pilot->pilot_energy);
+ *out_rssi_dbm = (int32_t) (-110.0 + (MAX (le16toh (pilot->pilot_energy) - 50, 0) / 14.0));
+ return TRUE;
+}
+
+/**********************************************************************/