aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2011-11-04 12:43:06 +0100
committerAleksander Morgado <aleksander@lanedo.com>2012-03-15 14:14:22 +0100
commitb6cb5bd6daac1b434a57a34ec2e08121455f3397 (patch)
treee41d07c96ccfd454de7bf5619ac293bebcafebb9 /src
parentf39923c97d33850cc1e70d23b2e8d808cda67fec (diff)
base-modem: ported all port grabbing/releasing logic to the base object
Diffstat (limited to 'src')
-rw-r--r--src/mm-base-modem.c292
-rw-r--r--src/mm-base-modem.h22
2 files changed, 222 insertions, 92 deletions
diff --git a/src/mm-base-modem.c b/src/mm-base-modem.c
index 67f0f190..fbbd1aae 100644
--- a/src/mm-base-modem.c
+++ b/src/mm-base-modem.c
@@ -52,6 +52,10 @@ struct _MMBaseModemPrivate {
MMAuthProvider *authp;
GHashTable *ports;
+ MMAtSerialPort *primary;
+ MMAtSerialPort *secondary;
+ MMQcdmSerialPort *qcdm;
+ MMPort *data;
};
static gchar *
@@ -85,6 +89,14 @@ mm_base_modem_get_port (MMBaseModem *self,
return port;
}
+gboolean
+mm_base_modem_owns_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name)
+{
+ return !!mm_base_modem_get_port (self, subsys, name);
+}
+
static gboolean
set_invalid_unresponsive_modem_cb (MMBaseModem *self)
{
@@ -102,11 +114,11 @@ serial_port_timed_out_cb (MMSerialPort *port,
if (self->priv->max_timeouts > 0 &&
n_consecutive_timeouts >= self->priv->max_timeouts) {
- mm_warn ("Modem %s: Port (%s/%s) timed out %u times, marking modem as disabled",
- g_dbus_object_get_object_path (G_DBUS_OBJECT (self)),
+ mm_warn ("(%s/%s) port timed out %u times, marking modem '%s' as disabled",
mm_port_type_to_name (mm_port_get_port_type (MM_PORT (port))),
mm_port_get_device (MM_PORT (port)),
- n_consecutive_timeouts);
+ n_consecutive_timeouts,
+ g_dbus_object_get_object_path (G_DBUS_OBJECT (self)));
/* Only set action to invalidate modem if not already done */
if (!self->priv->set_invalid_unresponsive_modem_id)
@@ -115,118 +127,236 @@ serial_port_timed_out_cb (MMSerialPort *port,
}
}
-static void
-find_primary (gpointer key, gpointer data, gpointer user_data)
+gboolean
+mm_base_modem_grab_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name,
+ MMPortType suggested_type)
{
- MMPort **found = user_data;
- MMPort *port = MM_PORT (data);
-
- if (!*found && (mm_port_get_port_type (port) == MM_PORT_TYPE_PRIMARY))
- *found = port;
-}
+ MMPort *port;
+ gchar *key;
-MMPort *
-mm_base_modem_add_port (MMBaseModem *self,
- const gchar *subsys,
- const gchar *name,
- MMPortType ptype)
-{
- MMPort *port = NULL;
- gchar *key, *device;
+ g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE);
+ g_return_val_if_fail (subsys != NULL, FALSE);
+ g_return_val_if_fail (name != NULL, FALSE);
- g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL);
- g_return_val_if_fail (subsys != NULL, NULL);
- g_return_val_if_fail (name != NULL, NULL);
- g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL);
+ /* Only allow 'tty' and 'net' ports */
+ if (!g_str_equal (subsys, "net") &&
+ !g_str_equal (subsys, "tty")) {
+ mm_warn ("(%s/%s): cannot add port, unhandled subsystem",
+ subsys, name);
+ return FALSE;
+ }
- /* Only 'net' or 'tty' should be given */
- g_return_val_if_fail (g_str_equal (subsys, "net") ||
- g_str_equal (subsys, "tty"),
- NULL);
+ /* Don't allow more than one Primary port to be set */
+ if (self->priv->primary &&
+ suggested_type == MM_PORT_TYPE_PRIMARY) {
+ mm_warn ("(%s/%s): cannot add port, primary port already exists",
+ subsys, name);
+ return FALSE;
+ }
+ /* Check whether we already have it stored */
key = get_hash_key (subsys, name);
port = g_hash_table_lookup (self->priv->ports, key);
-
if (port) {
- mm_warn ("cannot add port (%s/%s): already exists",
+ mm_warn ("(%s/%s): cannot add port, already exists",
subsys, name);
g_free (key);
- return NULL;
+ return FALSE;
}
- if (ptype == MM_PORT_TYPE_PRIMARY) {
- g_hash_table_foreach (self->priv->ports, find_primary, &port);
- if (port) {
- mm_warn ("cannot add port (%s/%s): primary port already exists",
- subsys, name);
- g_free (key);
- return NULL;
+ /* If we have a tty, decide whether it will be primary, secondary, or none */
+ if (g_str_equal (subsys, "tty")) {
+ MMPortType ptype;
+
+ /* Decide port type */
+ if (suggested_type != MM_PORT_TYPE_UNKNOWN)
+ ptype = suggested_type;
+ else {
+ if (!self->priv->primary)
+ ptype = MM_PORT_TYPE_PRIMARY;
+ else if (!self->priv->secondary)
+ ptype = MM_PORT_TYPE_SECONDARY;
+ else
+ ptype = MM_PORT_TYPE_IGNORED;
}
- }
- if (g_str_equal (subsys, "tty")) {
- if (ptype == MM_PORT_TYPE_QCDM)
+ if (ptype == MM_PORT_TYPE_QCDM) {
+ /* QCDM port */
port = MM_PORT (mm_qcdm_serial_port_new (name, ptype));
- else
+ if (!self->priv->qcdm)
+ self->priv->qcdm = g_object_ref (port);
+ } else {
+ /* AT port */
port = MM_PORT (mm_at_serial_port_new (name, ptype));
+ /* TODO: setup serial port response parser and unsolicited message handlers */
+
+ /* (CDMA) */
+ /* g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); */
+ /* 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); */
+
+ /* (GSM) */
+ /* { */
+ /* GPtrArray *array; */
+ /* int i; */
+
+ /* 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_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, reg_state_changed, self, NULL); */
+ /* } */
+ /* mm_gsm_creg_regex_destroy (array); */
+
+ /* regex = g_regex_new ("\\r\\n\\+CIEV: (\\d+),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); */
+ /* mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, ciev_received, self, NULL); */
+ /* g_regex_unref (regex); */
+
+ /* regex = g_regex_new ("\\r\\n\\+CMTI: \"(\\S+)\",(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); */
+ /* mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, cmti_received, self, NULL); */
+ /* g_regex_unref (regex); */
+
+ /* regex = g_regex_new ("\\r\\n\\+CUSD:\\s*(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); */
+ /* mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, cusd_received, self, NULL); */
+ /* g_regex_unref (regex); */
+ /* } */
+
+
+ if (ptype == MM_PORT_TYPE_PRIMARY) {
+ self->priv->primary = g_object_ref (port);
+
+ /* Primary port, which will also be data port */
+ if (!self->priv->data)
+ self->priv->data = g_object_ref (port);
+
+ /* TODO: GSM */
+ /* /\* Get the modem's general info *\/ */
+ /* initial_info_check (self); */
+ /* /\* Get modem's IMEI *\/ */
+ /* initial_imei_check (self); */
+ /* /\* Get modem's initial lock/unlock state; this also ensures the */
+ /* * SIM is ready by waiting if necessary for the SIM to initalize. */
+ /* *\/ */
+ /* initial_pin_check (self); */
+
+ /* TODO: CDMA */
+ /* /\* Get the modem's general info *\/ */
+ /* initial_info_check (self); */
+ /* /\* Get modem's ESN number *\/ */
+ /* initial_esn_check (self); */
+
+ } else if (ptype == MM_PORT_TYPE_SECONDARY)
+ self->priv->secondary = g_object_ref (port);
+ }
+
/* For serial ports, enable port timeout checks */
if (port)
g_signal_connect (port,
"timed-out",
G_CALLBACK (serial_port_timed_out_cb),
self);
- } else if (!strcmp (subsys, "net")) {
+
+ mm_dbg ("(%s/%s) port (%s) grabbed by %s",
+ subsys,
+ name,
+ mm_port_type_to_name (ptype),
+ mm_port_get_device (port));
+ } else {
+ /* Net */
port = MM_PORT (g_object_new (MM_TYPE_PORT,
MM_PORT_DEVICE, name,
MM_PORT_SUBSYS, MM_PORT_SUBSYS_NET,
- MM_PORT_TYPE, ptype,
+ MM_PORT_TYPE, MM_PORT_TYPE_IGNORED,
NULL));
- }
- device = mm_modem_get_device (MM_MODEM (self));
- mm_dbg ("(%s/%s) type %s claimed by %s",
- subsys,
- name,
- mm_port_type_to_name (ptype),
- device);
- g_free (device);
+ /* Net device (if any) is the preferred data port */
+ if (!self->priv->data || MM_IS_AT_SERIAL_PORT (self->priv->data)) {
+ g_clear_object (&self->priv->data);
+ self->priv->data = g_object_ref (port);
+
+ /* TODO: */
+ /* g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); */
+ /* check_valid (self); */
+ }
+
+ mm_dbg ("(%s/%s) port grabbed by %s",
+ subsys,
+ name,
+ mm_port_get_device (port));
+ }
+ /* Add it to the tracking HT.
+ * Note: 'key' and 'port' now owned by the HT. */
g_hash_table_insert (self->priv->ports, key, port);
- return port;
+ return TRUE;
}
-gboolean
-mm_base_modem_remove_port (MMBaseModem *self, MMPort *port)
+void
+mm_base_modem_release_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name)
{
- gchar *device, *key, *name;
- const gchar *type_name, *subsys;
- gboolean removed;
+ const gchar *type_name;
+ const gchar *device;
+ gchar *key;
+ MMPort *port;
- g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE);
- g_return_val_if_fail (MM_IS_PORT (port), FALSE);
+ g_return_if_fail (MM_IS_BASE_MODEM (self));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (subsys != NULL);
- name = g_strdup (mm_port_get_device (port));
- subsys = mm_port_subsys_to_name (mm_port_get_subsys (port));
- type_name = mm_port_type_to_name (mm_port_get_port_type (port));
+ if (!g_str_equal (subsys, "tty") &&
+ !g_str_equal (subsys, "net"))
+ return;
key = get_hash_key (subsys, name);
- removed = g_hash_table_remove (self->priv->ports, key);
- if (removed) {
- /* Port may have already been destroyed by removal from the hash */
- device = mm_modem_get_device (MM_MODEM (self));
- mm_dbg ("(%s/%s) type %s removed from %s",
- subsys,
- name,
- type_name,
- device);
- g_free (device);
+
+ /* Find the port */
+ port = g_hash_table_lookup (self->priv->ports, key);
+ if (!port) {
+ mm_warn ("(%s/%s): cannot release port, not found",
+ subsys, name);
+ g_free (key);
+ return;
}
+
+ if (port == (MMPort *)self->priv->primary)
+ g_clear_object (&self->priv->primary);
+
+ if (port == (MMPort *)self->priv->data)
+ g_clear_object (&self->priv->data);
+
+ if (port == (MMPort *)self->priv->secondary)
+ g_clear_object (&self->priv->secondary);
+
+ if (port == (MMPort *)self->priv->qcdm)
+ g_clear_object (&self->priv->qcdm);
+
+ /* Remove it from the tracking HT */
+ type_name = mm_port_type_to_name (mm_port_get_port_type (port));
+ device = mm_port_get_device (port);
+ mm_dbg ("(%s/%s) type %s released from %s",
+ subsys,
+ name,
+ type_name,
+ device);
+ g_hash_table_remove (self->priv->ports, key);
g_free (key);
- g_free (name);
- return removed;
+ /* TODO */
+ /* check_valid (MM_GENERIC_GSM (modem)); */
}
void
@@ -237,15 +367,6 @@ mm_base_modem_set_valid (MMBaseModem *self,
if (self->priv->valid != new_valid) {
self->priv->valid = new_valid;
-
- /* TODO */
- /* /\* Modem starts off in disabled state, and jumps to disabled when */
- /* * it's no longer valid. */
- /* *\/ */
- /* mm_modem_set_state (MM_MODEM (self), */
- /* MM_MODEM_STATE_DISABLED, */
- /* MM_MODEM_STATE_REASON_NONE); */
-
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VALID]);
}
}
@@ -371,6 +492,11 @@ dispose (GObject *object)
{
MMBaseModem *self = MM_BASE_MODEM (object);
+ g_clear_object (&self->priv->primary);
+ g_clear_object (&self->priv->secondary);
+ g_clear_object (&self->priv->data);
+ g_clear_object (&self->priv->qcdm);
+
if (self->priv->ports) {
g_hash_table_destroy (self->priv->ports);
self->priv->ports = NULL;
diff --git a/src/mm-base-modem.h b/src/mm-base-modem.h
index bed222e6..18352968 100644
--- a/src/mm-base-modem.h
+++ b/src/mm-base-modem.h
@@ -52,16 +52,20 @@ struct _MMBaseModemClass {
GType mm_base_modem_get_type (void);
+gboolean mm_base_modem_grab_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name,
+ MMPortType suggested_type);
+void mm_base_modem_release_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name);
+MMPort *mm_base_modem_get_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name);
+gboolean mm_base_modem_owns_port (MMBaseModem *self,
+ const gchar *subsys,
+ const gchar *name);
-MMPort *mm_base_modem_get_port (MMBaseModem *self,
- const gchar *subsys,
- const gchar *name);
-MMPort *mm_base_modem_add_port (MMBaseModem *self,
- const gchar *subsys,
- const gchar *name,
- MMPortType ptype);
-gboolean mm_base_modem_remove_port (MMBaseModem *self,
- MMPort *port);
void mm_base_modem_set_valid (MMBaseModem *self,
gboolean valid);