base-modem: ported all port grabbing/releasing logic to the base object
This commit is contained in:
@@ -52,6 +52,10 @@ struct _MMBaseModemPrivate {
|
|||||||
MMAuthProvider *authp;
|
MMAuthProvider *authp;
|
||||||
|
|
||||||
GHashTable *ports;
|
GHashTable *ports;
|
||||||
|
MMAtSerialPort *primary;
|
||||||
|
MMAtSerialPort *secondary;
|
||||||
|
MMQcdmSerialPort *qcdm;
|
||||||
|
MMPort *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
@@ -85,6 +89,14 @@ mm_base_modem_get_port (MMBaseModem *self,
|
|||||||
return port;
|
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
|
static gboolean
|
||||||
set_invalid_unresponsive_modem_cb (MMBaseModem *self)
|
set_invalid_unresponsive_modem_cb (MMBaseModem *self)
|
||||||
{
|
{
|
||||||
@@ -102,11 +114,11 @@ serial_port_timed_out_cb (MMSerialPort *port,
|
|||||||
|
|
||||||
if (self->priv->max_timeouts > 0 &&
|
if (self->priv->max_timeouts > 0 &&
|
||||||
n_consecutive_timeouts >= self->priv->max_timeouts) {
|
n_consecutive_timeouts >= self->priv->max_timeouts) {
|
||||||
mm_warn ("Modem %s: Port (%s/%s) timed out %u times, marking modem as disabled",
|
mm_warn ("(%s/%s) port timed out %u times, marking modem '%s' as disabled",
|
||||||
g_dbus_object_get_object_path (G_DBUS_OBJECT (self)),
|
|
||||||
mm_port_type_to_name (mm_port_get_port_type (MM_PORT (port))),
|
mm_port_type_to_name (mm_port_get_port_type (MM_PORT (port))),
|
||||||
mm_port_get_device (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 */
|
/* Only set action to invalidate modem if not already done */
|
||||||
if (!self->priv->set_invalid_unresponsive_modem_id)
|
if (!self->priv->set_invalid_unresponsive_modem_id)
|
||||||
@@ -115,60 +127,138 @@ serial_port_timed_out_cb (MMSerialPort *port,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
gboolean
|
||||||
find_primary (gpointer key, gpointer data, gpointer user_data)
|
mm_base_modem_grab_port (MMBaseModem *self,
|
||||||
{
|
|
||||||
MMPort **found = user_data;
|
|
||||||
MMPort *port = MM_PORT (data);
|
|
||||||
|
|
||||||
if (!*found && (mm_port_get_port_type (port) == MM_PORT_TYPE_PRIMARY))
|
|
||||||
*found = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
MMPort *
|
|
||||||
mm_base_modem_add_port (MMBaseModem *self,
|
|
||||||
const gchar *subsys,
|
const gchar *subsys,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
MMPortType ptype)
|
MMPortType suggested_type)
|
||||||
{
|
{
|
||||||
MMPort *port = NULL;
|
MMPort *port;
|
||||||
gchar *key, *device;
|
gchar *key;
|
||||||
|
|
||||||
g_return_val_if_fail (MM_IS_BASE_MODEM (self), NULL);
|
g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE);
|
||||||
g_return_val_if_fail (subsys != NULL, NULL);
|
g_return_val_if_fail (subsys != NULL, FALSE);
|
||||||
g_return_val_if_fail (name != NULL, NULL);
|
g_return_val_if_fail (name != NULL, FALSE);
|
||||||
g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL);
|
|
||||||
|
|
||||||
/* Only 'net' or 'tty' should be given */
|
/* Only allow 'tty' and 'net' ports */
|
||||||
g_return_val_if_fail (g_str_equal (subsys, "net") ||
|
if (!g_str_equal (subsys, "net") &&
|
||||||
g_str_equal (subsys, "tty"),
|
!g_str_equal (subsys, "tty")) {
|
||||||
NULL);
|
mm_warn ("(%s/%s): cannot add port, unhandled subsystem",
|
||||||
|
subsys, name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
key = get_hash_key (subsys, name);
|
||||||
port = g_hash_table_lookup (self->priv->ports, key);
|
port = g_hash_table_lookup (self->priv->ports, key);
|
||||||
|
|
||||||
if (port) {
|
if (port) {
|
||||||
mm_warn ("cannot add port (%s/%s): already exists",
|
mm_warn ("(%s/%s): cannot add port, already exists",
|
||||||
subsys, name);
|
subsys, name);
|
||||||
g_free (key);
|
g_free (key);
|
||||||
return NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 (ptype == MM_PORT_TYPE_QCDM) {
|
||||||
|
/* QCDM port */
|
||||||
|
port = MM_PORT (mm_qcdm_serial_port_new (name, ptype));
|
||||||
|
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) {
|
if (ptype == MM_PORT_TYPE_PRIMARY) {
|
||||||
g_hash_table_foreach (self->priv->ports, find_primary, &port);
|
self->priv->primary = g_object_ref (port);
|
||||||
if (port) {
|
|
||||||
mm_warn ("cannot add port (%s/%s): primary port already exists",
|
|
||||||
subsys, name);
|
|
||||||
g_free (key);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_str_equal (subsys, "tty")) {
|
/* Primary port, which will also be data port */
|
||||||
if (ptype == MM_PORT_TYPE_QCDM)
|
if (!self->priv->data)
|
||||||
port = MM_PORT (mm_qcdm_serial_port_new (name, ptype));
|
self->priv->data = g_object_ref (port);
|
||||||
else
|
|
||||||
port = MM_PORT (mm_at_serial_port_new (name, ptype));
|
/* 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 */
|
/* For serial ports, enable port timeout checks */
|
||||||
if (port)
|
if (port)
|
||||||
@@ -176,57 +266,97 @@ mm_base_modem_add_port (MMBaseModem *self,
|
|||||||
"timed-out",
|
"timed-out",
|
||||||
G_CALLBACK (serial_port_timed_out_cb),
|
G_CALLBACK (serial_port_timed_out_cb),
|
||||||
self);
|
self);
|
||||||
} else if (!strcmp (subsys, "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,
|
|
||||||
NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
device = mm_modem_get_device (MM_MODEM (self));
|
mm_dbg ("(%s/%s) port (%s) grabbed by %s",
|
||||||
mm_dbg ("(%s/%s) type %s claimed by %s",
|
|
||||||
subsys,
|
subsys,
|
||||||
name,
|
name,
|
||||||
mm_port_type_to_name (ptype),
|
mm_port_type_to_name (ptype),
|
||||||
device);
|
mm_port_get_device (port));
|
||||||
g_free (device);
|
} 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, MM_PORT_TYPE_IGNORED,
|
||||||
|
NULL));
|
||||||
|
|
||||||
g_hash_table_insert (self->priv->ports, key, port);
|
/* 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);
|
||||||
|
|
||||||
return port;
|
/* TODO: */
|
||||||
|
/* g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); */
|
||||||
|
/* check_valid (self); */
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
mm_dbg ("(%s/%s) port grabbed by %s",
|
||||||
mm_base_modem_remove_port (MMBaseModem *self, MMPort *port)
|
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 TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mm_base_modem_release_port (MMBaseModem *self,
|
||||||
|
const gchar *subsys,
|
||||||
|
const gchar *name)
|
||||||
{
|
{
|
||||||
gchar *device, *key, *name;
|
const gchar *type_name;
|
||||||
const gchar *type_name, *subsys;
|
const gchar *device;
|
||||||
gboolean removed;
|
gchar *key;
|
||||||
|
MMPort *port;
|
||||||
|
|
||||||
g_return_val_if_fail (MM_IS_BASE_MODEM (self), FALSE);
|
g_return_if_fail (MM_IS_BASE_MODEM (self));
|
||||||
g_return_val_if_fail (MM_IS_PORT (port), FALSE);
|
g_return_if_fail (name != NULL);
|
||||||
|
g_return_if_fail (subsys != NULL);
|
||||||
|
|
||||||
name = g_strdup (mm_port_get_device (port));
|
if (!g_str_equal (subsys, "tty") &&
|
||||||
subsys = mm_port_subsys_to_name (mm_port_get_subsys (port));
|
!g_str_equal (subsys, "net"))
|
||||||
type_name = mm_port_type_to_name (mm_port_get_port_type (port));
|
return;
|
||||||
|
|
||||||
key = get_hash_key (subsys, name);
|
key = get_hash_key (subsys, name);
|
||||||
removed = g_hash_table_remove (self->priv->ports, key);
|
|
||||||
if (removed) {
|
/* Find the port */
|
||||||
/* Port may have already been destroyed by removal from the hash */
|
port = g_hash_table_lookup (self->priv->ports, key);
|
||||||
device = mm_modem_get_device (MM_MODEM (self));
|
if (!port) {
|
||||||
mm_dbg ("(%s/%s) type %s removed from %s",
|
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,
|
subsys,
|
||||||
name,
|
name,
|
||||||
type_name,
|
type_name,
|
||||||
device);
|
device);
|
||||||
g_free (device);
|
g_hash_table_remove (self->priv->ports, key);
|
||||||
}
|
|
||||||
g_free (key);
|
g_free (key);
|
||||||
g_free (name);
|
|
||||||
|
|
||||||
return removed;
|
/* TODO */
|
||||||
|
/* check_valid (MM_GENERIC_GSM (modem)); */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -237,15 +367,6 @@ mm_base_modem_set_valid (MMBaseModem *self,
|
|||||||
|
|
||||||
if (self->priv->valid != new_valid) {
|
if (self->priv->valid != new_valid) {
|
||||||
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]);
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VALID]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,6 +492,11 @@ dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
MMBaseModem *self = MM_BASE_MODEM (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) {
|
if (self->priv->ports) {
|
||||||
g_hash_table_destroy (self->priv->ports);
|
g_hash_table_destroy (self->priv->ports);
|
||||||
self->priv->ports = NULL;
|
self->priv->ports = NULL;
|
||||||
|
@@ -52,16 +52,20 @@ struct _MMBaseModemClass {
|
|||||||
|
|
||||||
GType mm_base_modem_get_type (void);
|
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,
|
MMPort *mm_base_modem_get_port (MMBaseModem *self,
|
||||||
const gchar *subsys,
|
const gchar *subsys,
|
||||||
const gchar *name);
|
const gchar *name);
|
||||||
MMPort *mm_base_modem_add_port (MMBaseModem *self,
|
gboolean mm_base_modem_owns_port (MMBaseModem *self,
|
||||||
const gchar *subsys,
|
const gchar *subsys,
|
||||||
const gchar *name,
|
const gchar *name);
|
||||||
MMPortType ptype);
|
|
||||||
gboolean mm_base_modem_remove_port (MMBaseModem *self,
|
|
||||||
MMPort *port);
|
|
||||||
|
|
||||||
void mm_base_modem_set_valid (MMBaseModem *self,
|
void mm_base_modem_set_valid (MMBaseModem *self,
|
||||||
gboolean valid);
|
gboolean valid);
|
||||||
|
Reference in New Issue
Block a user