mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-01 18:50:12 +01:00
modem: add support for Sony Ericsson F3507g / Dell 5530 (bgo #574014)
These devices also need AT+CGREG, they have problems reporting PIN status correctly the first time, and are schizophrenic about which init strings are acceptable. Since they provide so many serial ports, filter out ones we don't care about, and ignore the cdc-ether device that we dont use yet.
This commit is contained in:
parent
8be5ada959
commit
73e39bc499
2 changed files with 139 additions and 18 deletions
|
|
@ -50,6 +50,8 @@ typedef struct {
|
|||
|
||||
guint reg_tries;
|
||||
guint init_tries;
|
||||
gboolean init_ok;
|
||||
guint pin_tries;
|
||||
|
||||
gboolean needs_cgreg;
|
||||
gboolean checked_cgmm;
|
||||
|
|
@ -84,7 +86,9 @@ const gchar *modem_init_sequences[] = {
|
|||
static void enter_pin (NMGsmDevice *device, NMGsmSecret secret_type, gboolean retry);
|
||||
static void manual_registration (NMGsmDevice *device);
|
||||
static void automatic_registration (NMGsmDevice *device);
|
||||
static void init_modem_full (NMGsmDevice *device);
|
||||
static void init_modem (NMSerialDevice *device);
|
||||
static void check_pin (NMGsmDevice *self);
|
||||
|
||||
NMGsmDevice *
|
||||
nm_gsm_device_new (const char *udi,
|
||||
|
|
@ -381,6 +385,7 @@ automatic_registration_response (NMSerialDevice *device,
|
|||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
switch (reply_index) {
|
||||
case 4:
|
||||
case 0:
|
||||
/* Try autoregistration a few times here because the card is actually
|
||||
* responding to the query and thus we aren't waiting as long for
|
||||
|
|
@ -412,7 +417,7 @@ automatic_registration_response (NMSerialDevice *device,
|
|||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
nm_info ("Registered on Roaming network");
|
||||
automatic_registration_get_network (NM_GSM_DEVICE (device));
|
||||
break;
|
||||
|
|
@ -444,8 +449,8 @@ static void
|
|||
automatic_registration (NMGsmDevice *device)
|
||||
{
|
||||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
|
||||
const char *creg_responses[] = { "+CREG: 0,0", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,5", NULL };
|
||||
const char *cgreg_responses[] = { "+CGREG: 0,0", "+CGREG: 0,1", "+CGREG: 0,2", "+CGREG: 0,3", "+CGREG: 0,5", NULL };
|
||||
const char *creg_responses[] = { "+CREG: 0,0", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,4", "+CREG: 0,5", NULL };
|
||||
const char *cgreg_responses[] = { "+CGREG: 0,0", "+CGREG: 0,1", "+CGREG: 0,2", "+CGREG: 0,3", "+CGREG: 0,4", "+CGREG: 0,5", NULL };
|
||||
const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
|
||||
|
||||
if (priv->needs_cgreg)
|
||||
|
|
@ -480,7 +485,8 @@ get_model_done (NMSerialDevice *device,
|
|||
priv->checked_cgmm = TRUE;
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
case 0: /* Huawei E160G */
|
||||
case 1: /* Ericsson F3507g */
|
||||
priv->needs_cgreg = TRUE;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -498,7 +504,7 @@ power_up_response (NMSerialDevice *device,
|
|||
{
|
||||
NMGsmDevice *self = NM_GSM_DEVICE (device);
|
||||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (self);
|
||||
const char *responses[] = { "E160G", NULL };
|
||||
const char *responses[] = { "E160G", "F3507g", "D5530", NULL };
|
||||
const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
|
||||
|
||||
/* Get the model the first time */
|
||||
|
|
@ -523,8 +529,12 @@ init_full_done (NMSerialDevice *device,
|
|||
const char *reply,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMGsmDevice *self = NM_GSM_DEVICE (device);
|
||||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
priv->init_ok = TRUE;
|
||||
power_up (NM_GSM_DEVICE (device));
|
||||
break;
|
||||
case -1:
|
||||
|
|
@ -534,10 +544,29 @@ init_full_done (NMSerialDevice *device,
|
|||
NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
|
||||
break;
|
||||
default:
|
||||
nm_warning ("Modem second stage initialization failed");
|
||||
nm_device_state_changed (NM_DEVICE (device),
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
|
||||
if (priv->init_ok) {
|
||||
/* If the successful init string from before PIN checking failed for
|
||||
* some reason, try all the init strings again.
|
||||
*/
|
||||
priv->init_ok = FALSE;
|
||||
|
||||
/* But don't try the first init string twice if it was previously
|
||||
* successful, but has now failed for some reason.
|
||||
*/
|
||||
priv->init_tries = (priv->init_tries > 0) ? 0 : 1;
|
||||
} else
|
||||
priv->init_tries++;
|
||||
|
||||
if (modem_init_sequences[priv->init_tries] != NULL) {
|
||||
nm_warning ("Trying alternate modem initialization (%d)",
|
||||
priv->init_tries);
|
||||
init_modem_full (self);
|
||||
} else {
|
||||
nm_warning ("Modem second stage initialization failed");
|
||||
nm_device_state_changed (NM_DEVICE (device),
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -548,9 +577,9 @@ init_modem_full (NMGsmDevice *device)
|
|||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
|
||||
const char *responses[] = { "OK", "ERROR", "ERR", NULL };
|
||||
|
||||
/* Send E0 too because some devices turn echo back on after CPIN which
|
||||
* just breaks stuff since echo-ed commands are interpreted as replies.
|
||||
* rh #456770
|
||||
/* Make sure that E0 gets sent here again, because some devices turn echo
|
||||
* back on after CPIN which just breaks stuff since echo-ed commands are
|
||||
* interpreted as replies. (rh #456770)
|
||||
*/
|
||||
modem_wait_for_reply (device, modem_init_sequences[priv->init_tries], 10, responses, responses, init_full_done, NULL);
|
||||
}
|
||||
|
|
@ -647,22 +676,58 @@ enter_pin (NMGsmDevice *device, NMGsmSecret secret_type, gboolean retry)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_pin_again (gpointer data)
|
||||
{
|
||||
check_pin (NM_GSM_DEVICE (data));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
schedule_check_pin_again (NMGsmDevice *self)
|
||||
{
|
||||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->pending_id)
|
||||
g_source_remove (priv->pending_id);
|
||||
|
||||
priv->pending_id = g_timeout_add_seconds (1, check_pin_again, self);
|
||||
}
|
||||
|
||||
static void
|
||||
check_pin_done (NMSerialDevice *device,
|
||||
int reply_index,
|
||||
const char *reply,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
priv->pin_tries = 0;
|
||||
init_modem_full (NM_GSM_DEVICE (device));
|
||||
break;
|
||||
case 1:
|
||||
priv->pin_tries = 0;
|
||||
enter_pin (NM_GSM_DEVICE (device), NM_GSM_SECRET_PIN, FALSE);
|
||||
break;
|
||||
case 2:
|
||||
priv->pin_tries = 0;
|
||||
enter_pin (NM_GSM_DEVICE (device), NM_GSM_SECRET_PUK, FALSE);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
/* Try the pin a few times; sometimes the error is transient */
|
||||
if (priv->pin_tries++ < 4) {
|
||||
schedule_check_pin_again (NM_GSM_DEVICE (device));
|
||||
} else {
|
||||
priv->pin_tries = 0;
|
||||
nm_warning ("PIN checking failed to many times");
|
||||
nm_device_state_changed (NM_DEVICE (device),
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED);
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
nm_warning ("PIN checking timed out");
|
||||
nm_device_state_changed (NM_DEVICE (device),
|
||||
|
|
@ -697,6 +762,7 @@ init_done (NMSerialDevice *device,
|
|||
|
||||
switch (reply_index) {
|
||||
case 0:
|
||||
priv->init_ok = TRUE;
|
||||
check_pin (NM_GSM_DEVICE (device));
|
||||
break;
|
||||
case -1:
|
||||
|
|
@ -746,6 +812,9 @@ real_act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason)
|
|||
}
|
||||
|
||||
NM_GSM_DEVICE_GET_PRIVATE (device)->init_tries = 0;
|
||||
NM_GSM_DEVICE_GET_PRIVATE (device)->init_ok = FALSE;
|
||||
NM_GSM_DEVICE_GET_PRIVATE (device)->pin_tries = 0;
|
||||
NM_GSM_DEVICE_GET_PRIVATE (device)->reg_tries = 0;
|
||||
|
||||
id = nm_serial_device_flash (serial_device, 100, (NMSerialFlashFn) init_modem, NULL);
|
||||
if (!id)
|
||||
|
|
|
|||
|
|
@ -130,6 +130,30 @@ nm_get_device_driver_name (LibHalContext *ctx, const char *origdev_udi)
|
|||
return driver_name;
|
||||
}
|
||||
|
||||
/* Returns the parent if the device is a Sony Ericsson 'mbm'-style device */
|
||||
static char *
|
||||
is_mbm (LibHalContext *ctx, const char *udi)
|
||||
{
|
||||
guint32 vendor_id = 0, product_id = 0;
|
||||
char *parent;
|
||||
|
||||
parent = libhal_device_get_property_string (ctx, udi, "info.parent", NULL);
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
vendor_id = libhal_device_get_property_int (ctx, parent, "usb.vendor_id", NULL);
|
||||
product_id = libhal_device_get_property_int (ctx, parent, "usb.product_id", NULL);
|
||||
|
||||
if ( (vendor_id == 0x0bdb && product_id == 0x1900) /* SE F3507g */
|
||||
|| (vendor_id == 0x0bdb && product_id == 0x1902) /* SE F3507g */
|
||||
|| (vendor_id == 0x0fce && product_id == 0xd0cf) /* SE MD300 */
|
||||
|| (vendor_id == 0x413c && product_id == 0x8147)) /* Dell 5530 HSDPA */
|
||||
return parent;
|
||||
|
||||
libhal_free_string (parent);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Wired device creator */
|
||||
|
||||
static gboolean
|
||||
|
|
@ -159,9 +183,9 @@ wired_device_creator (NMHalManager *self,
|
|||
gboolean managed)
|
||||
{
|
||||
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
|
||||
GObject *device;
|
||||
char *iface;
|
||||
char *driver;
|
||||
GObject *device = NULL;
|
||||
char *iface, *driver, *parent;
|
||||
gboolean mbm = FALSE;
|
||||
|
||||
iface = libhal_device_get_property_string (priv->hal_ctx, udi, "net.interface", NULL);
|
||||
if (!iface) {
|
||||
|
|
@ -170,11 +194,21 @@ wired_device_creator (NMHalManager *self,
|
|||
}
|
||||
|
||||
driver = nm_get_device_driver_name (priv->hal_ctx, origdev_udi);
|
||||
device = (GObject *) nm_device_ethernet_new (udi, iface, driver, managed);
|
||||
|
||||
/* Special handling of Ericsson F3507g 'mbm' devices; ignore the
|
||||
* cdc-ether device that it provides since we don't use it yet.
|
||||
*/
|
||||
if (!strcmp (driver, "cdc_ether")) {
|
||||
parent = is_mbm (priv->hal_ctx, udi);
|
||||
mbm = !!parent;
|
||||
libhal_free_string (parent);
|
||||
}
|
||||
|
||||
if (!mbm)
|
||||
device = (GObject *) nm_device_ethernet_new (udi, iface, driver, managed);
|
||||
|
||||
libhal_free_string (iface);
|
||||
g_free (driver);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
|
@ -614,7 +648,25 @@ modem_device_creator (NMHalManager *self,
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
g_free (parent);
|
||||
libhal_free_string (parent);
|
||||
}
|
||||
|
||||
/* Special handling of Ericsson F3507g 'mbm' devices; already handled by
|
||||
* ModemManager more correctly in HEAD.
|
||||
*/
|
||||
if (type_gsm && !strcmp (driver, "cdc_acm")) {
|
||||
char *parent;
|
||||
guint32 usb_interface;
|
||||
|
||||
parent = is_mbm (priv->hal_ctx, udi);
|
||||
if (parent) {
|
||||
usb_interface = libhal_device_get_property_int (priv->hal_ctx, parent, "usb.interface.number", NULL);
|
||||
if (usb_interface != 1) {
|
||||
libhal_free_string (parent);
|
||||
goto out;
|
||||
}
|
||||
libhal_free_string (parent);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_gsm) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue