During init, the N900 appears to ignore an E0 in the same command as
an E1. So just add another init command to disable echo, which won't
have any effect on devices that work with the first command.
If the rules to tag specific USB interface numbers only apply on the PID, we'll
end up seeing that if the port has a parent with another PID, and that other
PID also has a rule, port will get tagged multiple times. Easier to see with an
example:
The ZTE MF637 (VID 0x19D2, PID 0x0121) had the following rules:
ATTRS{idProduct}=="0121", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0121", ENV{.MM_USBIFNUM}=="01", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
In our ZTE rules we also have some for the device with PID 0x0002, like:
ATTRS{idProduct}=="0002", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_ZTE_PORT_TYPE_MODEM}="1"
ATTRS{idProduct}=="0002", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_ZTE_PORT_TYPE_AUX}="1"
And it seems that we can grab multiple PIDs from a single port, i.e. from the
parent objects in the hierarchy:
udevadm info -a -n /dev/ttyUSB4 | grep idProduct
ATTRS{idProduct}=="0121"
ATTRS{idProduct}=="0020"
ATTRS{idProduct}=="0002"
Where that 0x0002 idProduct is not from the modem, but from the EHCI Host
Controller (with idVendor 0x1d6b in my case).
So... we end up seeing that both set of rules will apply to the ports, and we
misleadingly get:
(ttyUSB3) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
ZTE: AT port 'tty/ttyUSB2' flagged as primary
(ttyUSB2) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
ZTE: AT port 'tty/ttyUSB1' flagged as secondary
(ttyUSB1) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
ZTE: AT port 'tty/ttyUSB4' flagged as primary
b_port(): (ttyUSB4) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB2 at (primary)
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB1 at (secondary)
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB2 data (primary)
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB0 qcdm
Which is wrong, as ttyUSB4 should have been our primary port, not ttyUSB2.
With this patch on, the rules apply only to the VID/PID pair, and we end up
getting what we really wanted:
(ttyUSB3) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
(ttyUSB2) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
ZTE: AT port 'tty/ttyUSB1' flagged as secondary
(ttyUSB1) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
ZTE: AT port 'tty/ttyUSB4' flagged as primary
b_port(): (ttyUSB4) type 'at' claimed by /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB4 at (primary)
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB1 at (secondary)
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB4 data (primary)
(/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2) tty/ttyUSB0 qcdm
https://bugzilla.gnome.org/show_bug.cgi?id=694759
Instead of a custom modem_init() step in the 'Modem' interface, just add a
sequence of port initialization commands in each port.
While enabling for the first time a non-hotplugged modem, we will issue the
port initialization commands only after having run the enabling_modem_init()
step (i.e. after ATZ usually).
We previously had the modem initialization command merged with some other port
setup commands in the 'modem_init' step of the 'Modem' interface. Instead of
doing this, we now split the logic into two separate steps:
A first 'enabling_modem_init' modem initialization step is to be run just after
the ports have been opened, but only during the first enabling operation, and
only if the modem was not hotplugged. A hotplugged modem is assumed to be
properly initialized already, so no need to ATZ-it. Also, we will now wait 500ms
by default after the modem initialization command has been sent, to let it
settle down.
The second 'modem_init' step will be run during the 'Modem' interface
initialization, and it currently only holds specific setup of the primary and
secondary serial ports. We'll be modifying this logic a bit in the next commits,
so no big deal to have that step name unchanged.
Both the ModemManager daemon and the mmcli will now include `libmm-glib.h' only.
We also handle two new special `_LIBMM_INSIDE_MM' and `LIBMM_INSIDE_MMCLI'
symbols, which if included before the `libmm-glib.h' library allow us to:
* Don't include the libmm-glib high level API in the ModemManager daemon, as
the object names would clash with those in the core.
* Define some of the methods of helper objects to be included only if compiling
ModemManager daemon or the mmcli.
Different ports of the same modem may get handled by different drivers. We
therefore need to provide a list of drivers (new `Modem.Drivers' property with
signature 'as') instead of just one (removed `Modem.Driver' property with
signature 's').
$ sudo mmcli -m 0 | grep drivers
| drivers: 'qcserial, qmi_wwan'
There's no real point in maintaining a separate `MMPlugin' interface, as all the
plugins will inherit from `MMPluginBase', so just merge them and simplify
everything.
Before this, we only exported the modem to DBus when all ports were organized,
in order to make sure that we select as primary port the one we really want and
not the first AT port grabbed. Given that to get all the ports organized we also
needed to wait to get all the ports grabbed, we can now also defer the creation
of the modem object until all the ports get grabbed. This allows us to create
different types of objects based on the ports available (e.g. we can now create
QMI-supported modem objects if we see a QMI port around).
Nokia modems/handsets use their own protocol (phonet) for all messaging related
operations, currently unsupported, so don't bother trying to check messaging
support with the generic implementation.
Instead of the `_in_port()' variants, we'll provide more generic
`_full()' methods. These should be used either if we want to send commands
to a specific port, or if we want to use a specific user-provided GCancellable.
In addition to this user-provided GCancellable, we keep the internal modem-wide
one.