Found a solution.

>> I have two mobile broadband Huawei E3372h devices, one with firmware
>> 21.200.07.01.26 (aka the 200-version) and one with firmware
>> 21.318.01.00.541 (aka the 318-version).
>> 
>> Whereas the 200-version works perfectly with a recent kernel (4.10),
>> the latter never manages to exchange any IP-packets. Upon debugging
>> USB-traces, I found that the 200-version correctly switches to NTB-16,
>> whereas the 318-version stays in NTB-32 mode.
> 
> And both these firmwares use the cdc_ncm class driver directly, and not
> the huawei_cdc_ncm driver?  I.e. they appear as true CDC NCM class
> devices

They appear to use the huawei_cdc_ncm driver. I am not at all familiar with 
driver nor kernel architecture, so I am sorry if I am being a bit vague. 

> Could you test if 
> 
> echo Y  >/sys/class/net/xxx/cdc_ncm/ndp_to_end
> 
> makes any difference, where xxx is the name of your wwan netdev?

It did not make any difference. See root cause below.

> Section 7.2 "Using Alternate Settings to Reset an NCM Function":
> 
> "Whenever alternate setting 0 is selected by the host, the function
>  shall:
>  ..
>  - reset the NTB format to NTB-16
> “

I downloaded the spec, and started to investigate. Comparing Windows driver 
traces to the spec, I noticed that the Windows driver queried GET_NTB_FORMAT, 
prior to setting it to NTB-32. It was always 0x0001h (aka. NTB-32), directly 
after coming out of alternate setting = 0. 

So I threw together a small python-usb script, to see what was different 
between the two devices I had.

My testing sequence is: 

        alt_setting = 1 
        alt_setting = 0
        GET_NTB_PARAMETERS
        GET_NTB_FORMAT (#A)
        SET_CRC_MODE 
        SET_NTB_FORMAT
        GET_NTB_FORMAT (#B)
        alt_setting = 1 
        GET_NTB_FORMAT (#C)
        SET_NTB_FORMAT
        GET_NTB_FORMAT (#D)

BOTH devices come out of alt_setting = 0 (after step #A) with GET_NTB_FORMAT = 
0x0001h! 

Readout of GET_NTB_FORMAT:

#A      200: 0x0001             318: 0x0001 <— bug in both
#B      200: 0x0000             318: 0x0000
#C      200: 0x0000             318: 0x0001 <— bug in 318
#D      200: 0x0000             318: 0x0000

So it is clear, that the 318-firmware resets to NTB-32 after alt_setting = 1

It is clearly non-standard behaviour. 

The spec concerning SET_NTB_FORMAT reads:
 "The host shall only send this  command while the NCM Data Interface is in 
alternate setting 0.”

So I blindly added:

usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
                                       USB_TYPE_CLASS | USB_DIR_OUT
                                       | USB_RECIP_INTERFACE,
                                       USB_CDC_NCM_NTB16_FORMAT,
                                       iface_no, NULL, 0);

 in cdc_ncm_bind_common after the interface was switched back with alt_setting 
= 1. Now the device works.

I have zero experience whether this should or could be implemented in the 
driver, nor do I have any kernel development experience.

A solution in pseudocode:

If GET_NTB_FORMAT == 0x0001 { // no restraints on alt setting according to spec
        // device is still in NTB-32 mode, which clearly indicates 
        // a firmware that is not in the accordance with the spec
        Run SET_NTB_FORMAT(0x0000)
}

> We cannot make vendors fix their firmwares, but we can vote for less
> buggy firmware with our wallets… 

Sadly I did not investigate this prior to my purchase, otherwise I would have 
stayed clear of these devices. 

Its been a long and convoluted journey. But I learned a lot. 

Thank you for your hints and guidance,

Christian       --
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to