usb_modeswitch problem with Huawei E3372 [EDIT: FOUND BUG, SEE PATCH]

Bug #1593669 reported by Luigi Tarenga on 2016-06-17
This bug affects 1 person
Affects Status Importance Assigned to Milestone

Bug Description

I'm using raspbian on a raspberry pi 3 and I found a problem with usb_modeswitch udev rules
and the Huawei E3372 LTE usb modem. With default usb_modeswitch udev rules installed the modem
is not recognised and it stay in CD mode:
Bus 001 Device 038: ID 12d1:1f01 Huawei Technologies Co., Ltd.

If I install ModemManager and reinsert the usb modem it get switched into an ethernet device:
Bus 001 Device 039: ID 12d1:14dc Huawei Technologies Co., Ltd.

The problem is that there is nothing in ModemManager that "should" influence the switch of the modem.
I started debugging and found that the udev rules added by ModemManager have some "timing" influence
on the udev flow that make the switch happen. I came up with a simple test case...

ModemManager add some udev rules like:
77-mm-cinterion-port-types.rules 77-mm-nokia-port-types.rules 77-mm-telit-port-types.rules
77-mm-ericsson-mbm.rules 77-mm-pcmcia-device-blacklist.rules 77-mm-usb-device-blacklist.rules
77-mm-huawei-net-port-types.rules 77-mm-platform-serial-whitelist.rules 77-mm-usb-serial-adapters-greylist.rules
77-mm-longcheer-port-types.rules 77-mm-qdl-device-blacklist.rules 77-mm-x22x-port-types.rules
77-mm-mtk-port-types.rules 77-mm-simtech-port-types.rules 77-mm-zte-port-types.rules

to make the switch happen I just need 77-mm-ericsson-mbm.rules in place or 77-mm-qdl-device-blacklist.rules in place. With just one of those two the switch happen correctly.

What happen is that the rules in /lib/udev/rules.d/40-usb_modeswitch.rules have a little different
behavior. The rule:
ATTRS{idVendor}=="12d1", ATTR{bInterfaceNumber}=="00", ATTR{bInterfaceClass}=="08", RUN+="usb_modeswitch '%b/%k'"
is the one responsible of the switch but without ModemManager installed it get fired with %b/%k
having the following value: 1-1.4/1-1.4:1.0
If I install ModemManager (or just put in flace one of the 2 rules files mentioned) this same rules
get fired with %b/%k having the value: /1-1.4:1.0
%b does not hold any value anymore! and the only change is some udev rules that have not effect
on the device just plugged...

the binary usb_modeswitch invoked by udev is /lib/udev/usb_modeswitch, the calling sequence is:
udev fire rule from 40-usb_modeswitch.rules
/lib/udev/usb_modeswitch %b/%k
/bin/systemctl --no-block start usb_modeswitch@$1.service
/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %I

if usb_modeswitch_dispatcher get called from
usb_modeswitch@1-1.4-1-1.4:1.0.service then no switch happen while if systemd get correcly called
than usb_modeswitch_dispatcher get called from usb_modeswitch@1-1.4:1.0.service and the modem
is correclty switched.

there is a bug in usb_modeswitch rules but maybe even in other place because I can't explain why
the id of the device get changed with some rules that have no clue with this modem....

thanks in advance

Luigi Tarenga (luigi-tarenga) wrote :

I found the bug in usb_modeswitch!
the script /lib/udev/usb_modeswitch call systemctl without escaping and I suspect that it
rely on the unescaping done by systemd and use_modeswitch_dispatcher. I tried to correcly invoke
the dispatcher with the --switch-systemd option but it does not work or I don't know what kind
of escaping it want and support....

So my patch rely on using use_modeswitch_dispatcher with --switch-mode options.
The patch is on 2 distinct files:

--- usb_modeswitch 2016-06-17 13:26:07.449674124 +0200
+++ /lib/udev/usb_modeswitch 2016-06-17 13:25:35.730749887 +0200
@@ -80,7 +80,7 @@
   if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | /bin/grep -q upstart; then # Test if upstart is running
    exec /sbin/initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1
   elif [ -d "/run/systemd/system/" ]; then # Test if systemd is running
- exec /bin/systemctl --no-block start usb_modeswitch@$1.service
+ exec /bin/systemctl --no-block start $(systemd-escape --template=usb_modeswitch@.service $1)
    export TMPDIR=/run
    exec /usr/sbin/usb_modeswitch_dispatcher --switch-mode $1 &

--- usb_modeswitch@.service 2016-06-17 13:30:51.080058537 +0200
+++ /lib/systemd/system/usb_modeswitch@.service 2016-06-17 13:21:47.668214935 +0200
@@ -3,5 +3,5 @@

-ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %I
+ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-mode %I

With my patch the usb modem switch correctly when use_modeswitch get invoke as:
/lib/udev/usb_modeswitch 1-1.4/1-1.4:1.0

Now I don't need to install ModemManager to have the switch to work. Still I don't know why
the rules contained in ModemManager makes the id change to blank... but at this point I don't care :D

I hope this can help

summary: - usb_modeswitch problem with Huawei E3372
+ usb_modeswitch problem with Huawei E3372 [EDIT: FOUND BUG, SEE PATCH]
Luigi Tarenga (luigi-tarenga) wrote :

please take care, the patch code get wrapped on some lines.


To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers