Opened 2 years ago

Last modified 3 months ago

#17746 new bug

[USB tethering] Samsung S6810-L not working

Reported by: bipolar Owned by: nobody
Priority: normal Milestone: Unscheduled
Component: Drivers Version: R1/Development
Keywords: usb tethering Cc:
Blocked By: Blocking:
Platform: x86-64

Description

Seing the inclusion of the new usb_rndis driver, I've attempted to use the two (rather old) Android 4.1 smartphones I have access to.

This ticket is for the one that under Linux works as an RNDIS device.

A Samsung Galaxy Fame (S6810-L, Android 4.1): Under Linux it works for USB tethering thanks to the rndis_* (and cdc_ether) drivers.

Under Haiku, it doesn't seems to work (no device appears under /dev/net/usb_rndis/).

The only lines that appear on the syslog after pluging in the phone, and enabling the USB tethering are the following:

KERN: usb hub 32: port 2: new device connected
KERN: usb hub 32: KERN: port 2: new device connected
KERN: usb error hub 32: new device on a port that is already in use

By default it presents as a MTP device, until USB tethering is enabled. I guess that's the cause of the new device on a port that is already in use error?

I'm attaching the output of listusb -v /dev/bus/usb/6/2 under Haiku hrev55112, and sudo lsusb -v -d 04e8:6864 under Linux, just in case (plus `lsmod | grep usbnet).

On both cases is with USB tethering already enabled (and working in case of Linux).

Attachments (10)

USB_04e8_6864_Haiku.txt (3.1 KB ) - added by bipolar 2 years ago.
USB_04e8-6864_Linux.txt (4.9 KB ) - added by bipolar 2 years ago.
USB_04e8_6864_hrev57531.txt (3.4 KB ) - added by bipolar 3 months ago.
Updated "listusb -v" from current nightly (hrev57531)
usb_rndis-diff.txt (3.4 KB ) - added by bipolar 3 months ago.
usb_rndis-patched-syslog.txt (17.6 KB ) - added by bipolar 3 months ago.
"tail -f /var/log/syslog" output while testing the modified driver
usb_rndis-working-clean.txt (6.3 KB ) - added by bipolar 3 months ago.
log of usb_rndis driver working with Samsug S6810. File uploaded via said working connection!
usb_rndis-diff2.txt (4.6 KB ) - added by bipolar 3 months ago.
Updated .diff. Re-enabled _ReadLinkSpeed() call, as it is not the one causing errors.
usb_rndis-not-working.txt (7.8 KB ) - added by bipolar 3 months ago.
Relevant syslog output when usb_rndis drive fails to work, and ends on KDL (file details steps taken).
usb_rndis-working.txt (9.4 KB ) - added by bipolar 3 months ago.
Syslog output when the driver works as intended, and steps taken to avoid getting KDL (need to disable usb_rndis on Network preflets before disabling usb-tethering, and unpluging the phone),
usb_rndis-xhci-working.txt (11.5 KB ) - added by bipolar 3 months ago.
syslog from testing same phone, patched usb_rnids driver on a "XHCI only" machine. (includes descriptions of the steps taken).

Download all attachments as: .zip

Change History (26)

by bipolar, 2 years ago

Attachment: USB_04e8_6864_Haiku.txt added

by bipolar, 2 years ago

Attachment: USB_04e8-6864_Linux.txt added

comment:1 by pulkomandy, 2 years ago

By default it presents as a MTP device, until USB tethering is enabled. I guess that's the cause of the new device on a port that is already in use error?

Yes.

I'm attaching the output of listusb -v /dev/bus/usb/6/2 under Haiku hrev55112, and sudo lsusb -v -d 04e8:6864 under Linux

In Haiku the device is showing as CDC-ACM, and not RNDIS. Could it be that the phone decided that Haiku is not a recognized operating system, and so they switched to a different USB tethering mode?

in reply to:  1 comment:2 by bipolar, 2 years ago

Replying to pulkomandy:

In Haiku the device is showing as CDC-ACM, and not RNDIS. Could it be that the phone decided that Haiku is not a recognized operating system, and so they switched to a different USB tethering mode?

No idea :-(

I tried it again, but this time setting the phone to default to PTP instead of MTP (no way of selecting USB tethering as default).

The following lines appear in syslog after plugin it in, and enabling tethering:

KERN: usb hub 32: port 2: new device connected
KERN: usb error hub 32: new device on a port that is already in use
KERN: usb hub 32: port 2: new device connected
KERN: usb error hub 32: new device on a port that is already in use
KERN: usb error ehci 6: qtd (0xfb5f380) error: 0x80020d40
KERN: usb error ehci 6: qtd (0xfb5f600) error: 0x80020d40
KERN: usb error ehci 6: qtd (0xfb5f880) error: 0x80020d40
KERN: usb error ehci 6: qtd (0xfb5fb00) error: 0x80020d40
KERN: usb error ehci 6: qtd (0xfb5fd80) error: 0x80020d40

No idea what those errors are about. They also appeared in my previous tests with this phone. I didn't reported them earlier because I guess I got confused with the syslog output for my other phone (#17747) that also present similar qtd errors.

by bipolar, 3 months ago

Attachment: USB_04e8_6864_hrev57531.txt added

Updated "listusb -v" from current nightly (hrev57531)

comment:3 by bipolar, 3 months ago

Retested on current nightly. Output of "listusb -v" looks now more aligned to what Linux shows, but seems the usb_rndis driver still doesn't wants to work with this old phone :-)

syslog output looks cleaner (no "qtd erros"), and only shows the usual "new device connected" messages.

comment:4 by pulkomandy, 3 months ago

So the device reports this:

3	    Class .................. 0x02 Communications ()
4	    Subclass ............... 0x00 Communications ()
5	    Protocol ............... 0x00 Communications ()

This does not match what the driver expects:

https://cgit.haiku-os.org/haiku/tree/src/add-ons/kernel/drivers/network/ether/usb_rndis/Driver.cpp#n125

Maybe this phone is from before RNDIS got its proper subclass assigned.

But we can try to add a specific case for this phone, something like this:

	static usb_support_descriptor supportDescriptor[] = {
            { // Standard USB-RNDIS devices
		0xE0, /* CDC - Wireless device */
		0x01, 0x03, /* RNDIS subclass/protocol */
		0, 0 /* no specific vendor or device */
	    },
            { 0x02, 0x00, 0x00, 0x04e8, 0x6864 }
        };

	gUSBModule->register_driver(DRIVER_NAME, &supportDescriptor, 2, NULL);

RNDISDevice::_SetupDevice is also looking for the interface with the proper device class:

https://cgit.haiku-os.org/haiku/tree/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp#n630

This will need to be adjusted to also accept descriptor->interface_class == 0x02, descriptor->interface_subclass == 0x02 and descriptor->interface_protocol == 0xff, to match this part of the USB descriptor from listusb:

              Class .............. 0x02 Communications ()
19	                Subclass ........... 0x02 Communications (Abstract (modem), None)
20	                Protocol ........... 0xff Communications (Abstract (modem), Vendor Specific (MSFT RNDIS?))
21	                Interface String ... "RNDIS Communications Control"

(Maybe check in addition in that case that the interface string is "RNDIS Communications Control", to be extra sure, but since we are already filtering on the device ID, it should be fine even without this check).

So, something like this replacing lines 630-635:

    if (interface->generic_count == 0) {
        // Ignore this interface, it doesn't have enough endpoints, try the next one
        continue;
    } else if (descriptor->interface_class == USB_COMMUNICATION_WIRELESS_DEVICE_CLASS
				&& descriptor->interface_subclass == 0x01
				&& descriptor->interface_protocol == 0x03) {
        // Looks good!
    } else if (descriptor->interface_class == 0x02
				&& descriptor->interface_subclass == 0x02
				&& descriptor->interface_protocol == 0x0F) {
        // TODO check interface string here, "continue" if it's not "RNDIS Communications Control"
    } else {
        // Interface does not match either of our known ways to identify an RNDIS interface, ignore it and try the next one
        continue;
    }

Let us know if that works better :)

comment:5 by bipolar, 3 months ago

Thanks PulkoMandy.

Applied your suggested changes (had to remove the "&" from gUSBModule->register_driver(DRIVER_NAME, &supportDescriptor, 2, NULL); to make it compile, not sure if that was the right thing to do :-/).

Installed the driver under ~/config/non-packaged/add-ons/kernel/drivers (bin/usb_rndis and symlink to dev/net/usb_rndis. Just in case, rebooted and black-listed the "system" usb_rndis.

tail -f /var/log/syslog shows:

KERN: usb_rndis: did not find a union descriptor
KERN: usb_rndis: failed to setup device

When I enable USB tethering on the phone.

Still... sounds like progress! :-D

Edit: I'll double check tomorrow, hopefully with fresher eyes/head :-D

Last edited 3 months ago by bipolar (previous) (diff)

comment:6 by thebuck, 3 months ago

Typo?

-               && descriptor->interface_protocol == 0x0F) {
+               && descriptor->interface_protocol == 0xFF) {

comment:7 by pulkomandy, 3 months ago

Yes, not sure how that happened but it should be 0xFF.

comment:8 by bipolar, 3 months ago

After applying the change mentioned by thebuck, now I get:

KERN: usb_rndis: control interface invalid
KERN: usb_rndis: failed to setup device

Getting closer, I feel! :-D

Edit: I assume I need to change https://cgit.haiku-os.org/haiku/tree/src/add-ons/kernel/drivers/network/ether/usb_rndis/RNDISDevice.cpp#n682 in a similar way to what PulkoMandy suggested for lines 630-635 (to allow "0x02, 0x02, 0xFF" for my device). Task for tomorrow! :-D

Last edited 3 months ago by bipolar (previous) (diff)

comment:9 by korli, 3 months ago

For instance:

if ((descriptor->interface_class != USB_COMMUNICATION_WIRELESS_DEVICE_CLASS || descriptor->interface_subclass != 0x01 || descriptor->interface_protocol != 0x03) 
		&& (descriptor->interface_class != USB_COMMUNICATION_DEVICE_CLASS || descriptor->interface_subclass != 0x02 || descriptor->interface_protocol != 0xff)
	|| interface->endpoint_count == 0) {

comment:10 by bipolar, 3 months ago

Welp, after massaging a bit that last suggestion by korli, the usb_rndis finally recognized my phone... it started to *try* to configure it (kept getting rndis related errors on the syslog, and after I unplugged the device, got a nice KDL (I got lucky, and cont worked :-D).

Next.. I will attach the used code diff, and a clean version of the relevant syslog messages (including KDL text).

Starting to look like it might be better to just try to find a different device I could use :-D

by bipolar, 3 months ago

Attachment: usb_rndis-diff.txt added

by bipolar, 3 months ago

"tail -f /var/log/syslog" output while testing the modified driver

comment:11 by pulkomandy, 3 months ago

The change you made to Korli's suggested code seems incorrect.

You have this:

if ((interface->endpoint_count == 0)
    || ! ((descriptor->interface_class == USB_COMMUNICATION_WIRELESS_DEVICE_CLASS && (descriptor->interface_protocol == 0x01 || descriptor->interface_protocol == 0x03))
    || (descriptor->interface_class == USB_COMMUNICATION_DEVICE_CLASS && (descriptor->interface_protocol == 0x02 || descriptor->interface_protocol == 0xFF)))) {

The second condition will always match in your case (for any descriptor). So, that will not work.

This is impossible to understand without spending 5 minutes looking at the code anyway, so let's split it up into smaller pieces so it's easier to read:

    if (interface->endpoint_count == 0) {
        TRACE_ALWAYS("control interface has no endpoint_count\n");
        return B_ERROR;
    }

    if (descriptor->interface_class == USB_COMMUNICATION_WIRELESS_DEVICE_CLASS) {
        if ((descriptor->interface_subclass != 0x01 || descriptor->interface_protocol != 0x03) {
            TRACE_ALWAYS("control interface has invalid interface subclass or protocol\n");
            return B_ERROR;
        }
    } else if (descriptor->interface_class == USB_COMMUNICATION_DEVICE_CLASS) {
        // Microsoft USBRNDIS style control interface
        if ((descriptor->interface_subclass != 0x02 || descriptor->interface_protocol != 0xFF) {
            TRACE_ALWAYS("control interface has invalid interface subclass or protocol\n");
            return B_ERROR;
        }
    } else {
        TRACE_ALWAYS("control interface has invalid interface class\n");
        return B_ERROR;
    }

Then, we have this in the syslog:

usb_rndis: link speed: -2021749710 * 100bps

Getting the link speed didn't work very well. I think for now we can comment out the call to _ReadLinkSpeed, there will be no problem with that except the link speed won't be reported in network preferences.

I don't know if this failure to get the link speed is what causes the next problems or not. The next thing to do is probably to enable TRACE (add a #define TRACE_RNDIS 1 in Driver.h so we can get more information in the debug logs.

Then we will see which requests caused the other errors and hopefully see more from _EnableBroadcast, which is supposed to enable the traffic, but it seems it didn't work.

comment:12 by bipolar, 3 months ago

Thanks Adrien. Splitting that logic indeed helps readability, for sure :-)

I've applied those changes, disabled the call to _ReadLinkSpeed(), enabled TRACE_RNDIS, and blacklisted the system-wide usb_rndis driver.

Long story short... in 2 parts:

1.- Connecting the phone and enabling USB tethering when the custom driver is already installed:

Doesn't works. And disabling tethering on the phone (before even unplugging it) eventually ends in a KDL (vm_page_fault from RNDISDevice::_NotifyCallback()). Sometimes cont ends with an still usable system, sometimes... a reboot is needed.

2.- If I connect the phone, enable USB tethering... and ONLY THEN I install the custom usb_rndis driver under non-packaged/[...]... it seems that things work relatively fine! (besides some USB ehci, and usb_rndis errors appearing on the syslog).

Quick tested doing pkgman refresh, and opening a couple of sites in WebPositive.

Disabling USB tethering, and waiting for the syslog output from usb_rndis to end before unplugging the phone seems to avoid surprise KDLs :-D

Will do my best to provide concise/clear logs for both situations (probably tomorrow, current logs are too long/messy).

Thanks you guys! Pretty wild seeing it actually "become alive"!

Last edited 3 months ago by bipolar (previous) (diff)

by bipolar, 3 months ago

Attachment: usb_rndis-working-clean.txt added

log of usb_rndis driver working with Samsug S6810. File uploaded via said working connection!

comment:13 by bipolar, 3 months ago

And... got a KDL upon disabling tethering on the phone thou :-D (vm_page_fault on "usb explore" thread, from device_node DeviceRemoved(), apparently). Oh well! :-D

by bipolar, 3 months ago

Attachment: usb_rndis-diff2.txt added

Updated .diff. Re-enabled _ReadLinkSpeed() call, as it is not the one causing errors.

by bipolar, 3 months ago

Attachment: usb_rndis-not-working.txt added

Relevant syslog output when usb_rndis drive fails to work, and ends on KDL (file details steps taken).

by bipolar, 3 months ago

Attachment: usb_rndis-working.txt added

Syslog output when the driver works as intended, and steps taken to avoid getting KDL (need to disable usb_rndis on Network preflets before disabling usb-tethering, and unpluging the phone),

comment:14 by bipolar, 3 months ago

Comparing both syslogs, seems that all goes well up to the return of _RNDISInitialize(). Then... even the mac address has a bogus value, and things just get worse from there.

Seems like EHCI gets confused with the usb device changing modes?

Will try to test on a machine with XHCI only, to see if XHCI vs EHCI makes any difference.

by bipolar, 3 months ago

Attachment: usb_rndis-xhci-working.txt added

syslog from testing same phone, patched usb_rnids driver on a "XHCI only" machine. (includes descriptions of the steps taken).

comment:15 by bipolar, 3 months ago

Neither unplugging the phone, or disabling USB tethering while usb_rnid driver was in use caused KDLs.

Attempting to re-connect the phone appeared to work, but could not actually access the internet. Rebooting and following the same steps detailed in the log file... resulted in working connection again (well enough as to actually slowly complete pkgman update).

Edit: tests where performed on hrev57554, 64 bits.

Last edited 3 months ago by bipolar (previous) (diff)

comment:16 by pulkomandy, 3 months ago

I think we can add some more checks to _GetOID.

First of all, _ReadResponse does not return the actual length of the response, so we don't know if there was actually enough data in the reply. Probably _ReadResponse could return the actual length instead of B_OK when it received something (and all places where we call it should be adjusted).

Then, in _GetOID, the response contains a 24 byte header before the reply. We don't check anything in there either. We should check the following layout:

uint32 MessageType == 0x80000004;
uint32 MessageLength == length + 24;
uint32 RequestID == 0x00000001; // Currently all our requests have ID 1 (there is a TODO about it in the code)
uint32 Status == 0; // RNDIS_STATUS_SUCCESS
uint32 InformationBufferLength == length;
uint32 InformationBufferOffset == 24;

If one of them does not match with that, we will have a better idea what is happening.

This info is from the USB-RNDIS specification: https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/WinArchive/%5BMS-RNDIS%5D.pdf

Note: See TracTickets for help on using tickets.