When initializing a Huawei device, send the AT&F0 command to restore the
default AT settings on device restart.
Huawei stores all APN settings, which can cause issues when changing the
APN. The AT&F0 command makes sure the device starts from a clean state.
After unplugging a Huawei USB dongle, the 'atoms' in oFono are removed
via 'flush_atoms'. Every atom has a destruct function pointer, used as
destructor. This includes the gprs_context atom that is currently
active.
The function calls are:
flush_atoms -> destruct -> gprs_context_remove ->
at_gprs_context_remove -> modem_disconnect
Because the device is physically removed, the IO channel for the AT
port is gone. In 'at_gprs_context_remove', there is an attempt to
resume communication over that AT port, but that is not possible. This
is detected, and 'io_disconnect' (pointer to 'modem_disconnect') is
called. 'modem_disconnect' has the same atom and tries to remove it
again, so it calls the same destructor. This continues infinitely.
This patch moves the GPRS context removal so that it only happens if the
modem port could be re-opened successfully. If the port cannot be
re-opened (in the case of modem removal), the atom is already in the
process of being removed by the process kicked off in flush_atoms.
This fix is limited to Huawei devices and has been tested using the
following devices:
- E3531i-2
- E3372
- E3531s-2
- E369
- E1552
On E3372 after a GPRS disconnection, modem AT channel (used by PPP) gets
disconnected (G_IO_HUP and G_IO_ERR are detected in received_data
in gatio.c).
After that all connection attempts fail because we are not able to send
any AT commands on modem channel (it is closed).
With this patch, when this behavior is detected, we close gprs context
driver, reopen AT channel and gprs context driver.
The Huawei CDMA modems only support CFUN=5 for offline mode and so
enforce this one if CDMA support has been detected. Even if the modem
would indicate AT^RFSWITCH support.
Using AT+CFUN=7 (if supported) to switch into offline mode has a problem
with older modems. Sending AT+CFUN=7 with a data connection active has
the problem that it never terminates with OK or ERROR.
Devices that support AT^RFSWITCH are known to handle this properly. So
only when that command is supported, use AT+CFUN=7 for offline mode. If
it is not supported, then keep using AT+CFUN=5 to switch the device into
offline mode.
When switching from offline into online mode, the SIM card access
gets temporarily disabled by the modem firmware. To work around
this limitation poll the SIM card state.
huawei_disconnect is used to recovery the io and gprs context when
io error happends, see commit 39382730d7
However, io error not only happends at PPP disconnect, in theory it
can happends at any situation. I also observed that it happens when modem
go into offline mode at my Huawei EM770W modem. in this case, gprs should
not be reopened.
Sim state is already known after modem is enabled and there's no need to
query it again. Before this patch, query_sim_state() was called upon
huawei_enable() and huawei_pre_sim(). Both functions might call
notify_sim_state() with a valid state. Hence we could eventually end up
sending AT+CFUN=5 command twice.
If a "^SYSINFO" arrives after the timer for query_sim_locked() has been
set up, it'd would set a new timer, signaling a sim state change more
than once.