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