diff options
57 files changed, 4527 insertions, 662 deletions
@@ -33,6 +33,8 @@ test/lsudev src/tests/test-modem-helpers policy/org.freedesktop.modem-manager.policy +libqcdm/tests/test-qcdm + po/Makefile.in.in po/POTFILES po/stamp-it diff --git a/Makefile.am b/Makefile.am index a25308df..c2639508 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,7 @@ all: $(GENERATED_FILES) CLEANFILES = $(GENERATED_FILES) endif -SUBDIRS = marshallers src plugins introspection po test +SUBDIRS = marshallers libqcdm src plugins introspection po policy test if WITH_POLKIT SUBDIRS += policy diff --git a/configure.ac b/configure.ac index d636cea5..6f6621d7 100644 --- a/configure.ac +++ b/configure.ac @@ -113,6 +113,9 @@ NM_COMPILER_WARNINGS AC_CONFIG_FILES([ Makefile marshallers/Makefile +libqcdm/Makefile +libqcdm/src/Makefile +libqcdm/tests/Makefile src/Makefile src/tests/Makefile plugins/Makefile diff --git a/libqcdm/Makefile.am b/libqcdm/Makefile.am new file mode 100644 index 00000000..77f28d7a --- /dev/null +++ b/libqcdm/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS=src tests + diff --git a/libqcdm/src/Makefile.am b/libqcdm/src/Makefile.am new file mode 100644 index 00000000..5cc05682 --- /dev/null +++ b/libqcdm/src/Makefile.am @@ -0,0 +1,42 @@ +noinst_LTLIBRARIES = libqcdm.la libqcdm-test.la + + +libqcdm_la_CPPFLAGS = \ + $(MM_CFLAGS) + +libqcdm_la_SOURCES = \ + dm-commands.h \ + nv-items.h \ + com.c \ + com.h \ + commands.c \ + commands.h \ + error.c \ + error.h \ + result.c \ + result.h \ + result-private.h \ + utils.c \ + utils.h + +libqcdm_la_LIBADD = \ + $(MM_LIBS) + +libqcdm_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libqcdm.ver \ + -version-info "0:0:0" + + +########################################### +# Test library without symbol versioning +########################################### + +libqcdm_test_la_CPPFLAGS = \ + $(MM_CFLAGS) + +libqcdm_test_la_SOURCES = \ + utils.c \ + utils.h + +libqcdm_test_la_LIBADD = \ + $(MM_LIBS) + diff --git a/libqcdm/src/com.c b/libqcdm/src/com.c new file mode 100644 index 00000000..59f2c6f8 --- /dev/null +++ b/libqcdm/src/com.c @@ -0,0 +1,62 @@ +/* -*- 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 <errno.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <string.h> +#include <termio.h> + +#include "com.h" +#include "error.h" + +gboolean +qcdm_port_setup (int fd, GError **error) +{ + struct termio stbuf; + + g_type_init (); + + errno = 0; + memset (&stbuf, 0, sizeof (struct termio)); + if (ioctl (fd, TCGETA, &stbuf) != 0) { + g_set_error (error, + QCDM_SERIAL_ERROR, QCDM_SERIAL_CONFIG_FAILED, + "TCGETA error: %d", errno); + } + + stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB); + stbuf.c_iflag &= ~(HUPCL | IUTF8 | IUCLC | ISTRIP | IXON | ICRNL); + stbuf.c_oflag &= ~(OPOST | OCRNL | ONLCR | OLCUC | ONLRET); + stbuf.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK | ECHONL); + stbuf.c_lflag &= ~(NOFLSH | XCASE | TOSTOP | ECHOPRT | ECHOCTL | ECHOKE); + stbuf.c_cc[VMIN] = 1; + stbuf.c_cc[VTIME] = 0; + stbuf.c_cc[VEOF] = 1; + stbuf.c_cflag |= (B115200 | CS8 | CREAD | 0 | 0); /* No parity, 1 stop bit */ + + errno = 0; + if (ioctl (fd, TCSETA, &stbuf) < 0) { + g_set_error (error, + QCDM_SERIAL_ERROR, QCDM_SERIAL_CONFIG_FAILED, + "TCSETA error: %d", errno); + return FALSE; + } + + return TRUE; +} + diff --git a/libqcdm/src/com.h b/libqcdm/src/com.h new file mode 100644 index 00000000..97561d03 --- /dev/null +++ b/libqcdm/src/com.h @@ -0,0 +1,25 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_COM_H +#define LIBQCDM_COM_H + +#include <glib.h> + +gboolean qcdm_port_setup (int fd, GError **error); + +#endif /* LIBQCDM_COM_H */ diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c new file mode 100644 index 00000000..611a0b1d --- /dev/null +++ b/libqcdm/src/commands.c @@ -0,0 +1,497 @@ +/* -*- 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 "commands.h" +#include "error.h" +#include "dm-commands.h" +#include "nv-items.h" +#include "result-private.h" +#include "utils.h" + +/* + * utils_bin2hexstr + * + * Convert a byte-array into a hexadecimal string. + * + * Code originally by Alex Larsson <alexl@redhat.com> and + * copyright Red Hat, Inc. under terms of the LGPL. + * + */ +static char * +bin2hexstr (const guint8 *bytes, int len) +{ + static char hex_digits[] = "0123456789abcdef"; + char *result; + int i; + gsize buflen = (len * 2) + 1; + + g_return_val_if_fail (bytes != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */ + + result = g_malloc0 (buflen); + for (i = 0; i < len; i++) { + result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf]; + result[2*i+1] = hex_digits[bytes[i] & 0xf]; + } + result[buflen - 1] = '\0'; + return result; +} + +static gboolean +check_command (const char *buf, gsize len, guint8 cmd, gsize min_len, GError **error) +{ + if (len < 1) { + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_MALFORMED_RESPONSE, + "DM command response malformed (must be at least 1 byte in length)"); + return FALSE; + } + + switch (buf[0]) { + case DIAG_CMD_BAD_CMD: + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND, + "DM command %d unknown or unimplemented by the device", + cmd); + return FALSE; + case DIAG_CMD_BAD_PARM: + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_PARAMETER, + "DM command %d contained invalid parameter", + cmd); + return FALSE; + case DIAG_CMD_BAD_LEN: + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_LENGTH, + "DM command %d was the wrong size", + cmd); + return FALSE; + case DIAG_CMD_BAD_DEV: + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_NOT_ACCEPTED, + "DM command %d was not accepted by the device", + cmd); + return FALSE; + case DIAG_CMD_BAD_MODE: + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_MODE, + "DM command %d not allowed in the current device mode", + cmd); + return FALSE; + default: + break; + } + + if (buf[0] != cmd) { + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_UNEXPECTED, + "Unexpected DM command response (expected %d, got %d)", + cmd, buf[0]); + return FALSE; + } + + if (len < min_len) { + g_set_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_LENGTH, + "DM command %d response not long enough (got %zu, expected " + "at least %zu).", cmd, len, min_len); + return FALSE; + } + + return TRUE; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_version_info_new (char *buf, gsize len, GError **error) +{ + char cmdbuf[3]; + DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0]; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (cmd)); + cmd->code = DIAG_CMD_VERSION_INFO; + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_version_info_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdVersionInfoRsp *rsp = (DMCmdVersionInfoRsp *) buf; + char tmp[12]; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_VERSION_INFO, sizeof (DMCmdVersionInfoRsp), error)) + return NULL; + + result = qcdm_result_new (); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->comp_date) <= sizeof (tmp)); + memcpy (tmp, rsp->comp_date, sizeof (rsp->comp_date)); + qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_COMP_DATE, tmp); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->comp_time) <= sizeof (tmp)); + memcpy (tmp, rsp->comp_time, sizeof (rsp->comp_time)); + qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_COMP_TIME, tmp); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->rel_date) <= sizeof (tmp)); + memcpy (tmp, rsp->rel_date, sizeof (rsp->rel_date)); + qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_RELEASE_DATE, tmp); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->rel_time) <= sizeof (tmp)); + memcpy (tmp, rsp->rel_time, sizeof (rsp->rel_time)); + qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_RELEASE_TIME, tmp); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->model) <= sizeof (tmp)); + memcpy (tmp, rsp->model, sizeof (rsp->model)); + qcdm_result_add_string (result, QCDM_CMD_VERSION_INFO_ITEM_MODEL, tmp); + + return result; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_esn_new (char *buf, gsize len, GError **error) +{ + char cmdbuf[3]; + DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0]; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (cmd)); + cmd->code = DIAG_CMD_ESN; + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_esn_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdEsnRsp *rsp = (DMCmdEsnRsp *) buf; + char *tmp; + guint8 swapped[4]; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_ESN, sizeof (DMCmdEsnRsp), error)) + return NULL; + + result = qcdm_result_new (); + + /* Convert the ESN from binary to a hex string; it's LE so we have to + * swap it to get the correct ordering. + */ + swapped[0] = rsp->esn[3]; + swapped[1] = rsp->esn[2]; + swapped[2] = rsp->esn[1]; + swapped[3] = rsp->esn[0]; + + tmp = bin2hexstr (&swapped[0], sizeof (swapped)); + qcdm_result_add_string (result, QCDM_CMD_ESN_ITEM_ESN, tmp); + g_free (tmp); + + return result; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_cdma_status_new (char *buf, gsize len, GError **error) +{ + char cmdbuf[3]; + DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0]; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (cmd)); + cmd->code = DIAG_CMD_STATUS; + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_cdma_status_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdStatusRsp *rsp = (DMCmdStatusRsp *) buf; + char *tmp; + guint8 swapped[4]; + guint32 tmp_num; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_STATUS, sizeof (DMCmdStatusRsp), error)) + return NULL; + + result = qcdm_result_new (); + + /* Convert the ESN from binary to a hex string; it's LE so we have to + * swap it to get the correct ordering. + */ + swapped[0] = rsp->esn[3]; + swapped[1] = rsp->esn[2]; + swapped[2] = rsp->esn[1]; + swapped[3] = rsp->esn[0]; + + tmp = bin2hexstr (&swapped[0], sizeof (swapped)); + qcdm_result_add_string (result, QCDM_CMD_CDMA_STATUS_ITEM_ESN, tmp); + g_free (tmp); + + tmp_num = (guint32) GUINT16_FROM_LE (rsp->cdma_rx_state); + qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, tmp_num); + + tmp_num = (guint32) GUINT16_FROM_LE (rsp->entry_reason); + qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON, tmp_num); + + tmp_num = (guint32) GUINT16_FROM_LE (rsp->curr_chan); + qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL, tmp_num); + + qcdm_result_add_uint8 (result, QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL, rsp->cdma_code_chan); + + tmp_num = (guint32) GUINT16_FROM_LE (rsp->pilot_base); + qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE, tmp_num); + + tmp_num = (guint32) GUINT16_FROM_LE (rsp->sid); + qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, tmp_num); + + tmp_num = (guint32) GUINT16_FROM_LE (rsp->nid); + qcdm_result_add_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_NID, tmp_num); + + return result; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_sw_version_new (char *buf, gsize len, GError **error) +{ + char cmdbuf[3]; + DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0]; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (cmd)); + cmd->code = DIAG_CMD_SW_VERSION; + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_sw_version_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdSwVersionRsp *rsp = (DMCmdSwVersionRsp *) buf; + char tmp[25]; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_SW_VERSION, sizeof (*rsp), error)) + return NULL; + + result = qcdm_result_new (); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->version) <= sizeof (tmp)); + memcpy (tmp, rsp->version, sizeof (rsp->version)); + qcdm_result_add_string (result, QCDM_CMD_SW_VERSION_ITEM_VERSION, tmp); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->comp_date) <= sizeof (tmp)); + memcpy (tmp, rsp->comp_date, sizeof (rsp->comp_date)); + qcdm_result_add_string (result, QCDM_CMD_SW_VERSION_ITEM_COMP_DATE, tmp); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (rsp->comp_time) <= sizeof (tmp)); + memcpy (tmp, rsp->comp_time, sizeof (rsp->comp_time)); + qcdm_result_add_string (result, QCDM_CMD_SW_VERSION_ITEM_COMP_TIME, tmp); + + return result; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_nv_get_mdn_new (char *buf, gsize len, guint8 profile, GError **error) +{ + char cmdbuf[sizeof (DMCmdNVReadWrite) + 2]; + DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0]; + DMNVItemMdn *req; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (*cmd)); + cmd->code = DIAG_CMD_NV_READ; + cmd->nv_item = GUINT16_TO_LE (DIAG_NV_DIR_NUMBER); + + req = (DMNVItemMdn *) &cmd->data[0]; + req->profile = profile; + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_nv_get_mdn_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf; + DMNVItemMdn *mdn; + char tmp[11]; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), error)) + return NULL; + + mdn = (DMNVItemMdn *) &rsp->data[0]; + + result = qcdm_result_new (); + + qcdm_result_add_uint8 (result, QCDM_CMD_NV_GET_MDN_ITEM_PROFILE, mdn->profile); + + memset (tmp, 0, sizeof (tmp)); + g_assert (sizeof (mdn->mdn) <= sizeof (tmp)); + memcpy (tmp, mdn->mdn, sizeof (mdn->mdn)); + qcdm_result_add_string (result, QCDM_CMD_NV_GET_MDN_ITEM_MDN, tmp); + + return result; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_cm_subsys_state_info_new (char *buf, gsize len, GError **error) +{ + char cmdbuf[sizeof (DMCmdSubsysHeader) + 2]; + DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0]; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (cmd)); + cmd->code = DIAG_CMD_SUBSYS; + cmd->subsys_id = DIAG_SUBSYS_CM; + cmd->subsys_cmd = GUINT16_TO_LE (DIAG_SUBSYS_CM_STATE_INFO); + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_cm_subsys_state_info_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdSubsysCMStateInfoRsp *rsp = (DMCmdSubsysCMStateInfoRsp *) buf; + guint32 tmp_num; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysCMStateInfoRsp), error)) + return NULL; + + result = qcdm_result_new (); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->call_state); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->oper_mode); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->system_mode); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->mode_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->band_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->roam_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->srv_domain_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->acq_order_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->hybrid_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF, tmp_num); + + tmp_num = (guint32) GUINT32_FROM_LE (rsp->network_sel_mode_pref); + qcdm_result_add_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF, tmp_num); + + return result; +} + +/**********************************************************************/ + +gsize +qcdm_cmd_hdr_subsys_state_info_new (char *buf, gsize len, GError **error) +{ + char cmdbuf[sizeof (DMCmdSubsysHeader) + 2]; + DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0]; + + g_return_val_if_fail (buf != NULL, 0); + g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0); + + memset (cmd, 0, sizeof (cmd)); + cmd->code = DIAG_CMD_SUBSYS; + cmd->subsys_id = DIAG_SUBSYS_HDR; + cmd->subsys_cmd = GUINT16_TO_LE (DIAG_SUBSYS_HDR_STATE_INFO); + + return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len); +} + +QCDMResult * +qcdm_cmd_hdr_subsys_state_info_result (const char *buf, gsize len, GError **error) +{ + QCDMResult *result = NULL; + DMCmdSubsysHDRStateInfoRsp *rsp = (DMCmdSubsysHDRStateInfoRsp *) buf; + + g_return_val_if_fail (buf != NULL, NULL); + + if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysHDRStateInfoRsp), error)) + return NULL; + + result = qcdm_result_new (); + + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE, rsp->at_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, rsp->session_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, rsp->almp_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE, rsp->init_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE, rsp->idle_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE, rsp->connected_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE, rsp->route_update_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE, rsp->overhead_msg_state); + qcdm_result_add_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, rsp->hdr_hybrid_mode); + + return result; +} + +/**********************************************************************/ + diff --git a/libqcdm/src/commands.h b/libqcdm/src/commands.h new file mode 100644 index 00000000..f1b6f77e --- /dev/null +++ b/libqcdm/src/commands.h @@ -0,0 +1,235 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_COMMANDS_H +#define LIBQCDM_COMMANDS_H + +#include <glib.h> + +#include "result.h" + +/**********************************************************************/ + +#define QCDM_CMD_VERSION_INFO_ITEM_COMP_DATE "comp-date" +#define QCDM_CMD_VERSION_INFO_ITEM_COMP_TIME "comp-time" +#define QCDM_CMD_VERSION_INFO_ITEM_RELEASE_DATE "release-date" +#define QCDM_CMD_VERSION_INFO_ITEM_RELEASE_TIME "release-time" +#define QCDM_CMD_VERSION_INFO_ITEM_MODEL "model" + +gsize qcdm_cmd_version_info_new (char *buf, + gsize len, + GError **error); + +QCDMResult *qcdm_cmd_version_info_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +#define QCDM_CMD_ESN_ITEM_ESN "esn" + +gsize qcdm_cmd_esn_new (char *buf, + gsize len, + GError **error); + +QCDMResult *qcdm_cmd_esn_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +/* Values for QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE */ +enum { + QCDM_CMD_CDMA_STATUS_RX_STATE_NO_SERVICE = 0, + QCDM_CMD_CDMA_STATUS_RX_STATE_IDLE = 1, + QCDM_CMD_CDMA_STATUS_RX_STATE_ACCESS = 2, + QCDM_CMD_CDMA_STATUS_RX_STATE_PAGING = 3, + QCDM_CMD_CDMA_STATUS_RX_STATE_TRAFFIC = 4, +}; + +#define QCDM_CMD_CDMA_STATUS_ITEM_ESN "esn" +#define QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE "rx-state" +#define QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON "entry-reason" +#define QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL "current-channel" +#define QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL "code-channel" +#define QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE "pilot-base" +#define QCDM_CMD_CDMA_STATUS_ITEM_SID "sid" +#define QCDM_CMD_CDMA_STATUS_ITEM_NID "nid" + +gsize qcdm_cmd_cdma_status_new (char *buf, + gsize len, + GError **error); + +QCDMResult *qcdm_cmd_cdma_status_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +/* NOTE: this command does not appear to be implemented in recent + * devices and probably returns (QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND). + */ + +#define QCDM_CMD_SW_VERSION_ITEM_VERSION "version" +#define QCDM_CMD_SW_VERSION_ITEM_COMP_DATE "comp-date" +#define QCDM_CMD_SW_VERSION_ITEM_COMP_TIME "comp-time" + +gsize qcdm_cmd_sw_version_new (char *buf, + gsize len, + GError **error); + +QCDMResult *qcdm_cmd_sw_version_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +#define QCDM_CMD_NV_GET_MDN_ITEM_PROFILE "profile" +#define QCDM_CMD_NV_GET_MDN_ITEM_MDN "mdn" + +gsize qcdm_cmd_nv_get_mdn_new (char *buf, + gsize len, + guint8 profile, + GError **error); + +QCDMResult *qcdm_cmd_nv_get_mdn_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE */ +enum { + QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE = 5 +}; + +/* Values for QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE */ +enum { + QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_NO_SERVICE = 0, + QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_AMPS = 1, + QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_CDMA = 2, + QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR = 4, + QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA = 5 +}; + +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE "call-state" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE "operating-mode" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE "system-mode" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF "mode-pref" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF "band-pref" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF "roam-pref" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF "service-domain-pref" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF "acq-order-pref" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF "hybrid-pref" +#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF "network-selection-pref" + +gsize qcdm_cmd_cm_subsys_state_info_new (char *buf, + gsize len, + GError **error); + +QCDMResult *qcdm_cmd_cm_subsys_state_info_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_INACTIVE = 0, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_ACQUISITION = 1, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_SYNC = 2, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_IDLE = 3, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_ACCESS = 4, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_CONNECTED = 5 +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSED = 0, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_SETUP = 1, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_AT_INIT = 2, /* initiated by Access Terminal */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_AN_INIT = 3, /* initiated by Access Node */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_OPEN = 4, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSING = 5 +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE (TIA-856-A section 9.2.1) */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INACTIVE = 0, /* initial state */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INIT = 1, /* terminal has yet to acquire network */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_IDLE = 2, /* network acquired but no connection */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_CONNECTED = 3, /* open connection to the network */ +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE (TIA-856-A section 9.3.1) */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_INACTIVE = 0, /* protocol waiting for ACTIVATE command */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_NET_DETERMINE = 1, /* choosing a network to operate on */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_ACQUISITION = 2, /* acquiring Forward Pilot Channel */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_SYNC = 3, /* synchronizing to Control Channel */ +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE (TIA-856-A section 9.4.1) */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_INACTIVE = 0, /* protocol waiting for ACTIVATE command */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_SLEEP = 1, /* sleeping */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_MONITOR = 2, /* monitoring the Control Channel */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_SETUP = 3, /* setting up a connection */ +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE (TIA-856-A section 9.6.1) */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_INACTIVE = 0, /* protocol waiting for ACTIVATE command */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_OPEN = 1, /* connection is open */ + QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_CLOSING = 2, /* connection is closed */ +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE (TIA-856-A section 9.7.1) */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_INACTIVE = 0, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_IDLE = 1, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_CONNECTED = 2, +}; + +/* Values for QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG (TIA-856-A section 9.9.1) */ +enum { + QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_INIT = 0, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_INACTIVE = 1, + QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_ACTIVE = 2, +}; + +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE "at-state" /* State of Access Terminal */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE "session-state" /* Current session state */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE "almp-state" /* Air Link Management Protocol (ALMP) state */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE "init-state" /* Initialization State Protocol (ISP) state */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE "idle-state" /* Idle State Protocol (IDP) state */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE "connected-state" /* Connected State Protocol (CSP) state */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE "route-update-state" /* Route Update Protocol (RUP) state */ +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE "overhead-msg-state" +#define QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE "hdr-hybrid-mode" + +gsize qcdm_cmd_hdr_subsys_state_info_new (char *buf, + gsize len, + GError **error); + +QCDMResult *qcdm_cmd_hdr_subsys_state_info_result (const char *buf, + gsize len, + GError **error); + +/**********************************************************************/ + +#endif /* LIBQCDM_COMMANDS_H */ diff --git a/libqcdm/src/dm-commands.h b/libqcdm/src/dm-commands.h new file mode 100644 index 00000000..bad9e932 --- /dev/null +++ b/libqcdm/src/dm-commands.h @@ -0,0 +1,254 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_DM_COMMANDS_H +#define LIBQCDM_DM_COMMANDS_H + +enum { + DIAG_CMD_VERSION_INFO = 0, /* Version info */ + DIAG_CMD_ESN = 1, /* ESN */ + DIAG_CMD_PEEKB = 2, /* Peek byte */ + DIAG_CMD_PEEKW = 3, /* Peek word */ + DIAG_CMD_PEEKD = 4, /* Peek dword */ + DIAG_CMD_POKEB = 5, /* Poke byte */ + DIAG_CMD_POKEW = 6, /* Poke word */ + DIAG_CMD_POKED = 7, /* Poke dword */ + DIAG_CMD_OUTP = 8, /* Byte output */ + DIAG_CMD_OUTPW = 9, /* Word output */ + DIAG_CMD_INP = 10, /* Byte input */ + DIAG_CMD_INPW = 11, /* Word input */ + DIAG_CMD_STATUS = 12, /* Station status */ + DIAG_CMD_LOGMASK = 15, /* Set logging mask */ + DIAG_CMD_LOG = 16, /* Log packet */ + DIAG_CMD_NV_PEEK = 17, /* Peek NV memory */ + DIAG_CMD_NV_POKE = 18, /* Poke NV memory */ + DIAG_CMD_BAD_CMD = 19, /* Invalid command (response) */ + DIAG_CMD_BAD_PARM = 20, /* Invalid parameter (response) */ + DIAG_CMD_BAD_LEN = 21, /* Invalid packet length (response) */ + DIAG_CMD_BAD_DEV = 22, /* Not accepted by the device (response) */ + DIAG_CMD_BAD_MODE = 24, /* Not allowed in this mode (response) */ + DIAG_CMD_TAGRAPH = 25, /* Info for TA power and voice graphs */ + DIAG_CMD_MARKOV = 26, /* Markov stats */ + DIAG_CMD_MARKOV_RESET = 27, /* Reset Markov stats */ + DIAG_CMD_DIAG_VER = 28, /* Diagnostic Monitor version */ + DIAG_CMD_TIMESTAMP = 29, /* Return a timestamp */ + DIAG_CMD_TA_PARM = 30, /* Set TA parameters */ + DIAG_CMD_MESSAGE = 31, /* Request for msg report */ + DIAG_CMD_HS_KEY = 32, /* Handset emulation -- keypress */ + DIAG_CMD_HS_LOCK = 33, /* Handset emulation -- lock or unlock */ + DIAG_CMD_HS_SCREEN = 34, /* Handset emulation -- display request */ + DIAG_CMD_PARM_SET = 36, /* Parameter download */ + DIAG_CMD_NV_READ = 38, /* Read NV item */ + DIAG_CMD_NV_WRITE = 39, /* Write NV item */ + DIAG_CMD_CONTROL = 41, /* Mode change request */ + DIAG_CMD_ERR_READ = 42, /* Error record retreival */ + DIAG_CMD_ERR_CLEAR = 43, /* Error record clear */ + DIAG_CMD_SER_RESET = 44, /* Symbol error rate counter reset */ + DIAG_CMD_SER_REPORT = 45, /* Symbol error rate counter report */ + DIAG_CMD_TEST = 46, /* Run a specified test */ + DIAG_CMD_GET_DIPSW = 47, /* Retreive the current DIP switch setting */ + DIAG_CMD_SET_DIPSW = 48, /* Write new DIP switch setting */ + DIAG_CMD_VOC_PCM_LB = 49, /* Start/Stop Vocoder PCM loopback */ + DIAG_CMD_VOC_PKT_LB = 50, /* Start/Stop Vocoder PKT loopback */ + DIAG_CMD_ORIG = 53, /* Originate a call */ + DIAG_CMD_END = 54, /* End a call */ + DIAG_CMD_SW_VERSION = 56, /* Get software version */ + DIAG_CMD_DLOAD = 58, /* Switch to downloader */ + DIAG_CMD_TMOB = 59, /* Test Mode Commands and FTM commands*/ + DIAG_CMD_STATE = 63, /* Current state of the phone */ + DIAG_CMD_PILOT_SETS = 64, /* Return all current sets of pilots */ + DIAG_CMD_SPC = 65, /* Send the Service Programming Code to unlock */ + DIAG_CMD_BAD_SPC_MODE = 66, /* Invalid NV read/write because SP is locked */ + DIAG_CMD_PARM_GET2 = 67, /* (obsolete) */ + DIAG_CMD_SERIAL_CHG = 68, /* Serial mode change */ + DIAG_CMD_PASSWORD = 70, /* Send password to unlock secure operations */ + DIAG_CMD_BAD_SEC_MODE = 71, /* Operation not allowed in this security state */ + DIAG_CMD_PRL_WRITE = 72, /* Write PRL */ + DIAG_CMD_PRL_READ = 73, /* Read PRL */ + DIAG_CMD_SUBSYS = 75, /* Subsystem commands */ + DIAG_CMD_FEATURE_QUERY = 81, + DIAG_CMD_SMS_READ = 83, /* Read SMS message out of NV memory */ + DIAG_CMD_SMS_WRITE = 84, /* Write SMS message into NV memory */ + DIAG_CMD_SUP_FER = 85, /* Frame Error Rate info on multiple channels */ + DIAG_CMD_SUP_WALSH_CODES = 86, /* Supplemental channel walsh codes */ + DIAG_CMD_SET_MAX_SUP_CH = 87, /* Sets the maximum # supplemental channels */ + DIAG_CMD_PARM_GET_IS95B = 88, /* Get parameters including SUPP and MUX2 */ + DIAG_CMD_FS_OP = 89, /* Embedded File System (EFS) operations */ + DIAG_CMD_AKEY_VERIFY = 90, /* AKEY Verification */ + DIAG_CMD_HS_BMP_SCREEN = 91, /* Handset Emulation -- Bitmap screen */ + DIAG_CMD_CONFIG_COMM = 92, /* Configure communications */ + DIAG_CMD_EXT_LOGMASK = 93, /* Extended logmask for > 32 bits */ + DIAG_CMD_EVENT_REPORT = 96, /* Static Event reporting */ + DIAG_CMD_STREAMING_CONFIG = 97, /* Load balancing etc */ + DIAG_CMD_PARM_RETRIEVE = 98, /* Parameter retrieval */ + DIAG_CMD_STATUS_SNAPSHOT = 99, /* Status snapshot */ + DIAG_CMD_RPC = 100, /* Used for RPC */ + DIAG_CMD_GET_PROPERTY = 101, + DIAG_CMD_PUT_PROPERTY = 102, + DIAG_CMD_GET_GUID = 103, /* GUID requests */ + DIAG_CMD_USER_CMD = 104, /* User callbacks */ + DIAG_CMD_GET_PERM_PROPERTY = 105, + DIAG_CMD_PUT_PERM_PROPERTY = 106, + DIAG_CMD_PERM_USER_CMD = 107, /* Permanent user callbacks */ + DIAG_CMD_GPS_SESS_CTRL = 108, /* GPS session control */ + DIAG_CMD_GPS_GRID = 109, /* GPS search grid */ + DIAG_CMD_GPS_STATISTICS = 110, + DIAG_CMD_TUNNEL = 111, /* Tunneling command code */ + DIAG_CMD_RAM_RW = 112, /* Calibration RAM control using DM */ + DIAG_CMD_CPU_RW = 113, /* Calibration CPU control using DM */ + DIAG_CMD_SET_FTM_TEST_MODE = 114, /* Field (or Factory?) Test Mode */ +}; + +/* Subsystem IDs used with DIAG_CMD_SUBSYS; these often obsolete many of + * the original DM commands. + */ +enum { + DIAG_SUBSYS_HDR = 5, /* High Data Rate (ie, EVDO) */ + DIAG_SUBSYS_GPS = 13, + DIAG_SUBSYS_SMS = 14, + DIAG_SUBSYS_CM = 15, /* Call manager */ + DIAG_SUBSYS_NW_CONTROL_6500 = 50, /* for Novatel Wireless MSM6500-based devices */ + DIAG_SUBSYS_NW_CONTROL_6800 = 250 /* for Novatel Wireless MSM6800-based devices */ +}; + +/* HDR subsystem command codes */ +enum { + DIAG_SUBSYS_HDR_STATE_INFO = 8, /* Gets EVDO state */ +}; + +enum { + DIAG_SUBSYS_CM_STATE_INFO = 0, /* Gets Call Manager state */ +}; + +/* NW_CONTROL subsystem command codes (only for Novatel Wireless devices) */ +enum { + DIAG_SUBSYS_NW_CONTROL_AT_REQUEST = 3, /* AT commands via diag */ + DIAG_SUBSYS_NW_CONTROL_AT_RESPONSE = 4, + DIAG_SUBSYS_NW_CONTROL_MODEM_STATUS = 7, /* Modem status */ + DIAG_SUBSYS_NW_CONTROL_ERI = 8, /* Extended Roaming Indicator */ + DIAG_SUBSYS_NW_CONTROL_PRL = 12, +}; + +enum { + DIAG_SUBSYS_NW_CONTROL_MODEM_STATUS_CDMA = 7, + DIAG_SUBSYS_NW_CONTROL_MODEM_STATUS_WCDMA = 20, +}; + +/* Generic DM command header */ +struct DMCmdHeader { + guint8 code; +} __attribute__ ((packed)); +typedef struct DMCmdHeader DMCmdHeader; + +/* DIAG_CMD_SUBSYS */ +struct DMCmdSubsysHeader { + guint8 code; + guint8 subsys_id; + guint16 subsys_cmd; +} __attribute__ ((packed)); +typedef struct DMCmdSubsysHeader DMCmdSubsysHeader; + +/* DIAG_CMD_NV_READ / DIAG_CMD_NV_WRITE */ +struct DMCmdNVReadWrite { + guint8 code; + guint16 nv_item; + guint8 data[128]; + guint16 status; +} __attribute__ ((packed)); +typedef struct DMCmdNVReadWrite DMCmdNVReadWrite; + +/* DIAG_CMD_VERSION_INFO */ +struct DMCmdVersionInfoRsp { + guint8 code; + char comp_date[11]; + char comp_time[8]; + char rel_date[11]; + char rel_time[8]; + char model[8]; + guint8 _unknown[8]; +} __attribute__ ((packed)); +typedef struct DMCmdVersionInfoRsp DMCmdVersionInfoRsp; + +/* DIAG_CMD_ESN */ +struct DMCmdEsnRsp { + guint8 code; + guint8 esn[4]; +} __attribute__ ((packed)); +typedef struct DMCmdEsnRsp DMCmdEsnRsp; + +/* DIAG_CMD_STATUS */ +struct DMCmdStatusRsp { + guint8 code; + guint8 _unknown[3]; + guint8 esn[4]; + guint8 _unknown2[2]; + guint8 _unknown3[8]; + guint8 _unknown4[4]; + guint16 cdma_rx_state; + guint16 entry_reason; + guint8 _unknown5[8]; + guint16 curr_chan; + guint8 cdma_code_chan; + guint16 pilot_base; + guint16 sid; + guint16 nid; + guint8 _unknown6[5]; +} __attribute__ ((packed)); +typedef struct DMCmdStatusRsp DMCmdStatusRsp; + +/* DIAG_CMD_SW_VERSION */ +struct DMCmdSwVersionRsp { + guint8 code; + char version[20]; + char comp_date[11]; + char comp_time[8]; +} __attribute__ ((packed)); +typedef struct DMCmdSwVersionRsp DMCmdSwVersionRsp; + +/* DIAG_SUBSYS_CM_STATE_INFO subsys command */ +struct DMCmdSubsysCMStateInfoRsp { + DMCmdSubsysHeader header; + guint32 call_state; + guint32 oper_mode; + guint32 system_mode; + guint32 mode_pref; + guint32 band_pref; + guint32 roam_pref; + guint32 srv_domain_pref; + guint32 acq_order_pref; + guint32 hybrid_pref; + guint32 network_sel_mode_pref; +} __attribute__ ((packed)); +typedef struct DMCmdSubsysCMStateInfoRsp DMCmdSubsysCMStateInfoRsp; + +/* DIAG_SUBSYS_HDR_STATE_INFO subsys command */ +struct DMCmdSubsysHDRStateInfoRsp { + DMCmdSubsysHeader header; + guint8 at_state; + guint8 session_state; + guint8 almp_state; + guint8 init_state; + guint8 idle_state; + guint8 connected_state; + guint8 route_update_state; + guint8 overhead_msg_state; + guint8 hdr_hybrid_mode; +} __attribute__ ((packed)); +typedef struct DMCmdSubsysHDRStateInfoRsp DMCmdSubsysHDRStateInfoRsp; + +#endif /* LIBQCDM_DM_COMMANDS_H */ + diff --git a/libqcdm/src/error.c b/libqcdm/src/error.c new file mode 100644 index 00000000..bf16b56a --- /dev/null +++ b/libqcdm/src/error.c @@ -0,0 +1,86 @@ +/* -*- 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 "error.h" + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GQuark +qcdm_serial_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) + ret = g_quark_from_static_string ("qcdm-serial-error"); + + return ret; +} + +GType +qcdm_serial_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (QCDM_SERIAL_CONFIG_FAILED, "SerialConfigFailed"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("QcdmSerialError", values); + } + + return etype; +} + +/***************************************************************/ + +GQuark +qcdm_command_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) + ret = g_quark_from_static_string ("qcdm-command-error"); + + return ret; +} + +GType +qcdm_command_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (QCDM_COMMAND_MALFORMED_RESPONSE, "QcdmCommandMalformedResponse"), + ENUM_ENTRY (QCDM_COMMAND_UNEXPECTED, "QcdmCommandUnexpected"), + ENUM_ENTRY (QCDM_COMMAND_BAD_LENGTH, "QcdmCommandBadLength"), + ENUM_ENTRY (QCDM_COMMAND_BAD_COMMAND, "QcdmCommandBadCommand"), + ENUM_ENTRY (QCDM_COMMAND_BAD_PARAMETER, "QcdmCommandBadParameter"), + ENUM_ENTRY (QCDM_COMMAND_NOT_ACCEPTED, "QcdmCommandNotAccepted"), + ENUM_ENTRY (QCDM_COMMAND_BAD_MODE, "QcdmCommandBadMode"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("QcdmCommandError", values); + } + + return etype; +} + + diff --git a/libqcdm/src/error.h b/libqcdm/src/error.h new file mode 100644 index 00000000..7098fcbe --- /dev/null +++ b/libqcdm/src/error.h @@ -0,0 +1,52 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_ERROR_H +#define LIBQCDM_ERROR_H + +#include <glib.h> +#include <glib-object.h> + +enum { + QCDM_SERIAL_CONFIG_FAILED = 0, +}; + +#define QCDM_SERIAL_ERROR (qcdm_serial_error_quark ()) +#define QCDM_TYPE_SERIAL_ERROR (qcdm_serial_error_get_type ()) + +GQuark qcdm_serial_error_quark (void); +GType qcdm_serial_error_get_type (void); + + +enum { + QCDM_COMMAND_MALFORMED_RESPONSE = 0, + QCDM_COMMAND_UNEXPECTED = 1, + QCDM_COMMAND_BAD_LENGTH = 2, + QCDM_COMMAND_BAD_COMMAND = 3, + QCDM_COMMAND_BAD_PARAMETER = 4, + QCDM_COMMAND_NOT_ACCEPTED = 5, + QCDM_COMMAND_BAD_MODE = 6 +}; + +#define QCDM_COMMAND_ERROR (qcdm_command_error_quark ()) +#define QCDM_TYPE_COMMAND_ERROR (qcdm_command_error_get_type ()) + +GQuark qcdm_command_error_quark (void); +GType qcdm_command_error_get_type (void); + +#endif /* LIBQCDM_ERROR_H */ + diff --git a/libqcdm/src/libqcdm.ver b/libqcdm/src/libqcdm.ver new file mode 100644 index 00000000..b1567e20 --- /dev/null +++ b/libqcdm/src/libqcdm.ver @@ -0,0 +1,6 @@ +{ +global: + nm_vpn_connection_new; +local: + *; +}; diff --git a/libqcdm/src/nv-items.h b/libqcdm/src/nv-items.h new file mode 100644 index 00000000..6f058121 --- /dev/null +++ b/libqcdm/src/nv-items.h @@ -0,0 +1,35 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_NV_ITEMS_H +#define LIBQCDM_NV_ITEMS_H + +enum { + DIAG_NV_DIR_NUMBER = 178, /* Mobile Directory Number (MDN) */ +}; + + +/* DIAG_NV_DIR_NUMBER */ +struct DMNVItemMdn { + guint8 profile; + guint8 mdn[10]; +} __attribute__ ((packed)); +typedef struct DMNVItemMdn DMNVItemMdn; + + +#endif /* LIBQCDM_NV_ITEMS_H */ + diff --git a/libqcdm/src/result-private.h b/libqcdm/src/result-private.h new file mode 100644 index 00000000..2a5fd5db --- /dev/null +++ b/libqcdm/src/result-private.h @@ -0,0 +1,41 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_RESULT_PRIVATE_H +#define LIBQCDM_RESULT_PRIVATE_H + +#include <glib.h> +#include "result.h" + +QCDMResult *qcdm_result_new (void); + +/* For these functions, 'key' *must* be a constant, not allocated and freed */ + +void qcdm_result_add_string (QCDMResult *result, + const char *key, + const char *str); + +void qcdm_result_add_uint8 (QCDMResult *result, + const char *key, + guint8 num); + +void qcdm_result_add_uint32 (QCDMResult *result, + const char *key, + guint32 num); + +#endif /* LIBQCDM_RESULT_PRIVATE_H */ + diff --git a/libqcdm/src/result.c b/libqcdm/src/result.c new file mode 100644 index 00000000..37898f39 --- /dev/null +++ b/libqcdm/src/result.c @@ -0,0 +1,206 @@ +/* -*- 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 <glib.h> + +#include "result.h" +#include "result-private.h" +#include "error.h" + +struct QCDMResult { + guint32 refcount; + GHashTable *hash; +}; + + +static void +gvalue_destroy (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +QCDMResult * +qcdm_result_new (void) +{ + QCDMResult *result; + + g_type_init (); + + result = g_malloc0 (sizeof (QCDMResult)); + result->hash = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, gvalue_destroy); + result->refcount = 1; + return result; +} + +QCDMResult * +qcdm_result_ref (QCDMResult *result) +{ + g_return_val_if_fail (result != NULL, NULL); + g_return_val_if_fail (result->refcount > 0, NULL); + + result->refcount++; + return result; +} + +void +qcdm_result_unref (QCDMResult *result) +{ + g_return_if_fail (result != NULL); + g_return_if_fail (result->refcount > 0); + + result->refcount--; + if (result->refcount == 0) { + g_hash_table_destroy (result->hash); + memset (result, 0, sizeof (QCDMResult)); + g_free (result); + } +} + + +void +qcdm_result_add_string (QCDMResult *result, + const char *key, + const char *str) +{ + GValue *val; + + g_return_if_fail (result != NULL); + g_return_if_fail (result->refcount > 0); + g_return_if_fail (key != NULL); + g_return_if_fail (str != NULL); + + val = g_slice_new0 (GValue); + g_value_init (val, G_TYPE_STRING); + g_value_set_string (val, str); + + g_hash_table_insert (result->hash, (gpointer) key, val); +} + +gboolean +qcdm_result_get_string (QCDMResult *result, + const char *key, + const char **out_val) +{ + GValue *val; + + g_return_val_if_fail (result != NULL, FALSE); + g_return_val_if_fail (result->refcount > 0, FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (out_val != NULL, FALSE); + g_return_val_if_fail (*out_val == NULL, FALSE); + + val = g_hash_table_lookup (result->hash, key); + if (!val) + return FALSE; + + g_warn_if_fail (G_VALUE_HOLDS_STRING (val)); + if (!G_VALUE_HOLDS_STRING (val)) + return FALSE; + + *out_val = g_value_get_string (val); + return TRUE; +} + +void +qcdm_result_add_uint8 (QCDMResult *result, + const char *key, + guint8 num) +{ + GValue *val; + + g_return_if_fail (result != NULL); + g_return_if_fail (result->refcount > 0); + g_return_if_fail (key != NULL); + + val = g_slice_new0 (GValue); + g_value_init (val, G_TYPE_UCHAR); + g_value_set_uchar (val, (unsigned char) num); + + g_hash_table_insert (result->hash, (gpointer) key, val); +} + +gboolean +qcdm_result_get_uint8 (QCDMResult *result, + const char *key, + guint8 *out_val) +{ + GValue *val; + + g_return_val_if_fail (result != NULL, FALSE); + g_return_val_if_fail (result->refcount > 0, FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (out_val != NULL, FALSE); + + val = g_hash_table_lookup (result->hash, key); + if (!val) + return FALSE; + + g_warn_if_fail (G_VALUE_HOLDS_UCHAR (val)); + if (!G_VALUE_HOLDS_UCHAR (val)) + return FALSE; + + *out_val = (guint8) g_value_get_uchar (val); + return TRUE; +} + +void +qcdm_result_add_uint32 (QCDMResult *result, + const char *key, + guint32 num) +{ + GValue *val; + + g_return_if_fail (result != NULL); + g_return_if_fail (result->refcount > 0); + g_return_if_fail (key != NULL); + + val = g_slice_new0 (GValue); + g_value_init (val, G_TYPE_UINT); + g_value_set_uint (val, num); + + g_hash_table_insert (result->hash, (gpointer) key, val); +} + +gboolean +qcdm_result_get_uint32 (QCDMResult *result, + const char *key, + guint32 *out_val) +{ + GValue *val; + + g_return_val_if_fail (result != NULL, FALSE); + g_return_val_if_fail (result->refcount > 0, FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (out_val != NULL, FALSE); + + val = g_hash_table_lookup (result->hash, key); + if (!val) + return FALSE; + + g_warn_if_fail (G_VALUE_HOLDS_UINT (val)); + if (!G_VALUE_HOLDS_UINT (val)) + return FALSE; + + *out_val = (guint32) g_value_get_uint (val); + return TRUE; +} + diff --git a/libqcdm/src/result.h b/libqcdm/src/result.h new file mode 100644 index 00000000..4912b07c --- /dev/null +++ b/libqcdm/src/result.h @@ -0,0 +1,42 @@ +/* -*- 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/>. + */ + +#ifndef LIBQCDM_RESULT_H +#define LIBQCDM_RESULT_H + +#include <glib.h> + +typedef struct QCDMResult QCDMResult; + +gboolean qcdm_result_get_string (QCDMResult *result, + const char *key, + const char **out_val); + +gboolean qcdm_result_get_uint8 (QCDMResult *result, + const char *key, + guint8 *out_val); + +gboolean qcdm_result_get_uint32 (QCDMResult *result, + const char *key, + guint32 *out_val); + +QCDMResult *qcdm_result_ref (QCDMResult *result); + +void qcdm_result_unref (QCDMResult *result); + +#endif /* LIBQCDM_RESULT_H */ + diff --git a/libqcdm/src/utils.c b/libqcdm/src/utils.c new file mode 100644 index 00000000..ab281557 --- /dev/null +++ b/libqcdm/src/utils.c @@ -0,0 +1,309 @@ +/* -*- 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 <stdio.h> +#include <sys/types.h> +#include <unistd.h> +#include <malloc.h> +#include <fcntl.h> +#include <string.h> + +#include "utils.h" + +/* QCDM protocol frames are pseudo Async HDLC frames which end with a 3-byte + * trailer. This trailer consists of the 16-bit CRC of the frame plus an ending + * "async control character" whose value is 0x7E. The frame *and* the CRC are + * escaped before adding the trailing control character so that the control + * character (0x7E) and the escape marker (0x7D) are never seen in the frame. + */ + +/* Table of CRCs for each possible byte, with a generator polynomial of 0x8408 */ +const guint16 crc_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, + 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, + 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, + 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, + 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, + 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, + 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, + 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, + 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, + 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, + 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, + 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, + 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, + 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, + 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, + 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, + 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, + 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, + 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, + 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, + 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, + 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, + 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, + 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, + 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, + 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, + 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, + 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, + 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, + 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 +}; + +/* Calculate the CRC for a buffer using a seed of 0xffff */ +guint16 +crc16 (const char *buffer, gsize len) +{ + guint16 crc = 0xffff; + + while (len--) + crc = crc_table[(crc ^ *buffer++) & 0xff] ^ (crc >> 8); + return ~crc; +} + +#define DIAG_ESC_CHAR 0x7D /* Escape sequence 1st character value */ +#define DIAG_ESC_MASK 0x20 /* Escape sequence complement value */ + +/* Performs DM escaping on inbuf putting the result into outbuf, and returns + * the final length of the buffer. + */ +gsize +dm_escape (const char *inbuf, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len) +{ + const char *src = inbuf; + char *dst = outbuf; + size_t i = inbuf_len; + + g_return_val_if_fail (inbuf != NULL, 0); + g_return_val_if_fail (inbuf_len > 0, 0); + g_return_val_if_fail (outbuf != NULL, 0); + g_return_val_if_fail (outbuf_len > inbuf_len, 0); + + /* Since escaping potentially doubles the # of bytes, short-circuit the + * length check if destination buffer is clearly large enough. Note the + * + */ + if (outbuf_len <= inbuf_len << 1) { + size_t outbuf_required = inbuf_len + 1; /* +1 for the trailing control char */ + + /* Each escaped character takes up two bytes in the output buffer */ + while (i--) { + if (*src == DIAG_CONTROL_CHAR || *src == DIAG_ESC_CHAR) + outbuf_required++; + src++; + } + + if (outbuf_len < outbuf_required) + return 0; + } + + /* Do the actual escaping. Replace both the control character and + * the escape character in the source buffer with the following sequence: + * + * <escape_char> <src_byte ^ escape_mask> + */ + src = inbuf; + i = inbuf_len; + while (i--) { + if (*src == DIAG_CONTROL_CHAR || *src == DIAG_ESC_CHAR) { + *dst++ = DIAG_ESC_CHAR; + *dst++ = *src ^ DIAG_ESC_MASK; + } else + *dst++ = *src; + src++; + } + + return (dst - outbuf); +} + +gsize +dm_unescape (const char *inbuf, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len, + gboolean *escaping) +{ + size_t i, outsize; + + g_return_val_if_fail (inbuf_len > 0, 0); + g_return_val_if_fail (outbuf_len >= inbuf_len, 0); + g_return_val_if_fail (escaping != NULL, 0); + + for (i = 0, outsize = 0; i < inbuf_len; i++) { + if (*escaping) { + outbuf[outsize++] = inbuf[i] ^ DIAG_ESC_MASK; + *escaping = FALSE; + } else if (inbuf[i] == DIAG_ESC_CHAR) + *escaping = TRUE; + else + outbuf[outsize++] = inbuf[i]; + + /* About to overrun output buffer size */ + if (outsize >= outbuf_len) + return 0; + } + + return outsize; +} + +/** + * dm_encapsulate_buffer: + * @inbuf: buffer in which a valid QCDM packet exists + * @cmd_len: size of the QCDM packet contained in @inbuf + * @inbuf_len: total size of @inbuf itself (not just the packet) + * @outbuf: buffer in which to put the encapsulated QCDM packet + * @outbuf_len: total size of @outbuf + * + * Escapes and CRCs a QCDM packet, and finally adds the trailing control + * character that denotes the end of the QCDM packet. + * + * Returns: size of the encapsulated QCDM command writted to @outbuf. + **/ +gsize +dm_encapsulate_buffer (char *inbuf, + gsize cmd_len, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len) +{ + guint16 crc; + gsize escaped_len; + + g_return_val_if_fail (inbuf != NULL, 0); + g_return_val_if_fail (cmd_len >= 1, 0); + g_return_val_if_fail (inbuf_len >= cmd_len + 2, 0); /* space for CRC */ + g_return_val_if_fail (outbuf != NULL, 0); + + crc = GUINT16_TO_LE (crc16 (inbuf, cmd_len)); + inbuf[cmd_len++] = crc & 0xFF; + inbuf[cmd_len++] = (crc >> 8) & 0xFF; + + escaped_len = dm_escape (inbuf, cmd_len, outbuf, outbuf_len); + g_return_val_if_fail (outbuf_len > escaped_len, 0); + outbuf[escaped_len++] = DIAG_CONTROL_CHAR; + + return escaped_len; +} + +/** + * dm_decapsulate_buffer: + * @inbuf: buffer in which to look for a QCDM packet + * @inbuf_len: length of valid data in @inbuf + * @outbuf: buffer in which to put decapsulated QCDM packet + * @outbuf_len: max size of @outbuf + * @out_decap_len: on success, size of the decapsulated QCDM packet + * @out_used: on either success or failure, amount of data used; caller should + * discard this much data from @inbuf before the next call to this function + * @out_need_more: when TRUE, indicates that more data is required before + * and determination about a valid QCDM packet can be made; caller should add + * more data to @inbuf before calling this function again. + * + * Attempts to retrieve, unescape, and CRC-check a QCDM packet from the given + * buffer. + * + * Returns: FALSE on error (packet was invalid or malformed, or the CRC check + * failed, etc) and places number of bytes to discard from @inbuf in @out_used. + * When TRUE, either more data is required (in which case @out_need_more will + * be TRUE), or a QCDM packet was successfully retrieved from @inbuf and the + * decapsulated packet of length @out_decap_len was placed into @outbuf. In + * all cases the caller should advance the buffer by the number of bytes + * returned in @out_used before calling this function again. + **/ +gboolean +dm_decapsulate_buffer (const char *inbuf, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len, + gsize *out_decap_len, + gsize *out_used, + gboolean *out_need_more) +{ + gboolean escaping = FALSE; + gsize i, pkt_len = 0, unesc_len; + guint16 crc, pkt_crc; + + g_return_val_if_fail (inbuf != NULL, FALSE); + g_return_val_if_fail (outbuf != NULL, FALSE); + g_return_val_if_fail (outbuf_len > 0, FALSE); + g_return_val_if_fail (out_decap_len != NULL, FALSE); + g_return_val_if_fail (out_used != NULL, FALSE); + g_return_val_if_fail (out_need_more != NULL, FALSE); + + *out_decap_len = 0; + *out_used = 0; + *out_need_more = FALSE; + + if (inbuf_len < 4) { + *out_need_more = TRUE; + return TRUE; + } + + /* Find the async control character */ + for (i = 0; i < inbuf_len; i++) { + if (inbuf[i] == DIAG_CONTROL_CHAR) { + /* If the control character shows up in a position before a valid + * QCDM packet length (4), the packet is malformed. + */ + if (i < 3) { + /* Tell the caller to advance the buffer past the control char */ + *out_used = i + 1; + return FALSE; + } + + pkt_len = i; + break; + } + } + + /* No control char yet, need more data */ + if (!pkt_len) { + *out_need_more = TRUE; + return TRUE; + } + + /* Unescape first; note that pkt_len */ + unesc_len = dm_unescape (inbuf, pkt_len, outbuf, outbuf_len, &escaping); + if (!unesc_len) { + /* Tell the caller to advance the buffer past the control char */ + *out_used = pkt_len + 1; + return FALSE; + } + + if (escaping) { + *out_need_more = TRUE; + return TRUE; + } + + /* Check the CRC of the packet's data */ + crc = crc16 (outbuf, unesc_len - 2); + pkt_crc = *((guint16 *) &outbuf[pkt_len - 2]); + if (crc != GUINT_FROM_LE (pkt_crc)) { + *out_used = pkt_len + 1; /* packet + CRC + 0x7E */ + return FALSE; + } + + *out_used = pkt_len + 1; /* packet + CRC + 0x7E */ + *out_decap_len = unesc_len - 2; /* decap_len should not include the CRC */ + return TRUE; +} + diff --git a/libqcdm/src/utils.h b/libqcdm/src/utils.h new file mode 100644 index 00000000..5fccf7f9 --- /dev/null +++ b/libqcdm/src/utils.h @@ -0,0 +1,54 @@ +/* -*- 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/>. + */ + +#ifndef UTILS_H +#define UTILS_H + +#include <glib.h> + +#define DIAG_CONTROL_CHAR 0x7E +#define DIAG_TRAILER_LEN 3 + +guint16 crc16 (const char *buffer, gsize len); + +gsize dm_escape (const char *inbuf, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len); + +gsize dm_unescape (const char *inbuf, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len, + gboolean *escaping); + +gsize dm_encapsulate_buffer (char *inbuf, + gsize cmd_len, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len); + +gboolean dm_decapsulate_buffer (const char *inbuf, + gsize inbuf_len, + char *outbuf, + gsize outbuf_len, + gsize *out_decap_len, + gsize *out_used, + gboolean *out_need_more); + +#endif /* UTILS_H */ + diff --git a/libqcdm/tests/Makefile.am b/libqcdm/tests/Makefile.am new file mode 100644 index 00000000..3d1b7ba5 --- /dev/null +++ b/libqcdm/tests/Makefile.am @@ -0,0 +1,30 @@ +INCLUDES = \ + -I$(top_srcdir)/libqcdm/src + +noinst_PROGRAMS = test-qcdm + +test_qcdm_SOURCES = \ + test-qcdm-crc.c \ + test-qcdm-crc.h \ + test-qcdm-escaping.c \ + test-qcdm-escaping.h \ + test-qcdm-com.c \ + test-qcdm-com.h \ + test-qcdm-result.c \ + test-qcdm-result.h \ + test-qcdm.c + +test_qcdm_CPPFLAGS = \ + $(MM_CFLAGS) + +test_qcdm_LDADD = \ + $(top_builddir)/libqcdm/src/libqcdm.la \ + $(MM_LIBS) + +if WITH_TESTS + +check-local: test-qcdm + $(abs_builddir)/test-qcdm + +endif + diff --git a/libqcdm/tests/test-qcdm-com.c b/libqcdm/tests/test-qcdm-com.c new file mode 100644 index 00000000..aeec6377 --- /dev/null +++ b/libqcdm/tests/test-qcdm-com.c @@ -0,0 +1,771 @@ +/* -*- 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 <glib.h> +#include <string.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <termios.h> +#include <unistd.h> +#include <stdlib.h> + +#include "test-qcdm-com.h" +#include "com.h" +#include "utils.h" +#include "result.h" +#include "commands.h" +#include "error.h" + +typedef struct { + char *port; + int fd; + struct termios old_t; + gboolean debug; +} TestComData; + +gpointer +test_com_setup (const char *port) +{ + TestComData *d; + int ret; + + d = g_malloc0 (sizeof (TestComData)); + g_assert (d); + + if (getenv ("SERIAL_DEBUG")) + d->debug = TRUE; + + errno = 0; + d->fd = open (port, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); + if (d->fd < 0) + g_warning ("%s: open failed: (%d) %s", port, errno, strerror (errno)); + g_assert (d->fd >= 0); + + ret = ioctl (d->fd, TIOCEXCL); + if (ret) { + g_warning ("%s: lock failed: (%d) %s", port, errno, strerror (errno)); + close (d->fd); + d->fd = -1; + } + g_assert (ret == 0); + + ret = ioctl (d->fd, TCGETA, &d->old_t); + if (ret) { + g_warning ("%s: old termios failed: (%d) %s", port, errno, strerror (errno)); + close (d->fd); + d->fd = -1; + } + g_assert (ret == 0); + + d->port = g_strdup (port); + return d; +} + +void +test_com_teardown (gpointer user_data) +{ + TestComData *d = user_data; + + g_assert (d); + + g_free (d->port); + close (d->fd); + g_free (d); +} + +static void +print_buf (const char *detail, const char *buf, gsize len) +{ + int i = 0; + gboolean newline = FALSE; + + g_print ("%s (%zu) ", detail, len); + for (i = 0; i < len; i++) { + g_print ("0x%02x ", buf[i] & 0xFF); + if (((i + 1) % 12) == 0) { + g_print ("\n"); + newline = TRUE; + } else + newline = FALSE; + } + + if (!newline) + g_print ("\n"); +} + +static gboolean +send_command (TestComData *d, char *buf, gsize len) +{ + int status; + int eagain_count = 1000; + gsize i = 0; + + if (d->debug) + print_buf (">>>", buf, len); + + while (i < len) { + errno = 0; + status = write (d->fd, &buf[i], 1); + if (status < 0) { + if (errno == EAGAIN) { + eagain_count--; + if (eagain_count <= 0) + return FALSE; + } else + g_assert (errno == 0); + } else + i++; + + usleep (1000); + } + + return TRUE; +} + +static gsize +wait_reply (TestComData *d, char *buf, gsize len) +{ + fd_set in; + int result; + struct timeval timeout = { 1, 0 }; + char readbuf[1024]; + ssize_t bytes_read; + int total = 0, retries = 0; + gsize decap_len = 0; + + FD_ZERO (&in); + FD_SET (d->fd, &in); + result = select (d->fd + 1, &in, NULL, NULL, &timeout); + if (result != 1 || !FD_ISSET (d->fd, &in)) + return 0; + + do { + errno = 0; + bytes_read = read (d->fd, &readbuf[total], 1); + if ((bytes_read == 0) || (errno == EAGAIN)) { + /* Haven't gotten the async control char yet */ + if (retries > 20) + return 0; /* 2 seconds, give up */ + + /* Otherwise wait a bit and try again */ + usleep (100000); + retries++; + continue; + } else if (bytes_read == 1) { + gboolean more = FALSE, success; + gsize used = 0; + + total++; + decap_len = 0; + success = dm_decapsulate_buffer (readbuf, total, buf, len, &decap_len, &used, &more); + + /* Discard used data */ + if (used > 0) { + total -= used; + memmove (readbuf, &readbuf[used], total); + } + + if (success && !more) { + /* Success; we have a packet */ + break; + } + } else { + /* Some error occurred */ + return 0; + } + } while (total < sizeof (readbuf)); + + if (d->debug) { + print_buf ("<<<", readbuf, total); + print_buf ("D<<", buf, decap_len); + } + + return decap_len; +} + +void +test_com_port_init (void *f, void *data) +{ + TestComData *d = data; + GError *error = NULL; + gboolean success; + + success = qcdm_port_setup (d->fd, &error); + if (!success) { + g_warning ("%s: error setting up port: (%d) %s", + d->port, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } + g_assert (success); +} + +void +test_com_version_info (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[512]; + const char *str; + gint len; + QCDMResult *result; + gsize reply_len; + + len = qcdm_cmd_version_info_new (buf, sizeof (buf), NULL); + g_assert (len == 4); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_version_info_result (buf, reply_len, &error); + g_assert (result); + + g_print ("\n"); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_VERSION_INFO_ITEM_COMP_DATE, &str); + g_message ("%s: Compiled Date: %s", __func__, str); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_VERSION_INFO_ITEM_COMP_TIME, &str); + g_message ("%s: Compiled Time: %s", __func__, str); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_VERSION_INFO_ITEM_RELEASE_DATE, &str); + g_message ("%s: Release Date: %s", __func__, str); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_VERSION_INFO_ITEM_RELEASE_TIME, &str); + g_message ("%s: Release Time: %s", __func__, str); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_VERSION_INFO_ITEM_MODEL, &str); + g_message ("%s: Model: %s", __func__, str); + + qcdm_result_unref (result); +} + +void +test_com_esn (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[512]; + const char *str; + gint len; + QCDMResult *result; + gsize reply_len; + + len = qcdm_cmd_esn_new (buf, sizeof (buf), NULL); + g_assert (len == 4); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_esn_result (buf, reply_len, &error); + g_assert (result); + + g_print ("\n"); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_ESN_ITEM_ESN, &str); + g_message ("%s: ESN: %s", __func__, str); + + qcdm_result_unref (result); +} + +void +test_com_mdn (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[512]; + const char *str; + gint len; + QCDMResult *result; + gsize reply_len; + + len = qcdm_cmd_nv_get_mdn_new (buf, sizeof (buf), 0, NULL); + g_assert (len > 0); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_nv_get_mdn_result (buf, reply_len, &error); + g_assert (result); + + g_print ("\n"); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_NV_GET_MDN_ITEM_MDN, &str); + g_message ("%s: MDN: %s", __func__, str); + + qcdm_result_unref (result); +} + +void +test_com_status (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[100]; + const char *str; + gint len; + QCDMResult *result; + gsize reply_len; + guint32 n32; + guint8 n8; + + len = qcdm_cmd_cdma_status_new (buf, sizeof (buf), NULL); + g_assert (len == 4); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_cdma_status_result (buf, reply_len, &error); + g_assert (result); + + g_print ("\n"); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_CDMA_STATUS_ITEM_ESN, &str); + g_message ("%s: ESN: %s", __func__, str); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_RX_STATE, &n32); + g_message ("%s: CDMA RX State: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_ENTRY_REASON, &n32); + g_message ("%s: Entry Reason: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_CURRENT_CHANNEL, &n32); + g_message ("%s: Current Channel: %u", __func__, n32); + + n8 = 0; + qcdm_result_get_uint8 (result, QCDM_CMD_CDMA_STATUS_ITEM_CODE_CHANNEL, &n8); + g_message ("%s: Code Channel: %u", __func__, n8); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_PILOT_BASE, &n32); + g_message ("%s: Pilot Base: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_SID, &n32); + g_message ("%s: CDMA System ID: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CDMA_STATUS_ITEM_NID, &n32); + g_message ("%s: CDMA Network ID: %u", __func__, n32); + + qcdm_result_unref (result); +} + +void +test_com_sw_version (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[100]; + gint len; + QCDMResult *result; + gsize reply_len; + + len = qcdm_cmd_sw_version_new (buf, sizeof (buf), NULL); + g_assert (len == 4); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_sw_version_result (buf, reply_len, &error); + + /* Recent devices don't appear to implement this command */ + g_assert (result == NULL); + g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND); + +/* + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_SW_VERSION_ITEM_VERSION, &str); + g_message ("%s: SW Version: %s", __func__, str); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_SW_VERSION_ITEM_COMP_DATE, &str); + g_message ("%s: Compiled Date: %s", __func__, str); + + str = NULL; + qcdm_result_get_string (result, QCDM_CMD_SW_VERSION_ITEM_COMP_TIME, &str); + g_message ("%s: Compiled Time: %s", __func__, str); + + qcdm_result_unref (result); +*/ +} + +void +test_com_cm_subsys_state_info (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[100]; + gint len; + QCDMResult *result; + gsize reply_len; + guint32 n32; + const char *detail; + + len = qcdm_cmd_cm_subsys_state_info_new (buf, sizeof (buf), NULL); + g_assert (len == 7); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_cm_subsys_state_info_result (buf, reply_len, &error); + g_assert (result); + + g_print ("\n"); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_CALL_STATE, &n32); + g_message ("%s: Call State: %u", __func__, n32); + + n32 = 0; + detail = NULL; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_OPERATING_MODE, &n32); + switch (n32) { + case QCDM_CMD_CM_SUBSYS_STATE_INFO_OPERATING_MODE_ONLINE: + detail = "online"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Operating Mode: %u (%s)", __func__, n32, detail); + + n32 = 0; + detail = NULL; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SYSTEM_MODE, &n32); + switch (n32) { + case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_NO_SERVICE: + detail = "no service"; + break; + case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_AMPS: + detail = "AMPS"; + break; + case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_CDMA: + detail = "CDMA"; + break; + case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_HDR: + detail = "HDR/EVDO"; + break; + case QCDM_CMD_CM_SUBSYS_STATE_INFO_SYSTEM_MODE_WCDMA: + detail = "WCDMA"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: System Mode: %u (%s)", __func__, n32, detail); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_MODE_PREF, &n32); + g_message ("%s: Mode Preference: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_BAND_PREF, &n32); + g_message ("%s: Band Preference: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ROAM_PREF, &n32); + g_message ("%s: Roam Preference: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF, &n32); + g_message ("%s: Service Domain Preference: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF, &n32); + g_message ("%s: Acquisition Order Preference: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF, &n32); + g_message ("%s: Hybrid Preference: %u", __func__, n32); + + n32 = 0; + qcdm_result_get_uint32 (result, QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF, &n32); + g_message ("%s: Network Selection Preference: %u", __func__, n32); + + qcdm_result_unref (result); +} + +void +test_com_hdr_subsys_state_info (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + GError *error = NULL; + char buf[100]; + gint len; + QCDMResult *result; + gsize reply_len; + guint8 num; + const char *detail; + + len = qcdm_cmd_hdr_subsys_state_info_new (buf, sizeof (buf), NULL); + g_assert (len == 7); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + /* Parse the response into a result structure */ + result = qcdm_cmd_hdr_subsys_state_info_result (buf, reply_len, &error); + if (!result) { + /* 1x-only devices won't implement the HDR subsystem of course */ + g_assert_error (error, QCDM_COMMAND_ERROR, QCDM_COMMAND_BAD_COMMAND); + g_message ("%s: device does not implement the HDR subsystem", __func__); + return; + } + g_assert (result); + + g_print ("\n"); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_AT_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_ACQUISITION: + detail = "acquisition"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_SYNC: + detail = "sync"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_IDLE: + detail = "idle"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_ACCESS: + detail = "access"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_AT_STATE_CONNECTED: + detail = "connected"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: AT State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_SESSION_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSED: + detail = "closed"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_SETUP: + detail = "setup"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_AT_INIT: + detail = "AT init"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_AN_INIT: + detail = "AN init"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_OPEN: + detail = "open"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_SESSION_STATE_CLOSING: + detail = "closing"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Session State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ALMP_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_INIT: + detail = "init"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_IDLE: + detail = "idle"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ALMP_STATE_CONNECTED: + detail = "connected"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: ALMP State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_INIT_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_NET_DETERMINE: + detail = "searching"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_ACQUISITION: + detail = "acquisition"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_INIT_STATE_SYNC: + detail = "sync"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Init State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_IDLE_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_SLEEP: + detail = "sleep"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_MONITOR: + detail = "monitor"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_IDLE_STATE_SETUP: + detail = "setup"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Idle State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_CONNECTED_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_OPEN: + detail = "open"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_CONNECTED_STATE_CLOSING: + detail = "closing"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Connected State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_ROUTE_UPDATE_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_IDLE: + detail = "idle"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_ROUTE_UPDATE_STATE_CONNECTED: + detail = "connected"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Route Update State: %u (%s)", __func__, num, detail); + + num = 0; + detail = NULL; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_OVERHEAD_MSG_STATE, &num); + switch (num) { + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_INIT: + detail = "initial"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_INACTIVE: + detail = "inactive"; + break; + case QCDM_CMD_HDR_SUBSYS_STATE_INFO_OVERHEAD_MSG_STATE_ACTIVE: + detail = "active"; + break; + default: + detail = "unknown"; + break; + } + g_message ("%s: Overhead Msg State: %u (%s)", __func__, num, detail); + + num = 0; + qcdm_result_get_uint8 (result, QCDM_CMD_HDR_SUBSYS_STATE_INFO_ITEM_HDR_HYBRID_MODE, &num); + g_message ("%s: HDR Hybrid Mode: %u", __func__, num); + + qcdm_result_unref (result); +} + diff --git a/libqcdm/tests/test-qcdm-com.h b/libqcdm/tests/test-qcdm-com.h new file mode 100644 index 00000000..6c9b6e0a --- /dev/null +++ b/libqcdm/tests/test-qcdm-com.h @@ -0,0 +1,41 @@ +/* -*- 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/>. + */ + +#ifndef TEST_QCDM_COM_H +#define TEST_QCDM_COM_H + +gpointer test_com_setup (const char *port); +void test_com_teardown (gpointer d); + +void test_com_port_init (void *f, void *data); + +void test_com_version_info (void *f, void *data); + +void test_com_esn (void *f, void *data); + +void test_com_mdn (void *f, void *data); + +void test_com_status (void *f, void *data); + +void test_com_sw_version (void *f, void *data); + +void test_com_cm_subsys_state_info (void *f, void *data); + +void test_com_hdr_subsys_state_info (void *f, void *data); + +#endif /* TEST_QCDM_COM_H */ + diff --git a/libqcdm/tests/test-qcdm-crc.c b/libqcdm/tests/test-qcdm-crc.c new file mode 100644 index 00000000..0cb3e863 --- /dev/null +++ b/libqcdm/tests/test-qcdm-crc.c @@ -0,0 +1,65 @@ +/* -*- 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 <glib.h> +#include <string.h> + +#include "test-qcdm-crc.h" +#include "utils.h" + +void +test_crc16_2 (void *f, void *data) +{ + static const char buf[] = { + 0x26, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 + }; + guint16 crc; + guint16 expected = 0x6D69; + + /* CRC check */ + crc = crc16 (buf, sizeof (buf)); + g_assert (crc == expected); +} + +void +test_crc16_1 (void *f, void *data) +{ + static const char buf[] = { + 0x4b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x3f, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff + }; + guint16 crc; + guint16 expected = 0x097A; + + /* CRC check */ + crc = crc16 (buf, sizeof (buf)); + g_assert (crc == expected); +} + diff --git a/libqcdm/tests/test-qcdm-crc.h b/libqcdm/tests/test-qcdm-crc.h new file mode 100644 index 00000000..91b95a08 --- /dev/null +++ b/libqcdm/tests/test-qcdm-crc.h @@ -0,0 +1,25 @@ +/* -*- 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/>. + */ + +#ifndef TEST_QCDM_CRC_H +#define TEST_QCDM_CRC_H + +void test_crc16_2 (void *f, void *data); +void test_crc16_1 (void *f, void *data); + +#endif /* TEST_QCDM_CRC_H */ + diff --git a/libqcdm/tests/test-qcdm-escaping.c b/libqcdm/tests/test-qcdm-escaping.c new file mode 100644 index 00000000..fb5fb82a --- /dev/null +++ b/libqcdm/tests/test-qcdm-escaping.c @@ -0,0 +1,124 @@ +/* -*- 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 <glib.h> +#include <string.h> + +#include "test-qcdm-escaping.h" +#include "utils.h" + +static const char data1[] = { + 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, + 0x0a, 0x6e, 0x6f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x74, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0a, 0x70, 0x68, 0x6f, + 0x6e, 0x7e, 0x7e, 0x7e, 0x7d, 0x7d, 0x7e, 0x7d, 0x7e, 0x7d, 0x7e, 0x6e, + 0x6b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x0a, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x6e, 0x6f, 0x74, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x0a, 0x70, 0x68, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x70, 0x68, 0x66, + 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x0a, 0x70, 0x68, 0x66, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, + 0x6e, 0x6f, 0x74, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x0a, + 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 0x72, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x66, 0x61, 0x69, + 0x6c, 0x75, 0x72, 0x65, 0x0a, 0x73, 0x69, 0x6d, 0x62, 0x75, 0x73, 0x79, + 0x0a, 0x73, 0x69, 0x6d, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x0a, 0x69, 0x6e, + 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x32, 0x72, + 0x65, 0x71, 0x75, 0x69 +}; + +static const char expected1[] = { + 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, + 0x0a, 0x6e, 0x6f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x74, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0a, 0x70, 0x68, 0x6f, + 0x6e, 0x7d, 0x5e, 0x7d, 0x5e, 0x7d, 0x5e, 0x7d, 0x5d, 0x7d, 0x5d, 0x7d, + 0x5e, 0x7d, 0x5d, 0x7d, 0x5e, 0x7d, 0x5d, 0x7d, 0x5e, 0x6e, 0x6b, 0x72, + 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x0a, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x64, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x6e, 0x6f, 0x74, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x0a, 0x70, 0x68, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x70, 0x68, 0x66, 0x73, 0x69, + 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x0a, 0x70, 0x68, 0x66, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x6e, 0x6f, + 0x74, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x0a, 0x73, 0x69, + 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x66, 0x61, 0x69, 0x6c, 0x75, + 0x72, 0x65, 0x0a, 0x73, 0x69, 0x6d, 0x62, 0x75, 0x73, 0x79, 0x0a, 0x73, + 0x69, 0x6d, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x0a, 0x69, 0x6e, 0x63, 0x6f, + 0x72, 0x72, 0x65, 0x63, 0x74, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x32, 0x72, 0x65, 0x71, + 0x75, 0x69 +}; + +void +test_escape1 (void *f, void *data) +{ + char escaped[1024]; + gsize len; + + /* Ensure that escaping in general works */ + len = dm_escape (data1, sizeof (data1), escaped, sizeof (escaped)); + g_assert (len == 266); + g_assert (len == sizeof (expected1)); + g_assert (memcmp (escaped, expected1, len) == 0); +} + +static const char data2[] = { + 0x4b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x3f, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff +}; + +void +test_escape2 (void *f, void *data) +{ + char escaped[1024]; + gsize len; + + /* Ensure that escaping data that doesn't need escaping works */ + len = dm_escape (data2, sizeof (data2), escaped, sizeof (escaped)); + g_assert (len == sizeof (data2)); + g_assert (memcmp (escaped, data2, len) == 0); +} + +void +test_escape_unescape (void *f, void *data) +{ + char escaped[512]; + char unescaped[512]; + gsize len, unlen; + gboolean escaping = FALSE; + + /* Ensure that escaping data that needs escaping, and then unescaping it, + * produces the exact same data as was originally escaped. + */ + len = dm_escape (data1, sizeof (data1), escaped, sizeof (escaped)); + unlen = dm_unescape (escaped, len, unescaped, sizeof (unescaped), &escaping); + + g_assert (unlen == sizeof (data1)); + g_assert (memcmp (unescaped, data1, unlen) == 0); +} + diff --git a/libqcdm/tests/test-qcdm-escaping.h b/libqcdm/tests/test-qcdm-escaping.h new file mode 100644 index 00000000..91706ee2 --- /dev/null +++ b/libqcdm/tests/test-qcdm-escaping.h @@ -0,0 +1,26 @@ +/* -*- 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/>. + */ + +#ifndef TEST_QCDM_ESCAPING_H +#define TEST_QCDM_ESCAPING_H + +void test_escape1 (void *f, void *data); +void test_escape2 (void *f, void *data); +void test_escape_unescape (void *f, void *data); + +#endif /* TEST_QCDM_ESCAPING_H */ + diff --git a/libqcdm/tests/test-qcdm-result.c b/libqcdm/tests/test-qcdm-result.c new file mode 100644 index 00000000..87f264b0 --- /dev/null +++ b/libqcdm/tests/test-qcdm-result.c @@ -0,0 +1,71 @@ +/* -*- 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 <glib.h> +#include <string.h> + +#include "test-qcdm-result.h" +#include "result.h" +#include "result-private.h" + +#define TEST_TAG "test" + +void +test_result_string (void *f, void *data) +{ + const char *str = "foobarblahblahblah"; + const char *tmp = NULL; + QCDMResult *result; + + result = qcdm_result_new (); + qcdm_result_add_string (result, TEST_TAG, str); + + qcdm_result_get_string (result, TEST_TAG, &tmp); + g_assert (tmp); + g_assert (strcmp (tmp, str) == 0); + + qcdm_result_unref (result); +} + +void +test_result_uint32 (void *f, void *data) +{ + guint32 num = 0xDEADBEEF; + guint32 tmp = 0; + QCDMResult *result; + + result = qcdm_result_new (); + qcdm_result_add_uint32 (result, TEST_TAG, num); + + qcdm_result_get_uint32 (result, TEST_TAG, &tmp); + g_assert (tmp == num); +} + +void +test_result_uint8 (void *f, void *data) +{ + guint8 num = 0x1E; + guint8 tmp = 0; + QCDMResult *result; + + result = qcdm_result_new (); + qcdm_result_add_uint8 (result, TEST_TAG, num); + + qcdm_result_get_uint8 (result, TEST_TAG, &tmp); + g_assert (tmp == num); +} + diff --git a/libqcdm/tests/test-qcdm-result.h b/libqcdm/tests/test-qcdm-result.h new file mode 100644 index 00000000..20d6cec0 --- /dev/null +++ b/libqcdm/tests/test-qcdm-result.h @@ -0,0 +1,26 @@ +/* -*- 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/>. + */ + +#ifndef TEST_QCDM_RESULT_H +#define TEST_QCDM_RESULT_H + +void test_result_string (void *f, void *data); +void test_result_uint32 (void *f, void *data); +void test_result_uint8 (void *f, void *data); + +#endif /* TEST_QCDM_RESULT_H */ + diff --git a/libqcdm/tests/test-qcdm.c b/libqcdm/tests/test-qcdm.c new file mode 100644 index 00000000..e5e3b42a --- /dev/null +++ b/libqcdm/tests/test-qcdm.c @@ -0,0 +1,107 @@ +/* -*- 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 <glib.h> +#include <string.h> + +#include "test-qcdm-crc.h" +#include "test-qcdm-escaping.h" +#include "test-qcdm-com.h" +#include "test-qcdm-result.h" + +typedef struct { + gpointer com_data; +} TestData; + +typedef void (*TCFunc)(void); + +#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL) + +static TestData * +test_data_new (const char *port) +{ + TestData *d; + + d = g_malloc0 (sizeof (TestData)); + g_assert (d); + + if (port) + d->com_data = test_com_setup (port); + + return d; +} + +static void +test_data_free (TestData *d) +{ + if (d->com_data) + test_com_teardown (d->com_data); + + g_free (d); +} + +int main (int argc, char **argv) +{ + GTestSuite *suite; + TestData *data; + int i; + const char *port = NULL; + gint result; + + g_test_init (&argc, &argv, NULL); + + /* See if we got passed a serial port for live testing */ + for (i = 0; i < argc; i++) { + if (!strcmp (argv[i], "--port")) { + /* Make sure there's actually a port in the next arg */ + g_assert (argc > i + 1); + port = argv[++i]; + } + } + + data = test_data_new (port); + + suite = g_test_get_root (); + + g_test_suite_add (suite, TESTCASE (test_crc16_1, NULL)); + g_test_suite_add (suite, TESTCASE (test_crc16_2, NULL)); + g_test_suite_add (suite, TESTCASE (test_escape1, NULL)); + g_test_suite_add (suite, TESTCASE (test_escape2, NULL)); + g_test_suite_add (suite, TESTCASE (test_escape_unescape, NULL)); + g_test_suite_add (suite, TESTCASE (test_result_string, NULL)); + g_test_suite_add (suite, TESTCASE (test_result_uint32, NULL)); + g_test_suite_add (suite, TESTCASE (test_result_uint8, NULL)); + + /* Live tests */ + if (port) { + g_test_suite_add (suite, TESTCASE (test_com_port_init, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_version_info, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_esn, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_mdn, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_status, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_sw_version, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_cm_subsys_state_info, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_hdr_subsys_state_info, data->com_data)); + } + + result = g_test_run (); + + test_data_free (data); + + return result; +} + diff --git a/plugins/mm-modem-anydata-cdma.c b/plugins/mm-modem-anydata-cdma.c index f6528ec2..eb5495eb 100644 --- a/plugins/mm-modem-anydata-cdma.c +++ b/plugins/mm-modem-anydata-cdma.c @@ -112,7 +112,7 @@ int_from_match_item (GMatchInfo *match_info, guint32 num, gint *val) } static void -evdo_state_done (MMSerialPort *port, +evdo_state_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -191,7 +191,7 @@ evdo_state_done (MMSerialPort *port, } static void -state_done (MMSerialPort *port, +state_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -265,7 +265,7 @@ state_done (MMSerialPort *port, mm_generic_cdma_query_reg_state_set_callback_1x_state (info, reg_state); /* Try for EVDO state too */ - mm_serial_port_queue_command (port, "*HSTATE?", 3, evdo_state_done, info); + mm_at_serial_port_queue_command (port, "*HSTATE?", 3, evdo_state_done, info); } static void @@ -274,10 +274,10 @@ query_registration_state (MMGenericCdma *cdma, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary, *secondary, *port; + MMAtSerialPort *primary, *secondary, *port; - port = primary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_PRIMARY); - secondary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_SECONDARY); + port = primary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_PRIMARY); + secondary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_SECONDARY); info = mm_generic_cdma_query_reg_state_callback_info_new (cdma, callback, user_data); @@ -293,7 +293,7 @@ query_registration_state (MMGenericCdma *cdma, port = secondary; } - mm_serial_port_queue_command (port, "*STATE?", 3, state_done, info); + mm_at_serial_port_queue_command (port, "*STATE?", 3, state_done, info); } /*****************************************************************************/ @@ -310,22 +310,22 @@ grab_port (MMModem *modem, GRegex *regex; port = mm_generic_cdma_grab_port (MM_GENERIC_CDMA (modem), subsys, name, suggested_type, user_data, error); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { /* Data state notifications */ /* Data call has connected */ regex = g_regex_new ("\\r\\n\\*ACTIVE:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Data call disconnected */ regex = g_regex_new ("\\r\\n\\*INACTIVE:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Modem is now dormant */ regex = g_regex_new ("\\r\\n\\*DORMANT:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Abnomral state notifications @@ -336,17 +336,17 @@ grab_port (MMModem *modem, /* Network acquisition fail */ regex = g_regex_new ("\\r\\n\\*OFFLINE:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Registration fail */ regex = g_regex_new ("\\r\\n\\*REGREQ:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Authentication fail */ regex = g_regex_new ("\\r\\n\\*AUTHREQ:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); } diff --git a/plugins/mm-modem-gobi-gsm.c b/plugins/mm-modem-gobi-gsm.c index 7ea9f8f4..566d0c82 100644 --- a/plugins/mm-modem-gobi-gsm.c +++ b/plugins/mm-modem-gobi-gsm.c @@ -23,6 +23,7 @@ #include "mm-errors.h" #include "mm-callback-info.h" #include "mm-modem-gsm-card.h" +#include "mm-at-serial-port.h" static void modem_init (MMModem *modem_class); static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); @@ -51,7 +52,7 @@ mm_modem_gobi_gsm_new (const char *device, /*****************************************************************************/ static void -get_string_done (MMSerialPort *port, +get_string_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -75,13 +76,13 @@ get_imsi (MMModemGsmCard *modem, MMModemStringFn callback, gpointer user_data) { - MMSerialPort *primary; + MMAtSerialPort *primary; MMCallbackInfo *info; info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command_cached (primary, "+CIMI", 3, get_string_done, info); + mm_at_serial_port_queue_command_cached (primary, "+CIMI", 3, get_string_done, info); } static void diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c index e4d830ff..8a7ffdbb 100644 --- a/plugins/mm-modem-hso.c +++ b/plugins/mm-modem-hso.c @@ -105,7 +105,7 @@ hso_get_cid (MMModemHso *self) } static void -auth_done (MMSerialPort *port, +auth_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -133,11 +133,11 @@ static void _internal_hso_modem_authenticate (MMModemHso *self, MMCallbackInfo *info) { MMModemHsoPrivate *priv = MM_MODEM_HSO_GET_PRIVATE (self); - MMSerialPort *primary; + MMAtSerialPort *primary; gint cid; char *command; - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); g_assert (primary); cid = hso_get_cid (self); @@ -155,7 +155,7 @@ _internal_hso_modem_authenticate (MMModemHso *self, MMCallbackInfo *info) } - mm_serial_port_queue_command (primary, command, 3, auth_done, info); + mm_at_serial_port_queue_command (primary, command, 3, auth_done, info); g_free (command); } @@ -212,7 +212,7 @@ connect_pending_done (MMModemHso *self) } static void -connection_enabled (MMSerialPort *port, +connection_enabled (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -244,7 +244,7 @@ connection_enabled (MMSerialPort *port, #define IGNORE_ERRORS_TAG "ignore-errors" static void -hso_call_control_done (MMSerialPort *port, +hso_call_control_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -266,15 +266,15 @@ hso_call_control (MMModemHso *self, { MMCallbackInfo *info; char *command; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); mm_callback_info_set_data (info, IGNORE_ERRORS_TAG, GUINT_TO_POINTER (ignore_errors), NULL); command = g_strdup_printf ("AT_OWANCALL=%d,%d,1", hso_get_cid (self), activate ? 1 : 0); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, command, 3, hso_call_control_done, info); + mm_at_serial_port_queue_command (primary, command, 3, hso_call_control_done, info); g_free (command); } @@ -445,7 +445,7 @@ ip4_config_invoke (MMCallbackInfo *info) } static void -get_ip4_config_done (MMSerialPort *port, +get_ip4_config_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -508,20 +508,20 @@ get_ip4_config (MMModem *modem, { MMCallbackInfo *info; char *command; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new_full (modem, ip4_config_invoke, G_CALLBACK (callback), user_data); command = g_strdup_printf ("AT_OWANDATA=%d", hso_get_cid (MM_MODEM_HSO (modem))); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, command, 3, get_ip4_config_done, info); + mm_at_serial_port_queue_command (primary, command, 3, get_ip4_config_done, info); g_free (command); } /*****************************************************************************/ static void -disconnect_owancall_done (MMSerialPort *port, +disconnect_owancall_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -536,16 +536,16 @@ do_disconnect (MMGenericGsm *gsm, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; char *command; info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); command = g_strdup_printf ("AT_OWANCALL=%d,0,0", cid); - mm_serial_port_queue_command (primary, command, 3, disconnect_owancall_done, info); + mm_at_serial_port_queue_command (primary, command, 3, disconnect_owancall_done, info); g_free (command); } @@ -672,13 +672,13 @@ grab_port (MMModem *modem, if (!port) goto out; - if (MM_IS_SERIAL_PORT (port)) { + if (MM_IS_AT_SERIAL_PORT (port)) { g_object_set (G_OBJECT (port), MM_SERIAL_PORT_SEND_DELAY, (guint64) 10000, NULL); if (ptype == MM_PORT_TYPE_PRIMARY) { GRegex *regex; regex = g_regex_new ("_OWANCALL: (\\d),\\s*(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, connection_enabled, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, connection_enabled, modem, NULL); g_regex_unref (regex); } } diff --git a/plugins/mm-modem-huawei-cdma.c b/plugins/mm-modem-huawei-cdma.c index 19b731a8..b164e675 100644 --- a/plugins/mm-modem-huawei-cdma.c +++ b/plugins/mm-modem-huawei-cdma.c @@ -82,7 +82,7 @@ parse_quality (const char *str, const char *detail) } static void -handle_1x_quality_change (MMSerialPort *port, +handle_1x_quality_change (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -99,9 +99,9 @@ handle_1x_quality_change (MMSerialPort *port, } static void -handle_evdo_quality_change (MMSerialPort *port, - GMatchInfo *match_info, - gpointer user_data) +handle_evdo_quality_change (MMAtSerialPort *port, + GMatchInfo *match_info, + gpointer user_data) { MMModemHuaweiCdma *self = MM_MODEM_HUAWEI_CDMA (user_data); char *str; @@ -152,7 +152,7 @@ uint_from_match_item (GMatchInfo *match_info, guint32 num, guint32 *val) } static void -sysinfo_done (MMSerialPort *port, +sysinfo_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -239,10 +239,10 @@ query_registration_state (MMGenericCdma *cdma, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary, *secondary, *port; + MMAtSerialPort *primary, *secondary, *port; - port = primary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_PRIMARY); - secondary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_SECONDARY); + port = primary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_PRIMARY); + secondary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_SECONDARY); info = mm_generic_cdma_query_reg_state_callback_info_new (cdma, callback, user_data); @@ -258,7 +258,7 @@ query_registration_state (MMGenericCdma *cdma, port = secondary; } - mm_serial_port_queue_command (port, "^SYSINFO", 3, sysinfo_done, info); + mm_at_serial_port_queue_command (port, "^SYSINFO", 3, sysinfo_done, info); } /*****************************************************************************/ @@ -275,14 +275,14 @@ grab_port (MMModem *modem, GRegex *regex; port = mm_generic_cdma_grab_port (MM_GENERIC_CDMA (modem), subsys, name, suggested_type, user_data, error); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { gboolean evdo0 = FALSE, evdoA = FALSE; g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); /* 1x signal level */ regex = g_regex_new ("\\r\\n\\^RSSILVL:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_1x_quality_change, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_1x_quality_change, modem, NULL); g_regex_unref (regex); g_object_get (G_OBJECT (modem), @@ -293,7 +293,7 @@ grab_port (MMModem *modem, if (evdo0 || evdoA) { /* EVDO signal level */ regex = g_regex_new ("\\r\\n\\^HRSSILVL:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_evdo_quality_change, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_evdo_quality_change, modem, NULL); g_regex_unref (regex); } } diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index b0d6a16e..b2677414 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -25,7 +25,7 @@ #include "mm-modem-gsm-network.h" #include "mm-errors.h" #include "mm-callback-info.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" #include "mm-serial-parsers.h" static void modem_init (MMModem *modem_class); @@ -104,7 +104,7 @@ parse_syscfg (MMModemHuaweiGsm *self, } static void -set_allowed_mode_done (MMSerialPort *port, +set_allowed_mode_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -118,7 +118,7 @@ set_allowed_mode_done (MMSerialPort *port, } static void -set_allowed_mode_get_done (MMSerialPort *port, +set_allowed_mode_get_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -163,7 +163,7 @@ set_allowed_mode_get_done (MMSerialPort *port, } command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2); - mm_serial_port_queue_command (port, command, 3, set_allowed_mode_done, info); + mm_at_serial_port_queue_command (port, command, 3, set_allowed_mode_done, info); g_free (command); } } @@ -176,22 +176,22 @@ set_allowed_mode (MMGenericGsm *gsm, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (gsm), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (gsm), MM_PORT_TYPE_PRIMARY); g_assert (primary); /* Get current configuration first so we don't change band and other * stuff when updating the mode. */ - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_allowed_mode_get_done, info); + mm_at_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_allowed_mode_get_done, info); } static void -get_allowed_mode_done (MMSerialPort *port, +get_allowed_mode_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -216,16 +216,16 @@ get_allowed_mode (MMGenericGsm *gsm, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_allowed_mode_done, info); + mm_at_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_allowed_mode_done, info); } static void -set_band_done (MMSerialPort *port, +set_band_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -244,7 +244,7 @@ set_band_done (MMSerialPort *port, } static void -set_band_get_done (MMSerialPort *port, +set_band_get_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -286,7 +286,7 @@ set_band_get_done (MMSerialPort *port, } command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2); - mm_serial_port_queue_command (port, command, 3, set_band_done, info); + mm_at_serial_port_queue_command (port, command, 3, set_band_done, info); g_free (command); } } @@ -299,7 +299,7 @@ set_band (MMModemGsmNetwork *modem, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); @@ -310,9 +310,9 @@ set_band (MMModemGsmNetwork *modem, case MM_MODEM_GSM_BAND_U2100: case MM_MODEM_GSM_BAND_PCS: mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (band), NULL); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_band_get_done, info); + mm_at_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_band_get_done, info); return; default: info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band."); @@ -323,7 +323,7 @@ set_band (MMModemGsmNetwork *modem, } static void -get_band_done (MMSerialPort *port, +get_band_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -348,7 +348,7 @@ get_band (MMModemGsmNetwork *modem, gpointer user_data) { MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (modem); - MMSerialPort *primary; + MMAtSerialPort *primary; if (priv->band != MM_MODEM_GSM_BAND_ANY) { /* have cached mode (from an unsolicited message). Use that */ @@ -362,16 +362,16 @@ get_band (MMModemGsmNetwork *modem, MMCallbackInfo *info; info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_band_done, info); + mm_at_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_band_done, info); } } /* Unsolicited message handlers */ static void -handle_signal_quality_change (MMSerialPort *port, +handle_signal_quality_change (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -395,7 +395,7 @@ handle_signal_quality_change (MMSerialPort *port, } static void -handle_mode_change (MMSerialPort *port, +handle_mode_change (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -439,7 +439,7 @@ handle_mode_change (MMSerialPort *port, } static void -handle_status_change (MMSerialPort *port, +handle_status_change (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -491,34 +491,34 @@ grab_port (MMModem *modem, } if (usbif == 0) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; } else if (suggested_type == MM_PORT_TYPE_SECONDARY) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { GRegex *regex; g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); regex = g_regex_new ("\\r\\n\\^RSSI:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_signal_quality_change, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_signal_quality_change, modem, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_mode_change, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_mode_change, modem, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_status_change, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, handle_status_change, modem, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, modem, NULL); g_regex_unref (regex); } diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index 7070f728..aa648cb6 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -117,11 +117,11 @@ register_done (gpointer user_data) MMModemMbm *self = MM_MODEM_MBM (reg_data->modem); MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self); MMModemGsmNetwork *parent_modem_iface; - MMSerialPort *primary; + MMAtSerialPort *primary; priv->reg_id = 0; - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); g_assert (primary); parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)); @@ -174,7 +174,7 @@ mbm_parse_allowed_mode (MMModemGsmAllowedMode network_mode) } static void -mbm_set_allowed_mode_done (MMSerialPort *port, +mbm_set_allowed_mode_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -195,19 +195,19 @@ set_allowed_mode (MMGenericGsm *gsm, { MMCallbackInfo *info; char *command; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); command = g_strdup_printf ("+CFUN=%d", mbm_parse_allowed_mode (mode)); - mm_serial_port_queue_command (primary, command, 3, mbm_set_allowed_mode_done, info); + mm_at_serial_port_queue_command (primary, command, 3, mbm_set_allowed_mode_done, info); g_free (command); } static void -mbm_erinfo_received (MMSerialPort *port, +mbm_erinfo_received (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { @@ -249,7 +249,7 @@ mbm_erinfo_received (MMSerialPort *port, } static void -get_allowed_mode_done (MMSerialPort *port, +get_allowed_mode_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -286,12 +286,12 @@ get_allowed_mode (MMGenericGsm *gsm, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "CFUN?", 3, get_allowed_mode_done, info); + mm_at_serial_port_queue_command (primary, "CFUN?", 3, get_allowed_mode_done, info); } /*****************************************************************************/ @@ -339,7 +339,7 @@ simple_connect (MMModemSimple *simple, /*****************************************************************************/ static void -mbm_enable_done (MMSerialPort *port, +mbm_enable_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -347,14 +347,14 @@ mbm_enable_done (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; /* Start unsolicited signal strength and access technology responses */ - mm_serial_port_queue_command (port, "+CMER=3,0,0,1", 3, NULL, NULL); - mm_serial_port_queue_command (port, "*ERINFO=1", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CMER=3,0,0,1", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "*ERINFO=1", 3, NULL, NULL); mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); } static void -mbm_enap0_done (MMSerialPort *port, +mbm_enap0_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -367,12 +367,12 @@ mbm_enap0_done (MMSerialPort *port, priv->network_mode = MBM_NETWORK_MODE_ANY; command = g_strdup_printf ("+CFUN=%d", priv->network_mode); - mm_serial_port_queue_command (port, command, 3, mbm_enable_done, info); + mm_at_serial_port_queue_command (port, command, 3, mbm_enable_done, info); g_free (command); } static void -mbm_init_done (MMSerialPort *port, +mbm_init_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -388,17 +388,17 @@ mbm_init_done (MMSerialPort *port, if (!priv->network_mode) priv->network_mode = MBM_NETWORK_MODE_ANY; - mm_serial_port_queue_command (port, "*ENAP=0", 3, mbm_enap0_done, info); + mm_at_serial_port_queue_command (port, "*ENAP=0", 3, mbm_enap0_done, info); } static void -do_init (MMSerialPort *port, MMCallbackInfo *info) +do_init (MMAtSerialPort *port, MMCallbackInfo *info) { - mm_serial_port_queue_command (port, "&F E0 V1 X4 &C1 +CMEE=1", 3, mbm_init_done, info); + mm_at_serial_port_queue_command (port, "&F E0 V1 X4 &C1 +CMEE=1", 3, mbm_init_done, info); } static void -mbm_emrdy_done (MMSerialPort *port, +mbm_emrdy_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -421,18 +421,18 @@ do_enable (MMGenericGsm *self, MMModemFn callback, gpointer user_data) { MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self); MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); - primary = mm_generic_gsm_get_port (self, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (self, MM_PORT_TYPE_PRIMARY); g_assert (primary); if (priv->have_emrdy) { /* Modem is ready, no need to check EMRDY */ do_init (primary, info); } else - mm_serial_port_queue_command (primary, "*EMRDY?", 5, mbm_emrdy_done, info); + mm_at_serial_port_queue_command (primary, "*EMRDY?", 5, mbm_emrdy_done, info); } typedef struct { @@ -442,7 +442,7 @@ typedef struct { } DisableInfo; static void -disable_unsolicited_done (MMSerialPort *port, +disable_unsolicited_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -461,7 +461,7 @@ disable (MMModem *modem, MMModemFn callback, gpointer user_data) { - MMSerialPort *primary; + MMAtSerialPort *primary; DisableInfo *info; info = g_malloc0 (sizeof (DisableInfo)); @@ -469,11 +469,11 @@ disable (MMModem *modem, info->user_data = user_data; info->modem = modem; - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); g_assert (primary); /* Turn off unsolicited responses */ - mm_serial_port_queue_command (primary, "+CMER=0;*ERINFO=0", 5, disable_unsolicited_done, info); + mm_at_serial_port_queue_command (primary, "+CMER=0;*ERINFO=0", 5, disable_unsolicited_done, info); } static void @@ -499,11 +499,11 @@ do_disconnect (MMGenericGsm *gsm, MMModemFn callback, gpointer user_data) { - MMSerialPort *primary; + MMAtSerialPort *primary; - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "*ENAP=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (primary, "*ENAP=0", 3, NULL, NULL); MM_GENERIC_GSM_CLASS (mm_modem_mbm_parent_class)->do_disconnect (gsm, cid, callback, user_data); } @@ -511,7 +511,7 @@ do_disconnect (MMGenericGsm *gsm, /*****************************************************************************/ static void -mbm_emrdy_received (MMSerialPort *port, +mbm_emrdy_received (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { @@ -519,7 +519,7 @@ mbm_emrdy_received (MMSerialPort *port, } static void -mbm_pacsp_received (MMSerialPort *port, +mbm_pacsp_received (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { @@ -527,7 +527,7 @@ mbm_pacsp_received (MMSerialPort *port, } static void -mbm_ciev_received (MMSerialPort *port, +mbm_ciev_received (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { @@ -570,7 +570,7 @@ mbm_do_connect_done (MMModemMbm *self, gboolean success) } static void -mbm_e2nap_received (MMSerialPort *port, +mbm_e2nap_received (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { @@ -598,7 +598,7 @@ mbm_e2nap_received (MMSerialPort *port, } static void -enap_poll_response (MMSerialPort *port, +enap_poll_response (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -633,20 +633,21 @@ static gboolean enap_poll (gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMSerialPort *port = mm_generic_gsm_get_port (MM_GENERIC_GSM (info->modem), MM_PORT_TYPE_PRIMARY); + MMAtSerialPort *port; + port = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (info->modem), MM_PORT_TYPE_PRIMARY); g_assert (port); - mm_serial_port_queue_command (port, "AT*ENAP?", 3, enap_poll_response, user_data); + mm_at_serial_port_queue_command (port, "AT*ENAP?", 3, enap_poll_response, user_data); /* we cancel this in the _done function if all is fine */ return TRUE; } static void -enap_done (MMSerialPort *port, - GString *response, - GError *error, - gpointer user_data) +enap_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; guint tid; @@ -662,7 +663,7 @@ enap_done (MMSerialPort *port, } static void -mbm_auth_done (MMSerialPort *port, +mbm_auth_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -679,10 +680,10 @@ mbm_auth_done (MMSerialPort *port, cid = mm_generic_gsm_get_cid (modem); - mm_serial_port_queue_command (port, "AT*E2NAP=1", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "AT*E2NAP=1", 3, NULL, NULL); command = g_strdup_printf ("AT*ENAP=1,%d", cid); - mm_serial_port_queue_command (port, command, 3, enap_done, user_data); + mm_at_serial_port_queue_command (port, command, 3, enap_done, user_data); g_free (command); } @@ -692,9 +693,9 @@ mbm_modem_authenticate (MMModemMbm *self, const char *password, gpointer user_data) { - MMSerialPort *primary; + MMAtSerialPort *primary; - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PRIMARY); g_assert (primary); if (username || password) { @@ -705,7 +706,7 @@ mbm_modem_authenticate (MMModemMbm *self, username ? username : "", password ? password : ""); - mm_serial_port_queue_command (primary, command, 3, mbm_auth_done, user_data); + mm_at_serial_port_queue_command (primary, command, 3, mbm_auth_done, user_data); g_free (command); } else mbm_auth_done (primary, NULL, NULL, user_data); @@ -765,47 +766,47 @@ grab_port (MMModem *modem, if (!strcmp (subsys, "tty")) { if (suggested_type == MM_PORT_TYPE_UNKNOWN) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; - else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) + else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } else ptype = suggested_type; } port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { GRegex *regex; if (ptype == MM_PORT_TYPE_PRIMARY) { regex = g_regex_new ("\\r\\n\\*E2NAP: (\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_e2nap_received, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_e2nap_received, modem, NULL); g_regex_unref (regex); } regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_emrdy_received, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_emrdy_received, modem, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\+PACSP(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_pacsp_received, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_pacsp_received, modem, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\+CIEV: (\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_ciev_received, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_ciev_received, modem, NULL); g_regex_unref (regex); /* also consume unsolicited mbm messages we are not interested in them - see LP: #416418 */ regex = g_regex_new ("\\R\\*ESTKSMENU:.*\\R", G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_MULTILINE | G_REGEX_NEWLINE_CRLF, G_REGEX_MATCH_NEWLINE_CRLF, NULL);
- mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\*EMWI: (\\d),(\\d).*\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); regex = g_regex_new ("\\r\\n\\*ERINFO:\\s*(\\d),(\\d),(\\d).*\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_erinfo_received, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, mbm_erinfo_received, modem, NULL); g_regex_unref (regex); } diff --git a/plugins/mm-modem-nokia.c b/plugins/mm-modem-nokia.c index 677a089d..eb90287a 100644 --- a/plugins/mm-modem-nokia.c +++ b/plugins/mm-modem-nokia.c @@ -56,19 +56,19 @@ grab_port (MMModem *modem, MMPort *port = NULL; if (suggested_type == MM_PORT_TYPE_UNKNOWN) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; - else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) + else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } else ptype = suggested_type; port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); - if (port && MM_IS_SERIAL_PORT (port)) { - mm_serial_port_set_response_parser (MM_SERIAL_PORT (port), - mm_serial_parser_v1_e1_parse, - mm_serial_parser_v1_e1_new (), - mm_serial_parser_v1_e1_destroy); + if (port && MM_IS_AT_SERIAL_PORT (port)) { + mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), + mm_serial_parser_v1_e1_parse, + mm_serial_parser_v1_e1_new (), + mm_serial_parser_v1_e1_destroy); } return !!port; diff --git a/plugins/mm-modem-novatel-cdma.c b/plugins/mm-modem-novatel-cdma.c index 679b3b87..c578d18b 100644 --- a/plugins/mm-modem-novatel-cdma.c +++ b/plugins/mm-modem-novatel-cdma.c @@ -98,7 +98,7 @@ get_one_qual (const char *reply, const char *tag) } static void -get_rssi_done (MMSerialPort *port, +get_rssi_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -143,10 +143,10 @@ get_signal_quality (MMModemCdma *modem, { MMGenericCdma *cdma = MM_GENERIC_CDMA (modem); MMCallbackInfo *info; - MMSerialPort *primary, *secondary, *port; + MMAtSerialPort *primary, *secondary, *port; - port = primary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_PRIMARY); - secondary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_SECONDARY); + port = primary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_PRIMARY); + secondary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_SECONDARY); info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); @@ -166,7 +166,7 @@ get_signal_quality (MMModemCdma *modem, * reply doesn't appear to be in positive dBm either; instead try the custom * Novatel command for it. */ - mm_serial_port_queue_command (port, "$NWRSSI", 3, get_rssi_done, info); + mm_at_serial_port_queue_command (port, "$NWRSSI", 3, get_rssi_done, info); } /*****************************************************************************/ diff --git a/plugins/mm-modem-novatel-gsm.c b/plugins/mm-modem-novatel-gsm.c index c8c28d1f..72c929d3 100644 --- a/plugins/mm-modem-novatel-gsm.c +++ b/plugins/mm-modem-novatel-gsm.c @@ -49,26 +49,26 @@ mm_modem_novatel_gsm_new (const char *device, /*****************************************************************************/ static void -dmat_callback2 (MMSerialPort *port, +dmat_callback2 (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) { - mm_serial_port_close (port); + mm_serial_port_close (MM_SERIAL_PORT (port)); } static void -dmat_callback (MMSerialPort *port, +dmat_callback (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) { if (error) { /* Try it again */ - if (mm_serial_port_open (port, NULL)) - mm_serial_port_queue_command (port, "$NWDMAT=1", 2, dmat_callback2, NULL); + if (mm_serial_port_open (MM_SERIAL_PORT (port), NULL)) + mm_at_serial_port_queue_command (port, "$NWDMAT=1", 2, dmat_callback2, NULL); } else - mm_serial_port_close (port); + mm_serial_port_close (MM_SERIAL_PORT (port)); } static gboolean @@ -84,18 +84,18 @@ grab_port (MMModem *modem, MMPort *port = NULL; if (suggested_type == MM_PORT_TYPE_UNKNOWN) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; - else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) + else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } else ptype = suggested_type; port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); - if (port && MM_IS_SERIAL_PORT (port) && (ptype == MM_PORT_TYPE_PRIMARY)) { + if (port && MM_IS_AT_SERIAL_PORT (port) && (ptype == MM_PORT_TYPE_PRIMARY)) { /* Flip secondary ports to AT mode */ if (mm_serial_port_open (MM_SERIAL_PORT (port), NULL)) - mm_serial_port_queue_command (MM_SERIAL_PORT (port), "$NWDMAT=1", 2, dmat_callback, NULL); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "$NWDMAT=1", 2, dmat_callback, NULL); } return !!port; diff --git a/plugins/mm-modem-option.c b/plugins/mm-modem-option.c index a7faf4d3..42cd927c 100644 --- a/plugins/mm-modem-option.c +++ b/plugins/mm-modem-option.c @@ -87,7 +87,7 @@ real_do_enable_power_up_done (MMGenericGsm *gsm, } static void -get_allowed_mode_done (MMSerialPort *port, +get_allowed_mode_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -138,16 +138,16 @@ get_allowed_mode (MMGenericGsm *gsm, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "AT_OPSYS?", 3, get_allowed_mode_done, info); + mm_at_serial_port_queue_command (primary, "AT_OPSYS?", 3, get_allowed_mode_done, info); } static void -set_allowed_mode_done (MMSerialPort *port, +set_allowed_mode_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -167,7 +167,7 @@ set_allowed_mode (MMGenericGsm *gsm, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; char *command; int i; @@ -193,9 +193,9 @@ set_allowed_mode (MMGenericGsm *gsm, } command = g_strdup_printf ("AT_OPSYS=%d,2", i); - primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, command, 3, set_allowed_mode_done, info); + mm_at_serial_port_queue_command (primary, command, 3, set_allowed_mode_done, info); g_free (command); } diff --git a/plugins/mm-modem-sierra-cdma.c b/plugins/mm-modem-sierra-cdma.c index 4f3140b7..f2fb4e09 100644 --- a/plugins/mm-modem-sierra-cdma.c +++ b/plugins/mm-modem-sierra-cdma.c @@ -110,7 +110,7 @@ sys_mode_has_service (SysMode mode) } static void -status_done (MMSerialPort *port, +status_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -293,11 +293,11 @@ query_registration_state (MMGenericCdma *cdma, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary, *secondary; - MMSerialPort *port; + MMAtSerialPort *primary, *secondary; + MMAtSerialPort *port; - port = primary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_PRIMARY); - secondary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_SECONDARY); + port = primary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_PRIMARY); + secondary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_SECONDARY); info = mm_generic_cdma_query_reg_state_callback_info_new (cdma, callback, user_data); @@ -313,11 +313,11 @@ query_registration_state (MMGenericCdma *cdma, port = secondary; } - mm_serial_port_queue_command (port, "!STATUS", 3, status_done, info); + mm_at_serial_port_queue_command (port, "!STATUS", 3, status_done, info); } static void -pcstate_done (MMSerialPort *port, +pcstate_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -334,14 +334,14 @@ post_enable (MMGenericCdma *cdma, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (cdma), callback, user_data); - primary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "!pcstate=1", 5, pcstate_done, info); + mm_at_serial_port_queue_command (primary, "!pcstate=1", 5, pcstate_done, info); } static void @@ -350,14 +350,14 @@ post_disable (MMGenericCdma *cdma, gpointer user_data) { MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; info = mm_callback_info_new (MM_MODEM (cdma), callback, user_data); - primary = mm_generic_cdma_get_port (cdma, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_cdma_get_at_port (cdma, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "!pcstate=0", 5, pcstate_done, info); + mm_at_serial_port_queue_command (primary, "!pcstate=0", 5, pcstate_done, info); } /*****************************************************************************/ diff --git a/plugins/mm-modem-sierra-gsm.c b/plugins/mm-modem-sierra-gsm.c index ce4bca6d..02be144f 100644 --- a/plugins/mm-modem-sierra-gsm.c +++ b/plugins/mm-modem-sierra-gsm.c @@ -104,22 +104,22 @@ grab_port (MMModem *modem, MMPort *port; if (suggested_type == MM_PORT_TYPE_UNKNOWN) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; - else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) + else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } else ptype = suggested_type; port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { GRegex *regex; g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); regex = g_regex_new ("\\r\\n\\+PACSP0\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); } diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c index cb5f8054..a4abe47b 100644 --- a/plugins/mm-modem-zte.c +++ b/plugins/mm-modem-zte.c @@ -53,7 +53,7 @@ mm_modem_zte_new (const char *device, } static void -zte_access_tech_changed (MMSerialPort *port, +zte_access_tech_changed (MMAtSerialPort *port, GMatchInfo *info, gpointer user_data) { @@ -89,7 +89,7 @@ zte_access_tech_changed (MMSerialPort *port, /* Modem class override functions */ /*****************************************************************************/ -static void cpms_try_done (MMSerialPort *port, +static void cpms_try_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data); @@ -100,17 +100,17 @@ cpms_timeout_cb (gpointer user_data) MMCallbackInfo *info = user_data; MMModem *modem = info->modem; MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (modem); - MMSerialPort *primary; + MMAtSerialPort *primary; priv->cpms_timeout = 0; - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); - mm_serial_port_queue_command (primary, "+CPMS?", 10, cpms_try_done, info); + primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + mm_at_serial_port_queue_command (primary, "+CPMS?", 10, cpms_try_done, info); return FALSE; } static void -cpms_try_done (MMSerialPort *port, +cpms_try_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -136,7 +136,7 @@ cpms_try_done (MMSerialPort *port, } static void -init_modem_done (MMSerialPort *port, +init_modem_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -148,7 +148,7 @@ init_modem_done (MMSerialPort *port, * done during probing, but if the device has a PIN enabled it won't * accept the +CPMS? during the probe and we have to do it here. */ - mm_serial_port_queue_command (port, "+CPMS?", 10, cpms_try_done, info); + mm_at_serial_port_queue_command (port, "+CPMS?", 10, cpms_try_done, info); } static void enable_flash_done (MMSerialPort *port, @@ -156,7 +156,7 @@ static void enable_flash_done (MMSerialPort *port, gpointer user_data); static void -pre_init_done (MMSerialPort *port, +pre_init_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -169,12 +169,12 @@ pre_init_done (MMSerialPort *port, if ( !priv->init_retried && g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_RESPONSE_TIMEOUT)) { priv->init_retried = TRUE; - enable_flash_done (port, NULL, user_data); + enable_flash_done (MM_SERIAL_PORT (port), NULL, user_data); } else mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); } else { /* Finish the initialization */ - mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info); + mm_at_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info); } } @@ -186,7 +186,7 @@ enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data) if (error) mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); else - mm_serial_port_queue_command (port, "E0 V1", 3, pre_init_done, user_data); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "E0 V1", 3, pre_init_done, user_data); } static void @@ -194,15 +194,15 @@ do_enable (MMGenericGsm *modem, MMModemFn callback, gpointer user_data) { MMModemZtePrivate *priv = MM_MODEM_ZTE_GET_PRIVATE (modem); MMCallbackInfo *info; - MMSerialPort *primary; + MMAtSerialPort *primary; priv->init_retried = FALSE; - primary = mm_generic_gsm_get_port (modem, MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_at_port (modem, MM_PORT_TYPE_PRIMARY); g_assert (primary); info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_flash (primary, 100, enable_flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (primary), 100, enable_flash_done, info); } static void @@ -233,41 +233,41 @@ grab_port (MMModem *modem, MMPort *port = NULL; if (suggested_type == MM_PORT_TYPE_UNKNOWN) { - if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY)) + if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) ptype = MM_PORT_TYPE_PRIMARY; - else if (!mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_SECONDARY)) + else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) ptype = MM_PORT_TYPE_SECONDARY; } else ptype = suggested_type; port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { GRegex *regex; g_object_set (port, MM_PORT_CARRIER_DETECT, FALSE, NULL); regex = g_regex_new ("\\r\\n\\+ZUSIMR:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Unsolicted operator display */ regex = g_regex_new ("\\r\\n\\+ZDONR: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* Current network and service domain */ regex = g_regex_new ("\\r\\n\\+ZPASR:\\s*(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, zte_access_tech_changed, modem, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, zte_access_tech_changed, modem, NULL); g_regex_unref (regex); /* SIM request to Build Main Menu */ regex = g_regex_new ("\\r\\n\\+ZPSTM: (.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); /* SIM request to Rebuild Main Menu */ regex = g_regex_new ("\\r\\n\\+ZEND\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, NULL, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, NULL, NULL, NULL); g_regex_unref (regex); } diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c index 96edc086..bee7d40f 100644 --- a/plugins/mm-plugin-huawei.c +++ b/plugins/mm-plugin-huawei.c @@ -26,6 +26,7 @@ #include "mm-modem-huawei-gsm.h" #include "mm-modem-huawei-cdma.h" #include "mm-serial-parsers.h" +#include "mm-at-serial-port.h" G_DEFINE_TYPE (MMPluginHuawei, mm_plugin_huawei, MM_TYPE_PLUGIN_BASE) @@ -69,7 +70,7 @@ probe_result (MMPluginBase *base, #define TAG_SUPPORTS_INFO "huawei-supports-info" typedef struct { - MMSerialPort *serial; + MMAtSerialPort *serial; guint id; gboolean secondary; } HuaweiSupportsInfo; @@ -106,7 +107,7 @@ probe_secondary_supported (gpointer user_data) } static void -probe_secondary_handle_msg (MMSerialPort *port, +probe_secondary_handle_msg (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -135,12 +136,12 @@ probe_secondary_timeout (gpointer user_data) } static void -add_regex (MMSerialPort *port, const char *match, gpointer user_data) +add_regex (MMAtSerialPort *port, const char *match, gpointer user_data) { GRegex *regex; regex = g_regex_new (match, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (port, regex, probe_secondary_handle_msg, user_data, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (port, regex, probe_secondary_handle_msg, user_data, NULL); g_regex_unref (regex); } @@ -208,13 +209,13 @@ supports_port (MMPluginBase *base, /* Listen for Huawei-specific unsolicited messages */ info = g_malloc0 (sizeof (HuaweiSupportsInfo)); - info->serial = mm_serial_port_new (name, MM_PORT_TYPE_PRIMARY); + info->serial = mm_at_serial_port_new (name, MM_PORT_TYPE_PRIMARY); g_object_set (G_OBJECT (info->serial), MM_PORT_CARRIER_DETECT, FALSE, NULL); - mm_serial_port_set_response_parser (info->serial, - mm_serial_parser_v1_parse, - mm_serial_parser_v1_new (), - mm_serial_parser_v1_destroy); + mm_at_serial_port_set_response_parser (info->serial, + mm_serial_parser_v1_parse, + mm_serial_parser_v1_new (), + mm_serial_parser_v1_destroy); add_regex (info->serial, "\\r\\n\\^RSSI:(\\d+)\\r\\n", task); add_regex (info->serial, "\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", task); @@ -227,7 +228,7 @@ supports_port (MMPluginBase *base, g_object_set_data_full (G_OBJECT (task), TAG_SUPPORTS_INFO, info, huawei_supports_info_destroy); - if (!mm_serial_port_open (info->serial, &error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (info->serial), &error)) { g_warning ("%s: (Huawei) %s: couldn't open serial port: (%d) %s", __func__, name, error ? error->code : -1, diff --git a/src/Makefile.am b/src/Makefile.am index a695f374..3d938063 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,6 +16,7 @@ sbin_PROGRAMS = modem-manager modem_manager_CPPFLAGS = \ $(MM_CFLAGS) \ $(GUDEV_CFLAGS) \ + $(top_srcdir) \ -I${top_builddir}/marshallers \ -DPLUGINDIR=\"$(pkglibdir)\" @@ -27,6 +28,7 @@ modem_manager_LDADD = \ $(MM_LIBS) \ $(GUDEV_LIBS) \ $(top_builddir)/marshallers/libmarshallers.la \ + $(top_builddir)/libqcdm/src/libqcdm.la \ $(builddir)/libmodem-helpers.la if WITH_POLKIT @@ -59,12 +61,16 @@ modem_manager_SOURCES = \ mm-modem.h \ mm-port.c \ mm-port.h \ - mm-modem-base.c \ - mm-modem-base.h \ mm-serial-port.c \ mm-serial-port.h \ + mm-at-serial-port.c \ + mm-at-serial-port.h \ + mm-qcdm-serial-port.c \ + mm-qcdm-serial-port.h \ mm-serial-parsers.c \ mm-serial-parsers.h \ + mm-modem-base.c \ + mm-modem-base.h \ mm-generic-cdma.c \ mm-generic-cdma.h \ mm-generic-gsm.c \ diff --git a/src/mm-at-serial-port.c b/src/mm-at-serial-port.c new file mode 100644 index 00000000..40fbd448 --- /dev/null +++ b/src/mm-at-serial-port.c @@ -0,0 +1,324 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 Red Hat, Inc. + */ + +#define _GNU_SOURCE /* for strcasestr() */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "mm-at-serial-port.h" +#include "mm-errors.h" +#include "mm-options.h" + +G_DEFINE_TYPE (MMAtSerialPort, mm_at_serial_port, MM_TYPE_SERIAL_PORT) + +#define MM_AT_SERIAL_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortPrivate)) + +typedef struct { + /* Response parser data */ + MMAtSerialResponseParserFn response_parser_fn; + gpointer response_parser_user_data; + GDestroyNotify response_parser_notify; + GSList *unsolicited_msg_handlers; +} MMAtSerialPortPrivate; + + +/*****************************************************************************/ + +void +mm_at_serial_port_set_response_parser (MMAtSerialPort *self, + MMAtSerialResponseParserFn fn, + gpointer user_data, + GDestroyNotify notify) +{ + MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); + + g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); + + if (priv->response_parser_notify) + priv->response_parser_notify (priv->response_parser_user_data); + + priv->response_parser_fn = fn; + priv->response_parser_user_data = user_data; + priv->response_parser_notify = notify; +} + +static gboolean +parse_response (MMSerialPort *port, GByteArray *response, GError **error) +{ + MMAtSerialPort *self = MM_AT_SERIAL_PORT (port); + MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); + gboolean found; + GString *string; + + g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE); + + /* Construct the string that AT-parsing functions expect */ + string = g_string_sized_new (response->len + 1); + g_string_append_len (string, (const char *) response->data, response->len); + + /* Parse it */ + found = priv->response_parser_fn (priv->response_parser_user_data, string, error); + + /* And copy it back into the response array after the parser has removed + * matches and cleaned it up. + */ + if (response->len) + g_byte_array_remove_range (response, 0, response->len); + g_byte_array_append (response, (const guint8 *) string->str, string->len); + g_string_free (string, TRUE); + return found; +} + +static void +handle_response (MMSerialPort *port, + GByteArray *response, + GError *error, + GCallback callback, + gpointer callback_data) +{ + MMAtSerialPort *self = MM_AT_SERIAL_PORT (port); + MMAtSerialResponseFn response_callback = (MMAtSerialResponseFn) callback; + GString *string; + + /* Convert to a string and call the callback */ + string = g_string_sized_new (response->len + 1); + g_string_append_len (string, (const char *) response->data, response->len); + response_callback (self, string, error, callback_data); + g_string_free (string, TRUE); +} + +/*****************************************************************************/ + +typedef struct { + GRegex *regex; + MMAtSerialUnsolicitedMsgFn callback; + gpointer user_data; + GDestroyNotify notify; +} MMAtUnsolicitedMsgHandler; + +void +mm_at_serial_port_add_unsolicited_msg_handler (MMAtSerialPort *self, + GRegex *regex, + MMAtSerialUnsolicitedMsgFn callback, + gpointer user_data, + GDestroyNotify notify) +{ + MMAtUnsolicitedMsgHandler *handler; + MMAtSerialPortPrivate *priv; + + g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); + g_return_if_fail (regex != NULL); + + handler = g_slice_new (MMAtUnsolicitedMsgHandler); + handler->regex = g_regex_ref (regex); + handler->callback = callback; + handler->user_data = user_data; + handler->notify = notify; + + priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); + priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler); +} + +static gboolean +remove_eval_cb (const GMatchInfo *match_info, + GString *result, + gpointer user_data) +{ + int *result_len = (int *) user_data; + int start; + int end; + + if (g_match_info_fetch_pos (match_info, 0, &start, &end)) + *result_len -= (end - start); + + return FALSE; +} + +static void +parse_unsolicited (MMSerialPort *port, GByteArray *response) +{ + MMAtSerialPort *self = MM_AT_SERIAL_PORT (port); + MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); + GSList *iter; + + for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) { + MMAtUnsolicitedMsgHandler *handler = (MMAtUnsolicitedMsgHandler *) iter->data; + GMatchInfo *match_info; + gboolean matches; + + matches = g_regex_match_full (handler->regex, + (const char *) response->data, + response->len, + 0, 0, &match_info, NULL); + if (handler->callback) { + while (g_match_info_matches (match_info)) { + handler->callback (self, match_info, handler->user_data); + g_match_info_next (match_info, NULL); + } + } + + g_match_info_free (match_info); + + if (matches) { + /* Remove matches */ + char *str; + int result_len = response->len; + + str = g_regex_replace_eval (handler->regex, + (const char *) response->data, + response->len, + 0, 0, + remove_eval_cb, &result_len, NULL); + + g_byte_array_remove_range (response, 0, response->len); + g_byte_array_append (response, (const guint8 *) str, result_len); + g_free (str); + } + } +} + +/*****************************************************************************/ + +static GByteArray * +at_command_to_byte_array (const char *command) +{ + GByteArray *buf; + int cmdlen; + + g_return_val_if_fail (command != NULL, NULL); + + cmdlen = strlen (command); + buf = g_byte_array_sized_new (cmdlen + 3); + + /* Make sure there's an AT in the front */ + if (!g_str_has_prefix (command, "AT")) + g_byte_array_append (buf, (const guint8 *) "AT", 2); + g_byte_array_append (buf, (const guint8 *) command, cmdlen); + + /* Make sure there's a trailing carriage return */ + if (command[cmdlen] != '\r') + g_byte_array_append (buf, (const guint8 *) "\r", 1); + + return buf; +} + +void +mm_at_serial_port_queue_command (MMAtSerialPort *self, + const char *command, + guint32 timeout_seconds, + MMAtSerialResponseFn callback, + gpointer user_data) +{ + GByteArray *buf; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); + g_return_if_fail (command != NULL); + + buf = at_command_to_byte_array (command); + g_return_if_fail (buf != NULL); + + mm_serial_port_queue_command (MM_SERIAL_PORT (self), + buf, + TRUE, + timeout_seconds, + G_CALLBACK (callback), + user_data); +} + +void +mm_at_serial_port_queue_command_cached (MMAtSerialPort *self, + const char *command, + guint32 timeout_seconds, + MMAtSerialResponseFn callback, + gpointer user_data) +{ + GByteArray *buf; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_AT_SERIAL_PORT (self)); + g_return_if_fail (command != NULL); + + buf = at_command_to_byte_array (command); + g_return_if_fail (buf != NULL); + + mm_serial_port_queue_command_cached (MM_SERIAL_PORT (self), + buf, + TRUE, + timeout_seconds, + G_CALLBACK (callback), + user_data); +} + +/*****************************************************************************/ + +MMAtSerialPort * +mm_at_serial_port_new (const char *name, MMPortType ptype) +{ + return MM_AT_SERIAL_PORT (g_object_new (MM_TYPE_AT_SERIAL_PORT, + MM_PORT_DEVICE, name, + MM_PORT_SUBSYS, MM_PORT_SUBSYS_TTY, + MM_PORT_TYPE, ptype, + NULL)); +} + +static void +mm_at_serial_port_init (MMAtSerialPort *self) +{ +} + +static void +finalize (GObject *object) +{ + MMAtSerialPort *self = MM_AT_SERIAL_PORT (object); + MMAtSerialPortPrivate *priv = MM_AT_SERIAL_PORT_GET_PRIVATE (self); + + while (priv->unsolicited_msg_handlers) { + MMAtUnsolicitedMsgHandler *handler = (MMAtUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data; + + if (handler->notify) + handler->notify (handler->user_data); + + g_regex_unref (handler->regex); + g_slice_free (MMAtUnsolicitedMsgHandler, handler); + priv->unsolicited_msg_handlers = g_slist_delete_link (priv->unsolicited_msg_handlers, + priv->unsolicited_msg_handlers); + } + + if (priv->response_parser_notify) + priv->response_parser_notify (priv->response_parser_user_data); + + G_OBJECT_CLASS (mm_at_serial_port_parent_class)->finalize (object); +} + +static void +mm_at_serial_port_class_init (MMAtSerialPortClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMSerialPortClass *port_class = MM_SERIAL_PORT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMAtSerialPortPrivate)); + + /* Virtual methods */ + object_class->finalize = finalize; + + port_class->parse_unsolicited = parse_unsolicited; + port_class->parse_response = parse_response; + port_class->handle_response = handle_response; +} diff --git a/src/mm-at-serial-port.h b/src/mm-at-serial-port.h new file mode 100644 index 00000000..5d5f13f2 --- /dev/null +++ b/src/mm-at-serial-port.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. + */ + +#ifndef MM_AT_SERIAL_PORT_H +#define MM_AT_SERIAL_PORT_H + +#include <glib.h> +#include <glib/gtypes.h> +#include <glib-object.h> + +#include "mm-serial-port.h" + +#define MM_TYPE_AT_SERIAL_PORT (mm_at_serial_port_get_type ()) +#define MM_AT_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPort)) +#define MM_AT_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortClass)) +#define MM_IS_AT_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_AT_SERIAL_PORT)) +#define MM_IS_AT_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_AT_SERIAL_PORT)) +#define MM_AT_SERIAL_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_AT_SERIAL_PORT, MMAtSerialPortClass)) + +typedef struct _MMAtSerialPort MMAtSerialPort; +typedef struct _MMAtSerialPortClass MMAtSerialPortClass; + +typedef gboolean (*MMAtSerialResponseParserFn) (gpointer user_data, + GString *response, + GError **error); + +typedef void (*MMAtSerialUnsolicitedMsgFn) (MMAtSerialPort *port, + GMatchInfo *match_info, + gpointer user_data); + +typedef void (*MMAtSerialResponseFn) (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data); + +struct _MMAtSerialPort { + MMSerialPort parent; +}; + +struct _MMAtSerialPortClass { + MMSerialPortClass parent; +}; + +GType mm_at_serial_port_get_type (void); + +MMAtSerialPort *mm_at_serial_port_new (const char *name, MMPortType ptype); + +void mm_at_serial_port_add_unsolicited_msg_handler (MMAtSerialPort *self, + GRegex *regex, + MMAtSerialUnsolicitedMsgFn callback, + gpointer user_data, + GDestroyNotify notify); + +void mm_at_serial_port_set_response_parser (MMAtSerialPort *self, + MMAtSerialResponseParserFn fn, + gpointer user_data, + GDestroyNotify notify); + +void mm_at_serial_port_queue_command (MMAtSerialPort *self, + const char *command, + guint32 timeout_seconds, + MMAtSerialResponseFn callback, + gpointer user_data); + +void mm_at_serial_port_queue_command_cached (MMAtSerialPort *self, + const char *command, + guint32 timeout_seconds, + MMAtSerialResponseFn callback, + gpointer user_data); + +#endif /* MM_AT_SERIAL_PORT_H */ + diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c index 211b1fa1..3dde2097 100644 --- a/src/mm-generic-cdma.c +++ b/src/mm-generic-cdma.c @@ -23,7 +23,7 @@ #include "mm-generic-cdma.h" #include "mm-modem-cdma.h" #include "mm-modem-simple.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" #include "mm-errors.h" #include "mm-callback-info.h" #include "mm-serial-parsers.h" @@ -69,8 +69,8 @@ typedef struct { guint reg_state_changed_id; MMCallbackInfo *simple_connect_info; - MMSerialPort *primary; - MMSerialPort *secondary; + MMAtSerialPort *primary; + MMAtSerialPort *secondary; MMPort *data; } MMGenericCdmaPrivate; @@ -150,22 +150,22 @@ mm_generic_cdma_grab_port (MMGenericCdma *self, } port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); - mm_serial_port_set_response_parser (MM_SERIAL_PORT (port), - mm_serial_parser_v1_e1_parse, - mm_serial_parser_v1_e1_new (), - mm_serial_parser_v1_e1_destroy); + mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), + mm_serial_parser_v1_e1_parse, + mm_serial_parser_v1_e1_new (), + mm_serial_parser_v1_e1_destroy); if (ptype == MM_PORT_TYPE_PRIMARY) { - priv->primary = MM_SERIAL_PORT (port); + priv->primary = MM_AT_SERIAL_PORT (port); if (!priv->data) { priv->data = port; g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); } check_valid (self); } else if (ptype == MM_PORT_TYPE_SECONDARY) - priv->secondary = MM_SERIAL_PORT (port); + priv->secondary = MM_AT_SERIAL_PORT (port); } else { /* Net device (if any) is the preferred data port */ if (!priv->data || MM_IS_SERIAL_PORT (priv->data)) { @@ -217,9 +217,9 @@ release_port (MMModem *modem, const char *subsys, const char *name) check_valid (MM_GENERIC_CDMA (modem)); } -MMSerialPort * -mm_generic_cdma_get_port (MMGenericCdma *modem, - MMPortType ptype) +MMAtSerialPort * +mm_generic_cdma_get_at_port (MMGenericCdma *modem, + MMPortType ptype) { g_return_val_if_fail (MM_IS_GENERIC_CDMA (modem), NULL); g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL); @@ -361,11 +361,11 @@ enable_all_done (MMModem *modem, GError *error, gpointer user_data) info->error = g_error_copy (error); else { /* Try to enable XON/XOFF flow control */ - mm_serial_port_queue_command (priv->primary, "+IFC=1,1", 3, NULL, NULL); + mm_at_serial_port_queue_command (priv->primary, "+IFC=1,1", 3, NULL, NULL); /* Open up the second port, if one exists */ if (priv->secondary) { - if (!mm_serial_port_open (priv->secondary, &info->error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &info->error)) { g_assert (info->error); goto out; } @@ -385,7 +385,7 @@ out: } static void -enable_error_reporting_done (MMSerialPort *port, +enable_error_reporting_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -404,7 +404,7 @@ enable_error_reporting_done (MMSerialPort *port, } static void -init_done (MMSerialPort *port, +init_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -424,7 +424,7 @@ init_done (MMSerialPort *port, FIXME: It's mandatory by spec, so it really shouldn't be optional. Figure out which CDMA modems have problems with it and implement plugin for them. */ - mm_serial_port_queue_command (port, "+CMEE=1", 3, enable_error_reporting_done, user_data); + mm_at_serial_port_queue_command (port, "+CMEE=1", 3, enable_error_reporting_done, user_data); } } @@ -444,7 +444,7 @@ flash_done (MMSerialPort *port, GError *error, gpointer user_data) return; } - mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1", 3, init_done, user_data); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "Z E0 V1 X4 &C1", 3, init_done, user_data); } static void @@ -458,7 +458,7 @@ enable (MMModem *modem, info = mm_callback_info_new (modem, callback, user_data); - if (!mm_serial_port_open (priv->primary, &info->error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &info->error)) { g_assert (info->error); mm_callback_info_schedule (info); return; @@ -468,7 +468,7 @@ enable (MMModem *modem, MM_MODEM_STATE_ENABLING, MM_MODEM_STATE_REASON_NONE); - mm_serial_port_flash (priv->primary, 100, flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 100, flash_done, info); } static void @@ -494,7 +494,7 @@ disable_all_done (MMModem *modem, GError *error, gpointer user_data) MMGenericCdma *self = MM_GENERIC_CDMA (info->modem); MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (self); - mm_serial_port_close (priv->primary); + mm_serial_port_close (MM_SERIAL_PORT (priv->primary)); mm_modem_set_state (modem, MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_REASON_NONE); priv->cdma_1x_reg_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN; @@ -551,20 +551,20 @@ disable (MMModem *modem, NULL); if (priv->secondary) - mm_serial_port_close (priv->secondary); + mm_serial_port_close (MM_SERIAL_PORT (priv->secondary)); mm_modem_set_state (MM_MODEM (info->modem), MM_MODEM_STATE_DISABLING, MM_MODEM_STATE_REASON_NONE); if (mm_port_get_connected (MM_PORT (priv->primary))) - mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disable_flash_done, info); else - disable_flash_done (priv->primary, NULL, info); + disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info); } static void -dial_done (MMSerialPort *port, +dial_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -603,7 +603,7 @@ connect (MMModem *modem, info = mm_callback_info_new (modem, callback, user_data); command = g_strconcat ("DT", number, NULL); - mm_serial_port_queue_command (priv->primary, command, 90, dial_done, info); + mm_at_serial_port_queue_command (priv->primary, command, 90, dial_done, info); g_free (command); } @@ -653,7 +653,7 @@ disconnect (MMModem *modem, NULL); mm_modem_set_state (modem, MM_MODEM_STATE_DISCONNECTING, MM_MODEM_STATE_REASON_NONE); - mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disconnect_flash_done, info); } static void @@ -683,7 +683,7 @@ strip_response (const char *resp, const char *cmd) } static void -get_version_done (MMSerialPort *port, +get_version_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -701,7 +701,7 @@ get_version_done (MMSerialPort *port, } static void -get_model_done (MMSerialPort *port, +get_model_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -717,7 +717,7 @@ get_model_done (MMSerialPort *port, } static void -get_manufacturer_done (MMSerialPort *port, +get_manufacturer_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -739,7 +739,7 @@ get_card_info (MMModem *modem, { MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem); MMCallbackInfo *info; - MMSerialPort *port = priv->primary; + MMAtSerialPort *port = priv->primary; info = mm_callback_info_new_full (MM_MODEM (modem), card_info_invoke, @@ -758,9 +758,9 @@ get_card_info (MMModem *modem, port = priv->secondary; } - mm_serial_port_queue_command_cached (port, "+GMI", 3, get_manufacturer_done, info); - mm_serial_port_queue_command_cached (port, "+GMM", 3, get_model_done, info); - mm_serial_port_queue_command_cached (port, "+GMR", 3, get_version_done, info); + mm_at_serial_port_queue_command_cached (port, "+GMI", 3, get_manufacturer_done, info); + mm_at_serial_port_queue_command_cached (port, "+GMM", 3, get_model_done, info); + mm_at_serial_port_queue_command_cached (port, "+GMR", 3, get_version_done, info); } /*****************************************************************************/ @@ -798,7 +798,7 @@ mm_generic_cdma_update_evdo_quality (MMGenericCdma *self, guint32 quality) #define CSQ2_TRIED "csq?-tried" static void -get_signal_quality_done (MMSerialPort *port, +get_signal_quality_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -816,7 +816,7 @@ get_signal_quality_done (MMSerialPort *port, * try the other command if the first one fails. */ mm_callback_info_set_data (info, CSQ2_TRIED, GUINT_TO_POINTER (1), NULL); - mm_serial_port_queue_command (port, "+CSQ?", 3, get_signal_quality_done, info); + mm_at_serial_port_queue_command (port, "+CSQ?", 3, get_signal_quality_done, info); return; } } else { @@ -858,7 +858,7 @@ get_signal_quality (MMModemCdma *modem, { MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem); MMCallbackInfo *info; - MMSerialPort *port = priv->primary; + MMAtSerialPort *port = priv->primary; if (mm_port_get_connected (MM_PORT (priv->primary))) { if (!priv->secondary) { @@ -872,11 +872,11 @@ get_signal_quality (MMModemCdma *modem, } info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_queue_command (port, "+CSQ", 3, get_signal_quality_done, info); + mm_at_serial_port_queue_command (port, "+CSQ", 3, get_signal_quality_done, info); } static void -get_string_done (MMSerialPort *port, +get_string_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -902,7 +902,7 @@ get_esn (MMModemCdma *modem, MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem); MMCallbackInfo *info; GError *error; - MMSerialPort *port = priv->primary; + MMAtSerialPort *port = priv->primary; if (mm_port_get_connected (MM_PORT (priv->primary))) { if (!priv->secondary) { @@ -918,7 +918,7 @@ get_esn (MMModemCdma *modem, } info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_queue_command_cached (port, "+GSN", 3, get_string_done, info); + mm_at_serial_port_queue_command_cached (port, "+GSN", 3, get_string_done, info); } static void @@ -1002,7 +1002,7 @@ convert_sid (const char *sid) } static void -serving_system_done (MMSerialPort *port, +serving_system_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1121,7 +1121,7 @@ get_serving_system (MMModemCdma *modem, MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem); MMCallbackInfo *info; GError *error; - MMSerialPort *port = priv->primary; + MMAtSerialPort *port = priv->primary; if (mm_port_get_connected (MM_PORT (priv->primary))) { if (!priv->secondary) { @@ -1141,7 +1141,7 @@ get_serving_system (MMModemCdma *modem, G_CALLBACK (callback), user_data); - mm_serial_port_queue_command (port, "+CSS?", 3, serving_system_done, info); + mm_at_serial_port_queue_command (port, "+CSS?", 3, serving_system_done, info); } #define CDMA_1X_STATE_TAG "cdma-1x-reg-state" @@ -1303,7 +1303,7 @@ reg_state_css_response (MMModemCdma *cdma, } static void -get_analog_digital_done (MMSerialPort *port, +get_analog_digital_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1370,7 +1370,7 @@ get_registration_state (MMModemCdma *modem, { MMGenericCdmaPrivate *priv = MM_GENERIC_CDMA_GET_PRIVATE (modem); MMCallbackInfo *info; - MMSerialPort *port = priv->primary; + MMAtSerialPort *port = priv->primary; if (mm_port_get_connected (MM_PORT (priv->primary))) { if (!priv->secondary) { @@ -1385,7 +1385,7 @@ get_registration_state (MMModemCdma *modem, } info = mm_generic_cdma_query_reg_state_callback_info_new (MM_GENERIC_CDMA (modem), callback, user_data); - mm_serial_port_queue_command (port, "+CAD?", 3, get_analog_digital_done, info); + mm_at_serial_port_queue_command (port, "+CAD?", 3, get_analog_digital_done, info); } /*****************************************************************************/ diff --git a/src/mm-generic-cdma.h b/src/mm-generic-cdma.h index f6e87675..18e1d61d 100644 --- a/src/mm-generic-cdma.h +++ b/src/mm-generic-cdma.h @@ -20,7 +20,7 @@ #include "mm-modem.h" #include "mm-modem-base.h" #include "mm-modem-cdma.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" #include "mm-callback-info.h" #define MM_TYPE_GENERIC_CDMA (mm_generic_cdma_get_type ()) @@ -78,7 +78,7 @@ MMPort * mm_generic_cdma_grab_port (MMGenericCdma *self, gpointer user_data, GError **error); -MMSerialPort *mm_generic_cdma_get_port (MMGenericCdma *modem, MMPortType ptype); +MMAtSerialPort *mm_generic_cdma_get_at_port (MMGenericCdma *modem, MMPortType ptype); void mm_generic_cdma_update_cdma1x_quality (MMGenericCdma *self, guint32 quality); void mm_generic_cdma_update_evdo_quality (MMGenericCdma *self, guint32 quality); diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index cab564ae..0d55431d 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -26,6 +26,7 @@ #include "mm-modem-simple.h" #include "mm-errors.h" #include "mm-callback-info.h" +#include "mm-at-serial-port.h" #include "mm-serial-parsers.h" #include "mm-modem-helpers.h" #include "mm-options.h" @@ -83,27 +84,27 @@ typedef struct { guint32 signal_quality; gint cid; - MMSerialPort *primary; - MMSerialPort *secondary; + MMAtSerialPort *primary; + MMAtSerialPort *secondary; MMPort *data; } MMGenericGsmPrivate; -static void get_registration_status (MMSerialPort *port, MMCallbackInfo *info); -static void read_operator_code_done (MMSerialPort *port, +static void get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info); +static void read_operator_code_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data); -static void read_operator_name_done (MMSerialPort *port, +static void read_operator_name_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data); -static void reg_state_changed (MMSerialPort *port, +static void reg_state_changed (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data); -static void get_reg_status_done (MMSerialPort *port, +static void get_reg_status_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data); @@ -196,7 +197,7 @@ error_for_unlock_required (const char *unlock) } static void -pin_check_done (MMSerialPort *port, +pin_check_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -255,7 +256,7 @@ mm_generic_gsm_check_pin (MMGenericGsm *modem, priv = MM_GENERIC_GSM_GET_PRIVATE (modem); info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info); + mm_at_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info); } /*****************************************************************************/ @@ -341,7 +342,7 @@ initial_pin_check_done (MMModem *modem, GError *error, gpointer user_data) } else { priv->pin_checked = TRUE; if (close_port) - mm_serial_port_close (priv->primary); + mm_serial_port_close (MM_SERIAL_PORT (priv->primary)); check_valid (MM_GENERIC_GSM (modem)); } } @@ -357,7 +358,7 @@ initial_pin_check (MMGenericGsm *self) g_return_if_fail (priv->primary != NULL); - if (mm_serial_port_open (priv->primary, &error)) + if (mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error)) mm_generic_gsm_check_pin (self, initial_pin_check_done, GUINT_TO_POINTER (TRUE)); else { g_warning ("%s: failed to open serial port: (%d) %s", @@ -393,26 +394,26 @@ mm_generic_gsm_grab_port (MMGenericGsm *self, g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), FALSE); port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype); - if (port && MM_IS_SERIAL_PORT (port)) { + if (port && MM_IS_AT_SERIAL_PORT (port)) { GPtrArray *array; int i; - mm_serial_port_set_response_parser (MM_SERIAL_PORT (port), - mm_serial_parser_v1_parse, - mm_serial_parser_v1_new (), - mm_serial_parser_v1_destroy); + mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), + mm_serial_parser_v1_parse, + mm_serial_parser_v1_new (), + mm_serial_parser_v1_destroy); /* Set up CREG unsolicited message handlers */ array = mm_gsm_creg_regex_get (FALSE); for (i = 0; i < array->len; i++) { regex = g_ptr_array_index (array, i); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, reg_state_changed, self, NULL); + mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, reg_state_changed, self, NULL); } mm_gsm_creg_regex_destroy (array); if (ptype == MM_PORT_TYPE_PRIMARY) { - priv->primary = MM_SERIAL_PORT (port); + priv->primary = MM_AT_SERIAL_PORT (port); if (!priv->data) { priv->data = port; g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); @@ -422,7 +423,7 @@ mm_generic_gsm_grab_port (MMGenericGsm *self, initial_pin_check (self); } else if (ptype == MM_PORT_TYPE_SECONDARY) - priv->secondary = MM_SERIAL_PORT (port); + priv->secondary = MM_AT_SERIAL_PORT (port); } else { /* Net device (if any) is the preferred data port */ if (!priv->data || MM_IS_SERIAL_PORT (priv->data)) { @@ -496,7 +497,7 @@ release_port (MMModem *modem, const char *subsys, const char *name) } static void -reg_poll_response (MMSerialPort *port, +reg_poll_response (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -512,7 +513,7 @@ periodic_poll_cb (gpointer user_data) { MMGenericGsm *self = MM_GENERIC_GSM (user_data); MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - MMSerialPort *port = priv->primary; + MMAtSerialPort *port = priv->primary; if (mm_port_get_connected (MM_PORT (priv->primary))) { if (!priv->secondary) @@ -523,15 +524,15 @@ periodic_poll_cb (gpointer user_data) } if (priv->creg_poll) - mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, self); + mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, self); if (priv->cgreg_poll) - mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, self); + mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, self); return TRUE; /* continue running */ } static void -cgreg1_done (MMSerialPort *port, +cgreg1_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -551,13 +552,13 @@ cgreg1_done (MMSerialPort *port, priv->poll_id = g_timeout_add_seconds (10, periodic_poll_cb, info->modem); } /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); + mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); } mm_callback_info_schedule (info); } static void -cgreg2_done (MMSerialPort *port, +cgreg2_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -570,10 +571,10 @@ cgreg2_done (MMSerialPort *port, if (info->error) { g_clear_error (&info->error); /* Try CGREG=1 instead */ - mm_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info); + mm_at_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info); } else { /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); + mm_at_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); /* All done */ mm_callback_info_schedule (info); @@ -585,7 +586,7 @@ cgreg2_done (MMSerialPort *port, } static void -creg1_done (MMSerialPort *port, +creg1_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -605,10 +606,10 @@ creg1_done (MMSerialPort *port, priv->poll_id = g_timeout_add_seconds (10, periodic_poll_cb, info->modem); } /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); + mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); /* Now try to set up CGREG messages */ - mm_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); + mm_at_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); } else { /* Modem got removed */ mm_callback_info_schedule (info); @@ -616,7 +617,7 @@ creg1_done (MMSerialPort *port, } static void -creg2_done (MMSerialPort *port, +creg2_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -628,13 +629,13 @@ creg2_done (MMSerialPort *port, if (info->modem) { if (info->error) { g_clear_error (&info->error); - mm_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); + mm_at_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); } else { /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); + mm_at_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); /* Now try to set up CGREG messages */ - mm_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); + mm_at_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); } } else { /* Modem got removed */ @@ -672,10 +673,10 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self, MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_REASON_NONE); - if (priv->primary && mm_serial_port_is_open (priv->primary)) - mm_serial_port_close (priv->primary); - if (priv->secondary && mm_serial_port_is_open (priv->secondary)) - mm_serial_port_close (priv->secondary); + if (priv->primary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) + mm_serial_port_close (MM_SERIAL_PORT (priv->primary)); + if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) + mm_serial_port_close (MM_SERIAL_PORT (priv->secondary)); info->error = g_error_copy (error); mm_callback_info_schedule (info); @@ -691,7 +692,7 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self, * messages to the secondary port but not the primary. */ if (priv->secondary) { - if (!mm_serial_port_open (priv->secondary, &error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (priv->secondary), &error)) { if (mm_options_debug ()) { g_warning ("%s: error opening secondary port: (%d) %s", __func__, @@ -702,14 +703,14 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self, } /* Try to enable XON/XOFF flow control */ - mm_serial_port_queue_command (priv->primary, "+IFC=1,1", 3, NULL, NULL); + mm_at_serial_port_queue_command (priv->primary, "+IFC=1,1", 3, NULL, NULL); /* Get allowed mode */ if (MM_GENERIC_GSM_GET_CLASS (self)->get_allowed_mode) MM_GENERIC_GSM_GET_CLASS (self)->get_allowed_mode (self, get_allowed_mode_done, NULL); /* Set up unsolicited registration notifications */ - mm_serial_port_queue_command (priv->primary, "+CREG=2", 3, creg2_done, info); + mm_at_serial_port_queue_command (priv->primary, "+CREG=2", 3, creg2_done, info); } static void @@ -723,7 +724,7 @@ real_do_enable_power_up_done (MMGenericGsm *self, } static void -enable_done (MMSerialPort *port, +enable_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -742,7 +743,7 @@ enable_done (MMSerialPort *port, } static void -init_done (MMSerialPort *port, +init_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -758,15 +759,15 @@ init_done (MMSerialPort *port, /* Ensure echo is off after the init command; some modems ignore the * E0 when it's in the same like as ATZ (Option GIO322). */ - mm_serial_port_queue_command (port, "E0 +CMEE=1", 2, NULL, NULL); + mm_at_serial_port_queue_command (port, "E0 +CMEE=1", 2, NULL, NULL); g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD_OPTIONAL, &cmd, NULL); - mm_serial_port_queue_command (port, cmd, 2, NULL, NULL); + mm_at_serial_port_queue_command (port, cmd, 2, NULL, NULL); g_free (cmd); g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL); if (cmd && strlen (cmd)) - mm_serial_port_queue_command (port, cmd, 5, enable_done, user_data); + mm_at_serial_port_queue_command (port, cmd, 5, enable_done, user_data); else enable_done (port, NULL, NULL, user_data); g_free (cmd); @@ -784,7 +785,7 @@ enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data) } g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD, &cmd, NULL); - mm_serial_port_queue_command (port, cmd, 3, init_done, user_data); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), cmd, 3, init_done, user_data); g_free (cmd); } @@ -795,7 +796,7 @@ real_do_enable (MMGenericGsm *self, MMModemFn callback, gpointer user_data) MMCallbackInfo *info; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); - mm_serial_port_flash (priv->primary, 100, enable_flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 100, enable_flash_done, info); } static void @@ -821,7 +822,7 @@ enable (MMModem *modem, /* First, reset the previously used CID */ priv->cid = -1; - if (!mm_serial_port_open (priv->primary, &error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error)) { MMCallbackInfo *info; g_assert (error); @@ -838,7 +839,7 @@ enable (MMModem *modem, } static void -disable_done (MMSerialPort *port, +disable_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -849,7 +850,7 @@ disable_done (MMSerialPort *port, if (!info->error) { MMGenericGsm *self = MM_GENERIC_GSM (info->modem); - mm_serial_port_close (port); + mm_serial_port_close (MM_SERIAL_PORT (port)); mm_modem_set_state (MM_MODEM (info->modem), MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_REASON_NONE); @@ -888,9 +889,9 @@ disable_flash_done (MMSerialPort *port, g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_DOWN_CMD, &cmd, NULL); if (cmd && strlen (cmd)) - mm_serial_port_queue_command (port, cmd, 5, disable_done, user_data); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), cmd, 5, disable_done, user_data); else - disable_done (port, NULL, NULL, user_data); + disable_done (MM_AT_SERIAL_PORT (port), NULL, NULL, user_data); g_free (cmd); } @@ -927,8 +928,8 @@ disable (MMModem *modem, _internal_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN); /* Close the secondary port if its open */ - if (priv->secondary && mm_serial_port_is_open (priv->secondary)) - mm_serial_port_close (priv->secondary); + if (priv->secondary && mm_serial_port_is_open (MM_SERIAL_PORT (priv->secondary))) + mm_serial_port_close (MM_SERIAL_PORT (priv->secondary)); info = mm_callback_info_new (modem, callback, user_data); @@ -944,13 +945,13 @@ disable (MMModem *modem, MM_MODEM_STATE_REASON_NONE); if (mm_port_get_connected (MM_PORT (priv->primary))) - mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disable_flash_done, info); else - disable_flash_done (priv->primary, NULL, info); + disable_flash_done (MM_SERIAL_PORT (priv->primary), NULL, info); } static void -get_string_done (MMSerialPort *port, +get_string_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -974,7 +975,7 @@ get_imei (MMModemGsmCard *modem, MMCallbackInfo *info; info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_queue_command_cached (priv->primary, "+CGSN", 3, get_string_done, info); + mm_at_serial_port_queue_command_cached (priv->primary, "+CGSN", 3, get_string_done, info); } static void @@ -986,7 +987,7 @@ get_imsi (MMModemGsmCard *modem, MMCallbackInfo *info; info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info); + mm_at_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info); } static void @@ -1017,7 +1018,7 @@ strip_tag (const char *str, const char *tag) } static void -get_version_done (MMSerialPort *port, +get_version_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1034,7 +1035,7 @@ get_version_done (MMSerialPort *port, } static void -get_model_done (MMSerialPort *port, +get_model_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1049,7 +1050,7 @@ get_model_done (MMSerialPort *port, } static void -get_manufacturer_done (MMSerialPort *port, +get_manufacturer_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1076,9 +1077,9 @@ get_card_info (MMModem *modem, G_CALLBACK (callback), user_data); - mm_serial_port_queue_command_cached (priv->primary, "+CGMI", 3, get_manufacturer_done, info); - mm_serial_port_queue_command_cached (priv->primary, "+CGMM", 3, get_model_done, info); - mm_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info); + mm_at_serial_port_queue_command_cached (priv->primary, "+CGMI", 3, get_manufacturer_done, info); + mm_at_serial_port_queue_command_cached (priv->primary, "+CGMM", 3, get_model_done, info); + mm_at_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info); } #define PIN_CLOSE_PORT_TAG "close-port" @@ -1094,14 +1095,18 @@ pin_puk_recheck_done (MMModem *modem, GError *error, gpointer user_data) */ info->error = mm_modem_check_removed (modem, error); - if (modem && close_port) - mm_serial_port_close (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary); + if (modem && close_port) { + MMSerialPort *port; + + port = MM_SERIAL_PORT (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary); + mm_serial_port_close (port); + } mm_callback_info_schedule (info); } static void -send_puk_done (MMSerialPort *port, +send_puk_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1113,7 +1118,7 @@ send_puk_done (MMSerialPort *port, info->error = g_error_copy (error); mm_callback_info_schedule (info); if (close_port) - mm_serial_port_close (port); + mm_serial_port_close (MM_SERIAL_PORT (port)); return; } @@ -1143,11 +1148,11 @@ send_puk (MMModemGsmCard *modem, "Cannot unlock device while connected"); mm_callback_info_schedule (info); return; - } else if (!mm_serial_port_is_open (priv->primary)) { + } else if (!mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) { /* Modem may not be enabled yet, which sometimes can't be done until * the device has been unlocked. */ - if (!mm_serial_port_open (priv->primary, &info->error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &info->error)) { mm_callback_info_schedule (info); return; } @@ -1157,12 +1162,12 @@ send_puk (MMModemGsmCard *modem, } command = g_strdup_printf ("+CPIN=\"%s\",\"%s\"", puk, pin); - mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_puk_done, info); + mm_at_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_puk_done, info); g_free (command); } static void -send_pin_done (MMSerialPort *port, +send_pin_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1174,7 +1179,7 @@ send_pin_done (MMSerialPort *port, info->error = g_error_copy (error); mm_callback_info_schedule (info); if (close_port) - mm_serial_port_close (port); + mm_serial_port_close (MM_SERIAL_PORT (port)); return; } @@ -1203,11 +1208,11 @@ send_pin (MMModemGsmCard *modem, "Cannot unlock device while connected"); mm_callback_info_schedule (info); return; - } else if (!mm_serial_port_is_open (priv->primary)) { + } else if (!mm_serial_port_is_open (MM_SERIAL_PORT (priv->primary))) { /* Modem may not be enabled yet, which sometimes can't be done until * the device has been unlocked. */ - if (!mm_serial_port_open (priv->primary, &info->error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &info->error)) { mm_callback_info_schedule (info); return; } @@ -1217,12 +1222,12 @@ send_pin (MMModemGsmCard *modem, } command = g_strdup_printf ("+CPIN=\"%s\"", pin); - mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_pin_done, info); + mm_at_serial_port_queue_command (connected ? priv->secondary : priv->primary, command, 3, send_pin_done, info); g_free (command); } static void -enable_pin_done (MMSerialPort *port, +enable_pin_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1247,12 +1252,12 @@ enable_pin (MMModemGsmCard *modem, info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); command = g_strdup_printf ("+CLCK=\"SC\",%d,\"%s\"", enabled ? 1 : 0, pin); - mm_serial_port_queue_command (priv->primary, command, 3, enable_pin_done, info); + mm_at_serial_port_queue_command (priv->primary, command, 3, enable_pin_done, info); g_free (command); } static void -change_pin_done (MMSerialPort *port, +change_pin_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1277,7 +1282,7 @@ change_pin (MMModemGsmCard *modem, info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); command = g_strdup_printf ("+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin); - mm_serial_port_queue_command (priv->primary, command, 3, change_pin_done, info); + mm_at_serial_port_queue_command (priv->primary, command, 3, change_pin_done, info); g_free (command); } @@ -1351,7 +1356,7 @@ parse_operator (const char *reply) } static void -read_operator_code_done (MMSerialPort *port, +read_operator_code_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1367,7 +1372,7 @@ read_operator_code_done (MMSerialPort *port, } static void -read_operator_name_done (MMSerialPort *port, +read_operator_name_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1432,8 +1437,8 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem, if (status == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) { - mm_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem); - mm_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem); + mm_at_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem); + mm_at_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem); mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL); } else reg_info_updated (MM_GENERIC_GSM (modem), FALSE, 0, TRUE, NULL, TRUE, NULL); @@ -1505,7 +1510,7 @@ reg_status_updated (MMGenericGsm *self, int new_value, GError **error) } static void -reg_state_changed (MMSerialPort *port, +reg_state_changed (MMAtSerialPort *port, GMatchInfo *match_info, gpointer user_data) { @@ -1630,7 +1635,7 @@ handle_reg_status_response (MMGenericGsm *self, } static void -get_reg_status_done (MMSerialPort *port, +get_reg_status_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1681,13 +1686,13 @@ reg_done: } static void -get_registration_status (MMSerialPort *port, MMCallbackInfo *info) +get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info) { - mm_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info); + mm_at_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info); } static void -register_done (MMSerialPort *port, +register_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1774,7 +1779,7 @@ do_register (MMModemGsmNetwork *modem, * the +COPS response is never received. */ mm_callback_info_ref (info); - mm_serial_port_queue_command (priv->primary, command, 120, register_done, info); + mm_at_serial_port_queue_command (priv->primary, command, 120, register_done, info); g_free (command); } @@ -1837,7 +1842,7 @@ mm_generic_gsm_connect_complete (MMGenericGsm *modem, } static void -connect_report_done (MMSerialPort *port, +connect_report_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1868,7 +1873,7 @@ connect_report_done (MMSerialPort *port, } static void -connect_done (MMSerialPort *port, +connect_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1880,7 +1885,7 @@ connect_done (MMSerialPort *port, info->error = g_error_copy (error); /* Try to get more information why it failed */ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); - mm_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info); + mm_at_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info); } else mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), NULL, info); } @@ -1914,7 +1919,7 @@ connect (MMModem *modem, } else command = g_strconcat ("DT", number, NULL); - mm_serial_port_queue_command (priv->primary, command, 60, connect_done, info); + mm_at_serial_port_queue_command (priv->primary, command, 60, connect_done, info); g_free (command); } @@ -1948,7 +1953,7 @@ disconnect_done (MMModem *modem, } static void -disconnect_cgact_done (MMSerialPort *port, +disconnect_cgact_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1986,7 +1991,7 @@ disconnect_flash_done (MMSerialPort *port, command = g_strdup_printf ("+CGACT=0"); } - mm_serial_port_queue_command (port, command, 3, disconnect_cgact_done, info); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), command, 3, disconnect_cgact_done, info); g_free (command); } @@ -2000,7 +2005,7 @@ real_do_disconnect (MMGenericGsm *self, MMCallbackInfo *info; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); - mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info); + mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, disconnect_flash_done, info); } static void @@ -2040,7 +2045,7 @@ gsm_network_scan_invoke (MMCallbackInfo *info) } static void -scan_done (MMSerialPort *port, +scan_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -2072,7 +2077,7 @@ scan (MMModemGsmNetwork *modem, G_CALLBACK (callback), user_data); - mm_serial_port_queue_command (priv->primary, "+COPS=?", 120, scan_done, info); + mm_at_serial_port_queue_command (priv->primary, "+COPS=?", 120, scan_done, info); } /* SetApn */ @@ -2080,7 +2085,7 @@ scan (MMModemGsmNetwork *modem, #define APN_CID_TAG "generic-gsm-cid" static void -set_apn_done (MMSerialPort *port, +set_apn_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -2098,7 +2103,7 @@ set_apn_done (MMSerialPort *port, } static void -cid_range_read (MMSerialPort *port, +cid_range_read (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -2158,13 +2163,13 @@ cid_range_read (MMSerialPort *port, mm_callback_info_set_data (info, APN_CID_TAG, GINT_TO_POINTER (cid), NULL); command = g_strdup_printf ("+CGDCONT=%d,\"IP\",\"%s\"", cid, apn); - mm_serial_port_queue_command (port, command, 3, set_apn_done, info); + mm_at_serial_port_queue_command (port, command, 3, set_apn_done, info); g_free (command); } } static void -existing_apns_read (MMSerialPort *port, +existing_apns_read (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -2231,7 +2236,7 @@ done: mm_callback_info_schedule (info); else { /* APN not configured on the card. Get the allowed CID range */ - mm_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info); + mm_at_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info); } } @@ -2248,7 +2253,7 @@ set_apn (MMModemGsmNetwork *modem, mm_callback_info_set_data (info, "apn", g_strdup (apn), g_free); /* Start by searching if the APN is already in card */ - mm_serial_port_queue_command (priv->primary, "+CGDCONT?", 3, existing_apns_read, info); + mm_at_serial_port_queue_command (priv->primary, "+CGDCONT?", 3, existing_apns_read, info); } /* GetSignalQuality */ @@ -2319,7 +2324,7 @@ mm_generic_gsm_update_signal_quality (MMGenericGsm *self, guint32 quality) } static void -get_signal_quality_done (MMSerialPort *port, +get_signal_quality_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -2379,7 +2384,7 @@ get_signal_quality (MMModemGsmNetwork *modem, } info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info); + mm_at_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info); } /*****************************************************************************/ @@ -2520,7 +2525,7 @@ set_allowed_mode (MMModemGsmNetwork *net, /* MMModemGsmSms interface */ static void -sms_send_done (MMSerialPort *port, +sms_send_done (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -2547,7 +2552,7 @@ sms_send (MMModemGsmSms *modem, MMCallbackInfo *info; char *command; gboolean connected; - MMSerialPort *port = NULL; + MMAtSerialPort *port = NULL; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); @@ -2566,16 +2571,16 @@ sms_send (MMModemGsmSms *modem, } /* FIXME: use the PDU mode instead */ - mm_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL); command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text); - mm_serial_port_queue_command (port, command, 10, sms_send_done, info); + mm_at_serial_port_queue_command (port, command, 10, sms_send_done, info); g_free (command); } -MMSerialPort * -mm_generic_gsm_get_port (MMGenericGsm *modem, - MMPortType ptype) +MMAtSerialPort * +mm_generic_gsm_get_at_port (MMGenericGsm *modem, + MMPortType ptype) { g_return_val_if_fail (MM_IS_GENERIC_GSM (modem), NULL); g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL); diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 9aef615e..2ef81c3c 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -20,7 +20,7 @@ #include "mm-modem-gsm.h" #include "mm-modem-gsm-network.h" #include "mm-modem-base.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" #include "mm-callback-info.h" #define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ()) @@ -148,8 +148,8 @@ void mm_generic_gsm_check_pin (MMGenericGsm *modem, MMModemFn callback, gpointer user_data); -MMSerialPort *mm_generic_gsm_get_port (MMGenericGsm *modem, - MMPortType ptype); +MMAtSerialPort *mm_generic_gsm_get_at_port (MMGenericGsm *modem, + MMPortType ptype); MMPort *mm_generic_gsm_grab_port (MMGenericGsm *modem, const char *subsys, diff --git a/src/mm-manager.c b/src/mm-manager.c index 389acba1..9576766c 100644 --- a/src/mm-manager.c +++ b/src/mm-manager.c @@ -520,7 +520,7 @@ device_added (MMManager *manager, GUdevDevice *device) /* ignore VTs */ if (strncmp (name, "tty", 3) == 0 && isdigit (name[3])) - return; + return; if (find_modem_for_port (manager, subsys, name)) return; @@ -633,12 +633,18 @@ mm_manager_start (MMManager *manager) priv = MM_MANAGER_GET_PRIVATE (manager); devices = g_udev_client_query_by_subsystem (priv->udev, "tty"); - for (iter = devices; iter; iter = g_list_next (iter)) + for (iter = devices; iter; iter = g_list_next (iter)) { device_added (manager, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_OBJECT (iter->data)); + } + g_list_free (devices); devices = g_udev_client_query_by_subsystem (priv->udev, "net"); - for (iter = devices; iter; iter = g_list_next (iter)) + for (iter = devices; iter; iter = g_list_next (iter)) { device_added (manager, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_OBJECT (iter->data)); + } + g_list_free (devices); } static void diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index 890c55c7..8af9bd14 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -21,7 +21,7 @@ #include "mm-modem-base.h" #include "mm-modem.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" #include "mm-errors.h" #include "mm-options.h" #include "mm-properties-changed-signal.h" @@ -115,7 +115,7 @@ mm_modem_base_add_port (MMModemBase *self, } if (!strcmp (subsys, "tty")) - port = MM_PORT (mm_serial_port_new (name, ptype)); + port = MM_PORT (mm_at_serial_port_new (name, ptype)); else if (!strcmp (subsys, "net")) { port = MM_PORT (g_object_new (MM_TYPE_PORT, MM_PORT_DEVICE, name, diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c index 4b74feb7..9e2532b2 100644 --- a/src/mm-plugin-base.c +++ b/src/mm-plugin-base.c @@ -26,7 +26,7 @@ #include <gudev/gudev.h> #include "mm-plugin-base.h" -#include "mm-serial-port.h" +#include "mm-at-serial-port.h" #include "mm-serial-parsers.h" #include "mm-errors.h" #include "mm-marshal.h" @@ -95,7 +95,7 @@ typedef struct { guint32 open_tries; guint full_id; - MMSerialPort *probe_port; + MMAtSerialPort *probe_port; guint32 probed_caps; ProbeState probe_state; guint probe_id; @@ -265,7 +265,7 @@ supports_task_dispose (GObject *object) if (priv->probe_id) g_source_remove (priv->probe_id); if (priv->probe_port) { - mm_serial_port_close (priv->probe_port); + mm_serial_port_close (MM_SERIAL_PORT (priv->probe_port)); g_object_unref (priv->probe_port); } @@ -391,7 +391,7 @@ port_buffer_full (MMSerialPort *port, GString *buffer, gpointer user_data) if (!memcmp (&buffer->str[i], *iter, iter_len)) { /* Immediately close the port and complete probing */ priv->probed_caps = 0; - mm_serial_port_close (priv->probe_port); + mm_serial_port_close (MM_SERIAL_PORT (priv->probe_port)); probe_complete (task); return; } @@ -428,7 +428,7 @@ probe_complete (MMPluginBaseSupportsTask *task) } static void -parse_response (MMSerialPort *port, +parse_response (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data); @@ -441,7 +441,7 @@ real_handle_probe_response (MMPluginBase *self, const GError *error) { MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); - MMSerialPort *port = task_priv->probe_port; + MMAtSerialPort *port = task_priv->probe_port; gboolean ignore_error = FALSE; /* Some modems (Huawei E160g) won't respond to +GCAP with no SIM, but @@ -455,7 +455,7 @@ real_handle_probe_response (MMPluginBase *self, /* Try GCAP again */ if (task_priv->probe_state < PROBE_STATE_GCAP_TRY3) { task_priv->probe_state++; - mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task); + mm_at_serial_port_queue_command (port, "+GCAP", 3, parse_response, task); } else { /* Otherwise, if all the GCAP tries timed out, ignore the port * as it's probably not an AT-capable port. @@ -509,19 +509,19 @@ real_handle_probe_response (MMPluginBase *self, switch (task_priv->probe_state) { case PROBE_STATE_GCAP_TRY2: case PROBE_STATE_GCAP_TRY3: - mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, task); + mm_at_serial_port_queue_command (port, "+GCAP", 3, parse_response, task); break; case PROBE_STATE_ATI: /* After the last GCAP attempt, try ATI */ - mm_serial_port_queue_command (port, "I", 3, parse_response, task); + mm_at_serial_port_queue_command (port, "I", 3, parse_response, task); break; case PROBE_STATE_CPIN: /* After the ATI attempt, try CPIN */ - mm_serial_port_queue_command (port, "+CPIN?", 3, parse_response, task); + mm_at_serial_port_queue_command (port, "+CPIN?", 3, parse_response, task); break; case PROBE_STATE_CGMM: /* After the CPIN attempt, try CGMM */ - mm_serial_port_queue_command (port, "+CGMM", 3, parse_response, task); + mm_at_serial_port_queue_command (port, "+CGMM", 3, parse_response, task); break; default: /* Probably not GSM or CDMA */ @@ -565,7 +565,7 @@ handle_probe_response (gpointer user_data) } static void -parse_response (MMSerialPort *port, +parse_response (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -595,7 +595,7 @@ parse_response (MMSerialPort *port, static void flash_done (MMSerialPort *port, GError *error, gpointer user_data); static void -custom_init_response (MMSerialPort *port, +custom_init_response (MMAtSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -607,7 +607,7 @@ custom_init_response (MMSerialPort *port, task_priv->custom_init_tries++; if (task_priv->custom_init_tries < task_priv->custom_init_max_tries) { /* Try the custom command again */ - flash_done (port, NULL, user_data); + flash_done (MM_SERIAL_PORT (port), NULL, user_data); return; } else if (task_priv->custom_init_fail_if_timeout) { /* Fail the probe if the plugin wanted it and the command timed out */ @@ -619,7 +619,7 @@ custom_init_response (MMSerialPort *port, } /* Otherwise proceed to probing */ - mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data); + mm_at_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data); } static void @@ -633,14 +633,14 @@ flash_done (MMSerialPort *port, GError *error, gpointer user_data) if (task_priv->custom_init) { if (!delay_secs) delay_secs = 3; - mm_serial_port_queue_command (port, - task_priv->custom_init, - delay_secs, - custom_init_response, - user_data); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), + task_priv->custom_init, + delay_secs, + custom_init_response, + user_data); } else { /* Otherwise start normal probing */ - custom_init_response (port, NULL, NULL, user_data); + custom_init_response (MM_AT_SERIAL_PORT (port), NULL, NULL, user_data); } } @@ -653,7 +653,7 @@ try_open (gpointer user_data) task_priv->open_id = 0; - if (!mm_serial_port_open (task_priv->probe_port, &error)) { + if (!mm_serial_port_open (MM_SERIAL_PORT (task_priv->probe_port), &error)) { if (++task_priv->open_tries > 4) { /* took too long to open the port; give up */ g_warning ("(%s): failed to open after 4 tries.", @@ -682,7 +682,7 @@ try_open (gpointer user_data) g_debug ("(%s): probe requested by plugin '%s'", g_udev_device_get_name (port), mm_plugin_get_name (MM_PLUGIN (task_priv->plugin))); - mm_serial_port_flash (task_priv->probe_port, 100, flash_done, task); + mm_serial_port_flash (MM_SERIAL_PORT (task_priv->probe_port), 100, flash_done, task); } return FALSE; @@ -694,7 +694,7 @@ mm_plugin_base_probe_port (MMPluginBase *self, GError **error) { MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); - MMSerialPort *serial; + MMAtSerialPort *serial; const char *name; GUdevDevice *port; @@ -707,7 +707,7 @@ mm_plugin_base_probe_port (MMPluginBase *self, name = g_udev_device_get_name (port); g_assert (name); - serial = mm_serial_port_new (name, MM_PORT_TYPE_PRIMARY); + serial = mm_at_serial_port_new (name, MM_PORT_TYPE_PRIMARY); if (serial == NULL) { g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Failed to create new serial port."); @@ -719,10 +719,10 @@ mm_plugin_base_probe_port (MMPluginBase *self, MM_PORT_CARRIER_DETECT, FALSE, NULL); - mm_serial_port_set_response_parser (serial, - mm_serial_parser_v1_parse, - mm_serial_parser_v1_new (), - mm_serial_parser_v1_destroy); + mm_at_serial_port_set_response_parser (serial, + mm_serial_parser_v1_parse, + mm_serial_parser_v1_new (), + mm_serial_parser_v1_destroy); /* Open the port */ task_priv->probe_port = serial; diff --git a/src/mm-qcdm-serial-port.c b/src/mm-qcdm-serial-port.c new file mode 100644 index 00000000..51d7c189 --- /dev/null +++ b/src/mm-qcdm-serial-port.c @@ -0,0 +1,176 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "mm-qcdm-serial-port.h" +#include "mm-errors.h" +#include "mm-options.h" +#include "libqcdm/src/com.h" +#include "libqcdm/src/utils.h" + +G_DEFINE_TYPE (MMQcdmSerialPort, mm_qcdm_serial_port, MM_TYPE_SERIAL_PORT) + +#define MM_QCDM_SERIAL_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_QCDM_SERIAL_PORT, MMQcdmSerialPortPrivate)) + +typedef struct { + gboolean foo; +} MMQcdmSerialPortPrivate; + + +/*****************************************************************************/ + +static gboolean +parse_response (MMSerialPort *port, GByteArray *response, GError **error) +{ + int i; + + /* Look for the QCDM packet termination character; if we found it, treat + * the buffer as a qcdm command. + */ + for (i = 0; i < response->len; i++) { + if (response->data[i] == 0x7E) + return TRUE; + } + + /* Otherwise, need more data from the device */ + return FALSE; +} + +static void +handle_response (MMSerialPort *port, + GByteArray *response, + GError *error, + GCallback callback, + gpointer callback_data) +{ + MMQcdmSerialResponseFn response_callback = (MMQcdmSerialResponseFn) callback; + GByteArray *unescaped = NULL; + gboolean escaping = FALSE; + GError *dm_error = NULL; + + if (!error) { + unescaped = g_byte_array_sized_new (response->len); + unescaped->len = dm_unescape ((const char *) response->data, response->len, + (char *) unescaped->data, unescaped->len, + &escaping); + if (unescaped->len == 0) { + g_set_error_literal (&dm_error, 0, 0, "Failed to unescape QCDM packet."); + g_byte_array_free (unescaped, TRUE); + unescaped = NULL; + } + } + + response_callback (MM_QCDM_SERIAL_PORT (port), + unescaped, + dm_error ? dm_error : error, + callback_data); + + if (unescaped) + g_byte_array_free (unescaped, TRUE); +} + +/*****************************************************************************/ + +void +mm_qcdm_serial_port_queue_command (MMQcdmSerialPort *self, + GByteArray *command, + guint32 timeout_seconds, + MMQcdmSerialResponseFn callback, + gpointer user_data) +{ + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_QCDM_SERIAL_PORT (self)); + g_return_if_fail (command != NULL); + + /* 'command' is expected to be already CRC-ed and escaped */ + mm_serial_port_queue_command (MM_SERIAL_PORT (self), + command, + TRUE, + timeout_seconds, + G_CALLBACK (callback), + user_data); +} + +void +mm_qcdm_serial_port_queue_command_cached (MMQcdmSerialPort *self, + GByteArray *command, + guint32 timeout_seconds, + MMQcdmSerialResponseFn callback, + gpointer user_data) +{ + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_QCDM_SERIAL_PORT (self)); + g_return_if_fail (command != NULL); + + /* 'command' is expected to be already CRC-ed and escaped */ + mm_serial_port_queue_command_cached (MM_SERIAL_PORT (self), + command, + TRUE, + timeout_seconds, + G_CALLBACK (callback), + user_data); +} + +/*****************************************************************************/ + +static gboolean +config_fd (MMSerialPort *port, int fd, GError **error) +{ + return qcdm_port_setup (fd, error); +} + +/*****************************************************************************/ + +MMQcdmSerialPort * +mm_qcdm_serial_port_new (const char *name, MMPortType ptype) +{ + return MM_QCDM_SERIAL_PORT (g_object_new (MM_TYPE_QCDM_SERIAL_PORT, + MM_PORT_DEVICE, name, + MM_PORT_SUBSYS, MM_PORT_SUBSYS_TTY, + MM_PORT_TYPE, ptype, + NULL)); +} + +static void +mm_qcdm_serial_port_init (MMQcdmSerialPort *self) +{ +} + +static void +finalize (GObject *object) +{ + G_OBJECT_CLASS (mm_qcdm_serial_port_parent_class)->finalize (object); +} + +static void +mm_qcdm_serial_port_class_init (MMQcdmSerialPortClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMSerialPortClass *port_class = MM_SERIAL_PORT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (MMQcdmSerialPortPrivate)); + + /* Virtual methods */ + object_class->finalize = finalize; + + port_class->parse_response = parse_response; + port_class->handle_response = handle_response; + port_class->config_fd = config_fd; +} diff --git a/src/mm-qcdm-serial-port.h b/src/mm-qcdm-serial-port.h new file mode 100644 index 00000000..e70e124b --- /dev/null +++ b/src/mm-qcdm-serial-port.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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: + * + * Copyright (C) 2008 - 2009 Novell, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. + */ + +#ifndef MM_QCDM_SERIAL_PORT_H +#define MM_QCDM_SERIAL_PORT_H + +#include <glib.h> +#include <glib/gtypes.h> +#include <glib-object.h> + +#include "mm-serial-port.h" + +#define MM_TYPE_QCDM_SERIAL_PORT (mm_qcdm_serial_port_get_type ()) +#define MM_QCDM_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_QCDM_SERIAL_PORT, MMQcdmSerialPort)) +#define MM_QCDM_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_QCDM_SERIAL_PORT, MMQcdmSerialPortClass)) +#define MM_IS_QCDM_SERIAL_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_QCDM_SERIAL_PORT)) +#define MM_IS_QCDM_SERIAL_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_QCDM_SERIAL_PORT)) +#define MM_QCDM_SERIAL_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_QCDM_SERIAL_PORT, MMQcdmSerialPortClass)) + +typedef struct _MMQcdmSerialPort MMQcdmSerialPort; +typedef struct _MMQcdmSerialPortClass MMQcdmSerialPortClass; + +typedef void (*MMQcdmSerialResponseFn) (MMQcdmSerialPort *port, + GByteArray *response, + GError *error, + gpointer user_data); + +struct _MMQcdmSerialPort { + MMSerialPort parent; +}; + +struct _MMQcdmSerialPortClass { + MMSerialPortClass parent; +}; + +GType mm_qcdm_serial_port_get_type (void); + +MMQcdmSerialPort *mm_qcdm_serial_port_new (const char *name, MMPortType ptype); + +void mm_qcdm_serial_port_queue_command (MMQcdmSerialPort *self, + GByteArray *command, + guint32 timeout_seconds, + MMQcdmSerialResponseFn callback, + gpointer user_data); + +void mm_qcdm_serial_port_queue_command_cached (MMQcdmSerialPort *self, + GByteArray *command, + guint32 timeout_seconds, + MMQcdmSerialResponseFn callback, + gpointer user_data); + +#endif /* MM_QCDM_SERIAL_PORT_H */ + diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c index 2134751f..29505a21 100644 --- a/src/mm-serial-port.c +++ b/src/mm-serial-port.c @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -55,16 +54,7 @@ typedef struct { GHashTable *reply_cache; GIOChannel *channel; GQueue *queue; - GString *command; - GString *response; - - gboolean connected; - - /* Response parser data */ - MMSerialResponseParserFn response_parser_fn; - gpointer response_parser_user_data; - GDestroyNotify response_parser_notify; - GSList *unsolicited_msg_handlers; + GByteArray *response; struct termios old_t; @@ -165,33 +155,6 @@ mm_serial_port_print_config (MMSerialPort *port, const char *detail) } #endif -typedef struct { - GRegex *regex; - MMSerialUnsolicitedMsgFn callback; - gpointer user_data; - GDestroyNotify notify; -} MMUnsolicitedMsgHandler; - -static void -mm_serial_port_set_cached_reply (MMSerialPort *self, - const char *command, - const char *reply) -{ - if (reply) - g_hash_table_insert (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, - g_strdup (command), - g_strdup (reply)); - else - g_hash_table_remove (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command); -} - -static const char * -mm_serial_port_get_cached_reply (MMSerialPort *self, - const char *command) -{ - return (char *) g_hash_table_lookup (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command); -} - static int parse_baudrate (guint i) { @@ -327,7 +290,7 @@ parse_stopbits (guint i) } static gboolean -config_fd (MMSerialPort *self, GError **error) +real_config_fd (MMSerialPort *self, int fd, GError **error) { MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); struct termio stbuf; @@ -342,7 +305,7 @@ config_fd (MMSerialPort *self, GError **error) stopbits = parse_stopbits (priv->stopbits); memset (&stbuf, 0, sizeof (struct termio)); - if (ioctl (priv->fd, TCGETA, &stbuf) != 0) { + if (ioctl (fd, TCGETA, &stbuf) != 0) { g_warning ("%s (%s): TCGETA error: %d", __func__, mm_port_get_device (MM_PORT (self)), @@ -366,7 +329,7 @@ config_fd (MMSerialPort *self, GError **error) stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | PARENB | CRTSCTS); stbuf.c_cflag |= (speed | bits | CREAD | 0 | parity | stopbits | CLOCAL); - if (ioctl (priv->fd, TCSETA, &stbuf) < 0) { + if (ioctl (fd, TCSETA, &stbuf) < 0) { g_set_error (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, @@ -417,13 +380,13 @@ serial_debug (MMSerialPort *self, const char *prefix, const char *buf, int len) static gboolean mm_serial_port_send_command (MMSerialPort *self, - const char *command, + GByteArray *command, GError **error) { MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); - const char *s; - int status; + int status, i = 0; int eagain_count = 1000; + const guint8 *p; if (priv->fd < 0) { g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_SEND_FAILED, @@ -437,21 +400,15 @@ mm_serial_port_send_command (MMSerialPort *self, return FALSE; } - g_string_truncate (priv->command, g_str_has_prefix (command, "AT") ? 0 : 2); - g_string_append (priv->command, command); - - if (command[strlen (command)] != '\r') - g_string_append_c (priv->command, '\r'); - - serial_debug (self, "-->", priv->command->str, -1); + serial_debug (self, "-->", (const char *) command->data, command->len); /* Only accept about 3 seconds of EAGAIN */ if (priv->send_delay > 0) eagain_count = 3000000 / priv->send_delay; - s = priv->command->str; - while (*s) { - status = write (priv->fd, s, 1); + while (i < command->len) { + p = &command->data[i]; + status = write (priv->fd, p, 1); if (status < 0) { if (errno == EAGAIN) { eagain_count--; @@ -466,18 +423,46 @@ mm_serial_port_send_command (MMSerialPort *self, break; } } else - s++; + i++; if (priv->send_delay) usleep (priv->send_delay); } - return *s == '\0'; + return i == command->len; +} + +static void +mm_serial_port_set_cached_reply (MMSerialPort *self, + const GByteArray *command, + const GByteArray *response) +{ + MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_SERIAL_PORT (self)); + g_return_if_fail (command != NULL); + + if (response) { + GByteArray *cmd_copy = g_byte_array_sized_new (command->len); + GByteArray *rsp_copy = g_byte_array_sized_new (response->len); + + g_byte_array_append (cmd_copy, command->data, command->len); + g_byte_array_append (rsp_copy, response->data, response->len); + g_hash_table_insert (priv->reply_cache, cmd_copy, rsp_copy); + } else + g_hash_table_remove (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command); +} + +static const GByteArray * +mm_serial_port_get_cached_reply (MMSerialPort *self, GByteArray *command) +{ + return (const GByteArray *) g_hash_table_lookup (MM_SERIAL_PORT_GET_PRIVATE (self)->reply_cache, command); } typedef struct { - char *command; - MMSerialResponseFn callback; + GByteArray *command; + GCallback callback; gpointer user_data; guint32 timeout; gboolean cached; @@ -520,19 +505,26 @@ mm_serial_port_got_response (MMSerialPort *self, GError *error) info = (MMQueueData *) g_queue_pop_head (priv->queue); if (info) { if (info->cached && !error) - mm_serial_port_set_cached_reply (self, info->command, priv->response->str); - - if (info->callback) - info->callback (self, priv->response, error, info->user_data); + mm_serial_port_set_cached_reply (self, info->command, priv->response); + + if (info->callback) { + g_warn_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->handle_response != NULL); + MM_SERIAL_PORT_GET_CLASS (self)->handle_response (self, + priv->response, + error, + info->callback, + info->user_data); + } - g_free (info->command); + g_byte_array_free (info->command, TRUE); g_slice_free (MMQueueData, info); } if (error) g_error_free (error); - g_string_truncate (priv->response, 0); + if (priv->response->len) + g_byte_array_remove_range (priv->response, 0, priv->response->len); if (!g_queue_is_empty (priv->queue)) mm_serial_port_schedule_queue_process (self); } @@ -572,10 +564,10 @@ mm_serial_port_queue_process (gpointer data) return FALSE; if (info->cached) { - const char *cached = mm_serial_port_get_cached_reply (self, info->command); + const GByteArray *cached = mm_serial_port_get_cached_reply (self, info->command); if (cached) { - g_string_append (priv->response, cached); + g_byte_array_append (priv->response, cached->data, cached->len); mm_serial_port_got_response (self, NULL); return FALSE; } @@ -596,111 +588,16 @@ mm_serial_port_queue_process (gpointer data) return FALSE; } -void -mm_serial_port_add_unsolicited_msg_handler (MMSerialPort *self, - GRegex *regex, - MMSerialUnsolicitedMsgFn callback, - gpointer user_data, - GDestroyNotify notify) -{ - MMUnsolicitedMsgHandler *handler; - MMSerialPortPrivate *priv; - - g_return_if_fail (MM_IS_SERIAL_PORT (self)); - g_return_if_fail (regex != NULL); - - handler = g_slice_new (MMUnsolicitedMsgHandler); - handler->regex = g_regex_ref (regex); - handler->callback = callback; - handler->user_data = user_data; - handler->notify = notify; - - priv = MM_SERIAL_PORT_GET_PRIVATE (self); - priv->unsolicited_msg_handlers = g_slist_append (priv->unsolicited_msg_handlers, handler); -} - -void -mm_serial_port_set_response_parser (MMSerialPort *self, - MMSerialResponseParserFn fn, - gpointer user_data, - GDestroyNotify notify) -{ - MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); - - g_return_if_fail (MM_IS_SERIAL_PORT (self)); - - if (priv->response_parser_notify) - priv->response_parser_notify (priv->response_parser_user_data); - - priv->response_parser_fn = fn; - priv->response_parser_user_data = user_data; - priv->response_parser_notify = notify; -} - -static gboolean -remove_eval_cb (const GMatchInfo *match_info, - GString *result, - gpointer user_data) -{ - int *result_len = (int *) user_data; - int start; - int end; - - if (g_match_info_fetch_pos (match_info, 0, &start, &end)) - *result_len -= (end - start); - - return FALSE; -} - -static void -parse_unsolicited_messages (MMSerialPort *self, - GString *response) -{ - MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); - GSList *iter; - - for (iter = priv->unsolicited_msg_handlers; iter; iter = iter->next) { - MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) iter->data; - GMatchInfo *match_info; - gboolean matches; - - matches = g_regex_match_full (handler->regex, response->str, response->len, 0, 0, &match_info, NULL); - if (handler->callback) { - while (g_match_info_matches (match_info)) { - handler->callback (self, match_info, handler->user_data); - g_match_info_next (match_info, NULL); - } - } - - g_match_info_free (match_info); - - if (matches) { - /* Remove matches */ - char *str; - int result_len = response->len; - - str = g_regex_replace_eval (handler->regex, response->str, response->len, 0, 0, - remove_eval_cb, &result_len, NULL); - - g_string_truncate (response, 0); - g_string_append_len (response, str, result_len); - g_free (str); - } - } -} - static gboolean parse_response (MMSerialPort *self, - GString *response, + GByteArray *response, GError **error) { - MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); + if (MM_SERIAL_PORT_GET_CLASS (self)->parse_unsolicited) + MM_SERIAL_PORT_GET_CLASS (self)->parse_unsolicited (self, response); - g_return_val_if_fail (priv->response_parser_fn != NULL, FALSE); - - parse_unsolicited_messages (self, response); - - return priv->response_parser_fn (priv->response_parser_user_data, response, error); + g_return_val_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->parse_response, FALSE); + return MM_SERIAL_PORT_GET_CLASS (self)->parse_response (self, response, error); } static gboolean @@ -715,13 +612,15 @@ data_available (GIOChannel *source, GIOStatus status; if (condition & G_IO_HUP) { - g_string_truncate (priv->response, 0); + if (priv->response->len) + g_byte_array_remove_range (priv->response, 0, priv->response->len); mm_serial_port_close (self); return FALSE; } if (condition & G_IO_ERR) { - g_string_truncate (priv->response, 0); + if (priv->response->len) + g_byte_array_remove_range (priv->response, 0, priv->response->len); return TRUE; } @@ -745,14 +644,14 @@ data_available (GIOChannel *source, if (bytes_read > 0) { serial_debug (self, "<--", buf, bytes_read); - g_string_append_len (priv->response, buf, bytes_read); + g_byte_array_append (priv->response, (const guint8 *) buf, bytes_read); } - /* Make sure the string doesn't grow too long */ + /* Make sure the response doesn't grow too long */ if (priv->response->len > SERIAL_BUF_SIZE) { /* Notify listeners and then trim the buffer */ g_signal_emit_by_name (self, "buffer-full", priv->response); - g_string_erase (priv->response, 0, (SERIAL_BUF_SIZE / 2)); + g_byte_array_remove_range (priv->response, 0, (SERIAL_BUF_SIZE / 2)); } if (parse_response (self, priv->response, &err)) @@ -843,7 +742,8 @@ mm_serial_port_open (MMSerialPort *self, GError **error) return FALSE; } - if (!config_fd (self, error)) { + g_warn_if_fail (MM_SERIAL_PORT_GET_CLASS (self)->config_fd); + if (!MM_SERIAL_PORT_GET_CLASS (self)->config_fd (self, priv->fd, error)) { close (priv->fd); priv->fd = -1; return FALSE; @@ -875,6 +775,7 @@ void mm_serial_port_close (MMSerialPort *self) { MMSerialPortPrivate *priv; + int i; g_return_if_fail (MM_IS_SERIAL_PORT (self)); @@ -907,14 +808,24 @@ mm_serial_port_close (MMSerialPort *self) close (priv->fd); priv->fd = -1; } + + /* Clear the command queue */ + for (i = 0; i < g_queue_get_length (priv->queue); i++) { + MMQueueData *item = g_queue_peek_nth (priv->queue, i); + + g_byte_array_free (item->command, TRUE); + g_slice_free (MMQueueData, item); + } + g_queue_clear (priv->queue); } static void internal_queue_command (MMSerialPort *self, - const char *command, + GByteArray *command, + gboolean take_command, gboolean cached, guint32 timeout_seconds, - MMSerialResponseFn callback, + GCallback callback, gpointer user_data) { MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); @@ -924,7 +835,12 @@ internal_queue_command (MMSerialPort *self, g_return_if_fail (command != NULL); info = g_slice_new0 (MMQueueData); - info->command = g_strdup (command); + if (take_command) + info->command = command; + else { + info->command = g_byte_array_sized_new (command->len); + g_byte_array_append (info->command, command->data, command->len); + } info->cached = cached; info->timeout = timeout_seconds; info->callback = callback; @@ -932,7 +848,7 @@ internal_queue_command (MMSerialPort *self, /* Clear the cached value for this command if not asking for cached value */ if (!cached) - mm_serial_port_set_cached_reply (self, command, NULL); + mm_serial_port_set_cached_reply (self, info->command, NULL); g_queue_push_tail (priv->queue, info); @@ -942,22 +858,24 @@ internal_queue_command (MMSerialPort *self, void mm_serial_port_queue_command (MMSerialPort *self, - const char *command, + GByteArray *command, + gboolean take_command, guint32 timeout_seconds, - MMSerialResponseFn callback, + GCallback callback, gpointer user_data) { - internal_queue_command (self, command, FALSE, timeout_seconds, callback, user_data); + internal_queue_command (self, command, take_command, FALSE, timeout_seconds, callback, user_data); } void mm_serial_port_queue_command_cached (MMSerialPort *self, - const char *command, + GByteArray *command, + gboolean take_command, guint32 timeout_seconds, - MMSerialResponseFn callback, + GCallback callback, gpointer user_data) { - internal_queue_command (self, command, TRUE, timeout_seconds, callback, user_data); + internal_queue_command (self, command, take_command, TRUE, timeout_seconds, callback, user_data); } typedef struct { @@ -1133,12 +1051,54 @@ mm_serial_port_new (const char *name, MMPortType ptype) NULL)); } +static gboolean +ba_equal (gconstpointer v1, gconstpointer v2) +{ + const GByteArray *a = v1; + const GByteArray *b = v2; + + if (!a && b) + return -1; + else if (a && !b) + return 1; + else if (!a && !b) + return 0; + + g_assert (a && b); + if (a->len < b->len) + return -1; + else if (a->len > b->len) + return 1; + + g_assert (a->len == b->len); + return !memcmp (a->data, b->data, a->len); +} + +static guint +ba_hash (gconstpointer v) +{ + /* 31 bit hash function */ + const GByteArray *array = v; + guint32 i, h = (const signed char) array->data[0]; + + for (i = 1; i < array->len; i++) + h = (h << 5) - h + (const signed char) array->data[i]; + + return h; +} + +static void +ba_free (gpointer v) +{ + g_byte_array_free ((GByteArray *) v, TRUE); +} + static void mm_serial_port_init (MMSerialPort *self) { MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); - priv->reply_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + priv->reply_cache = g_hash_table_new_full (ba_hash, ba_equal, ba_free, ba_free); priv->fd = -1; priv->baud = 57600; @@ -1148,8 +1108,7 @@ mm_serial_port_init (MMSerialPort *self) priv->send_delay = 1000; priv->queue = g_queue_new (); - priv->command = g_string_new_len ("AT", SERIAL_BUF_SIZE); - priv->response = g_string_sized_new (SERIAL_BUF_SIZE); + priv->response = g_byte_array_sized_new (500); } static void @@ -1223,24 +1182,8 @@ finalize (GObject *object) MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); g_hash_table_destroy (priv->reply_cache); + g_byte_array_free (priv->response, TRUE); g_queue_free (priv->queue); - g_string_free (priv->command, TRUE); - g_string_free (priv->response, TRUE); - - while (priv->unsolicited_msg_handlers) { - MMUnsolicitedMsgHandler *handler = (MMUnsolicitedMsgHandler *) priv->unsolicited_msg_handlers->data; - - if (handler->notify) - handler->notify (handler->user_data); - - g_regex_unref (handler->regex); - g_slice_free (MMUnsolicitedMsgHandler, handler); - priv->unsolicited_msg_handlers = g_slist_delete_link (priv->unsolicited_msg_handlers, - priv->unsolicited_msg_handlers); - } - - if (priv->response_parser_notify) - priv->response_parser_notify (priv->response_parser_user_data); G_OBJECT_CLASS (mm_serial_port_parent_class)->finalize (object); } @@ -1258,6 +1201,8 @@ mm_serial_port_class_init (MMSerialPortClass *klass) object_class->dispose = dispose; object_class->finalize = finalize; + klass->config_fd = real_config_fd; + /* Properties */ g_object_class_install_property (object_class, PROP_BAUD, diff --git a/src/mm-serial-port.h b/src/mm-serial-port.h index dd5a6689..a8ee8bee 100644 --- a/src/mm-serial-port.h +++ b/src/mm-serial-port.h @@ -39,19 +39,6 @@ typedef struct _MMSerialPort MMSerialPort; typedef struct _MMSerialPortClass MMSerialPortClass; -typedef gboolean (*MMSerialResponseParserFn) (gpointer user_data, - GString *response, - GError **error); - -typedef void (*MMSerialUnsolicitedMsgFn) (MMSerialPort *port, - GMatchInfo *match_info, - gpointer user_data); - -typedef void (*MMSerialResponseFn) (MMSerialPort *port, - GString *response, - GError *error, - gpointer user_data); - typedef void (*MMSerialFlashFn) (MMSerialPort *port, GError *error, gpointer user_data); @@ -63,48 +50,71 @@ struct _MMSerialPort { struct _MMSerialPortClass { MMPortClass parent; + /* Called for subclasses to parse unsolicited responses. If any recognized + * unsolicited response is found, it should be removed from the 'response' + * byte array before returning. + */ + void (*parse_unsolicited) (MMSerialPort *self, GByteArray *response); + + /* Called to parse the device's response to a command or determine if the + * response was an error response. If the response indicates an error, an + * appropriate error should be returned in the 'error' argument. The + * function should return FALSE if there is not enough data yet to determine + * the device's reply (whether success *or* error), and should return TRUE + * when the device's response has been recognized and parsed. + */ + gboolean (*parse_response) (MMSerialPort *self, + GByteArray *response, + GError **error); + + /* Called after parsing to allow the command response to be delivered to + * it's callback to be handled. + */ + void (*handle_response) (MMSerialPort *self, + GByteArray *response, + GError *error, + GCallback callback, + gpointer callback_data); + + /* Called to configure the serial port after it's opened. On error, should + * return FALSE and set 'error' as appropriate. + */ + gboolean (*config_fd) (MMSerialPort *self, int fd, GError **error); + /* Signals */ - void (*buffer_full) (MMSerialPort *port, const GString *buffer); + void (*buffer_full) (MMSerialPort *port, const GByteArray *buffer); }; GType mm_serial_port_get_type (void); MMSerialPort *mm_serial_port_new (const char *name, MMPortType ptype); -void mm_serial_port_add_unsolicited_msg_handler (MMSerialPort *self, - GRegex *regex, - MMSerialUnsolicitedMsgFn callback, - gpointer user_data, - GDestroyNotify notify); - -void mm_serial_port_set_response_parser (MMSerialPort *self, - MMSerialResponseParserFn fn, - gpointer user_data, - GDestroyNotify notify); - gboolean mm_serial_port_is_open (MMSerialPort *self); gboolean mm_serial_port_open (MMSerialPort *self, GError **error); void mm_serial_port_close (MMSerialPort *self); + +gboolean mm_serial_port_flash (MMSerialPort *self, + guint32 flash_time, + MMSerialFlashFn callback, + gpointer user_data); +void mm_serial_port_flash_cancel (MMSerialPort *self); + void mm_serial_port_queue_command (MMSerialPort *self, - const char *command, + GByteArray *command, + gboolean take_command, guint32 timeout_seconds, - MMSerialResponseFn callback, + GCallback callback, gpointer user_data); void mm_serial_port_queue_command_cached (MMSerialPort *self, - const char *command, + GByteArray *command, + gboolean take_command, guint32 timeout_seconds, - MMSerialResponseFn callback, + GCallback callback, gpointer user_data); -gboolean mm_serial_port_flash (MMSerialPort *self, - guint32 flash_time, - MMSerialFlashFn callback, - gpointer user_data); -void mm_serial_port_flash_cancel (MMSerialPort *self); - #endif /* MM_SERIAL_PORT_H */ |