Re: Huawei E3131 wwan interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Enrico Mioso <mrkiko.rs@xxxxxxxxx> writes:

> Hi!
> I'm trying to investigate on the Huawei E3131 wwan interface - like the E398, 
> this device ignores the at^ndisdup command.
> I wanted to verify if my device was running a jungo firmware or not, since I 
> found contraddictory informations on the network.
> To this end, I patched the cdc_ncm driver with a function was responsible for 
> the initializzation of jungo devices:
>
> diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
> index 43afde8..79770ed 100644
> --- a/drivers/net/usb/cdc_ncm.c
> +++ b/drivers/net/usb/cdc_ncm.c
> @@ -39,6 +39,7 @@
>   */
>  
>  #include <linux/module.h>
> +#include <linux/usbdevice_fs.h>
>  #include <linux/init.h>
>  #include <linux/netdevice.h>
>  #include <linux/ctype.h>
> @@ -352,6 +353,37 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
>  	.nway_reset = usbnet_nway_reset,
>  };
>  
> +int hw_send_tlp_download_request(struct usb_interface *intf){
> +	printk("Entering hw_send_tlp_download_request...\n");
> +	struct usb_device *udev = interface_to_usbdev(intf);
> +	struct usb_host_interface *interface = intf->cur_altsetting;
> +	struct usbdevfs_ctrltransfer req = {0};
> +//memset?
> +	unsigned char buf[256] = {0};
> +	int retval = 0;
> +	req.bRequestType = 0xC0;
> +	req.bRequest = 0x02;
> +	req.wIndex = interface->desc.bInterfaceNumber;
> +	req.wValue = 1;
> +	req.wLength = 1;
> +	req.data = buf;
> +	req.timeout = 1000;
> +	retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), req.bRequest, req.bRequestType, req.wValue, req.wIndex, req.data, req.wLength, req.timeout);
> +	/*
> +		Check the TLP feature is activated or not, response value 0x01
> +		indicates success
> +	*/
> +	if (0 < retval && 0x01 == buf[0]){
> +		printk("Success!\n");
> +		return retval; /* succeeded */
> +	}
> +	else
> +	{ 
> +		printk("Failed...\n");
> +		return 0; /* failed */
> +	}
> +}
> +
>  int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
>  {
>  	struct cdc_ncm_ctx *ctx;
> @@ -1142,7 +1174,10 @@ static int cdc_ncm_check_connect(struct usbnet *dev)
>  static int
>  cdc_ncm_probe(struct usb_interface *udev, const struct usb_device_id *prod)
>  {
> -	return usbnet_probe(udev, prod);
> +	int retval;
> +	retval = usbnet_probe(udev, prod);
> +	hw_send_tlp_download_request(udev);
> +	return retval;
>  }
>  
>  static void cdc_ncm_disconnect(struct usb_interface *intf)
>
>
> and I'm hitting the "failed" case. So, can I say I'm not running a jungo-based 
> firmware?

This code enables the Qualcomm "Thin Layer Protocol", which is a
proprietary and undocumented (as far as open source goes, at least)
protocol for frame bundling. I don't think it's related to Jungo or not
at all.  If this protocol is implemented, then it is at a lower firmware
level (the Qualcomm firmware).

Enabling both NCM and TLP simultaneously does not make sense because
they do pretty much the same.  So this could be the reason your request
fails.  Or it could be becuase the device isn't a Qualcomm device at
all?

In any case, as far as I have been able to figure out, the TLP support
is entirely optional.  If you don't enable it then the device will work
just fine, without any frame bundling. This is one of the reasons I have
decided not to implement support for it.  The others being that the
protocol is undocumented, provides no measurable gain, and there are
standardized alternatives like NCM and MBIM available. Even RNDIS is
better documented.  TLP is dead because the vendor chose to not make it
public.  Let it rest in peace.

The Huawei driver does "Jungo detection" simply by looking at the
bcdDevice value.   You'll find a few tests like this:

  HW_JUNGO_BCDDEVICE_VALUE != dev->udev->descriptor.bcdDevice

where the constant is defined as 0x0102.

But you should note that we don't care unless there is a real quirk
needed.  We try to make the drivers generic enough to handle any device
with a specific device ID or class code.

Some of the tests in the Huawei driver is only to know whether to expect
one or two interfaces for the function.  We already deal with this by
looking at the Union descriptor.  And most (all?) of the other tests are
there to know whether or not to use QMI.  Which we figure out just fine
based on class codes for Huawei devices.

So I don't think you need to know where Huawei got the firmware for the
device. Focus on the features in that firmware instead, and try to
detect and support those features.

> And - another note.
> I never used ncm devices, so I don't know if there is a way to communicate with 
> the device directly via ncm protocol (i.e.: not using AT).

Not any standardized way, but NCM has the same support for embedded
vendor specific management protocols as ECM. So it could have something
like QMI embedded the same way we have seen on devices supported by
qmi_wwan.  Or RNDIS.

> When I try to bring up the ncm interface, I always get a "unexpected 
> notification" message.

Yes, and if that notification is 01 ("Response Available"), then this is
an indication that there is such a protocol embedded.  We've also seen
occasional 03 notifications from this device or E3276.  I have no idea
what that means.  03 is reserved AFAIK.

I would appreciate it alot if you could try to figure out the embedded
protocol here. If the protocol is somewhat documented, then we might be
able to support it. To do this, you need to start responding to those
"Response Available" notfications with USB_CDC_GET_ENCAPSULATED_RESPONSE
requests.  You could do this using libusb, temporarily forgetting about
the cdc_ncm driver and the network interface and focusing only on the
embedded protocol. But another and maybe even simpler approach is
hacking cdc-wdm subdriver support into cdc_ncm.  Take a look bind/unbind
in qmi_wwan and cdc_mbim and add similar subdriver support to cdc_ncm.
Since NCM actually use the notfication endpoint, you need to disable
that temporarily so that the cdc-wdm subdriver can own this endpoint.
But other than that, this should be a plain copy of the cdc_mbim
approach.

If successful, then you will have a cdc_ncm driver exporting the
embedded protocol as a /dev/cdc-wdmX character device.  You can then
start looking at the messages received there using userspace tools.


> Looking at the VERY MESSY w_cdc_driver.c release from Huawei, I noticed there 
> are various functions to deal with ncm fixups, particularly:
> - one for fixing up received packets
> - the other for fixing up sent packets

I believe that code predates the in-kernel cdc_ncm driver, and actually
is an alternative NCM driver implementation. The approaches taken by the
two drivers are very different, so it can be hard comparing the code.
But the end result should be pretty much the same.  We do have good
experience with the in-kernel driver handling the E3276, so I believe it
should work with these devices.

> So probably the ncm driver would need a substantial rewrite aniway, making it 
> more practical to create a new one.

Absolutely.  If these devices need many additional hacks then I believe
it is more appropriate to create a new driver.  Just like I made
qmi_wwan for the QMI devices, although the network protocol is plain CDC
ECM.

This will have to happen if you for example want the cdc-wdm subdriver
permanently.  As I said, standard NCM use notifications so we cannot
just steal the endpoint away from it.  We recently factored out parts of
the cdc_ncm driver for cdc_mbim.  It would be great if any of this could
be reused for such a vendor driver.  If it comes to that.

But do note that the messy driver is messy because it tries to combine
support for every possible Huawei device out there into one single
driver, including support for optional features like TLP.  Figuring out
which parts of the driver is required for a specific device isn't
straight forward.

> Another thing - the w_cdc_driver.c driver, seems to be free software!

Yes, it is.  As it has to be, because it is based on GPL code.  But it
has always been available with full source and a proper GPL license, so
there is no problem there.

> So - am I wrong or do we actually have all the hints we need to implement a 
> "proper" driver?

The driver is very useful as a hint, but I'm afraid it is far from a
complete documentation needed for a  "proper" driver.  Take a look at
the QMI support in there (if you can find it at all...).  It consists of
a few hard coded byte arrays which the driver will just blindly throw at
the device, hoping it will end up connected.  This may work sometimes,
but it is very, very far from the complete and working implementation we
ended up with.

> But - another quqestion is probably worthwhile: can someone confirm that the 
> w_cdc_driver.c can establish a connection, even with the device ignoring the 
> ^ndisdup / ^ndisconn commands?

I don't think I have seen any such confirmation for the E3131 (or even
the E3276).  So if you could start by testing this, then that would be
good.  If this driver is capable of initiating a connection, then it
should be just simple hard work to get the necessary parts into
mainline.

Thanks a lot for working on this.


Bjørn
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux