Wie lässt sich Ethernet auf Android über OTG zum Laufen bringen?

Ich versuche, ein LTE-Modem zu verwenden, das über ein OTG-Kabel mit einem Android 7-Gerät verbunden ist. Der Kernel erkennt das Gerät und registriert es bei cdc_ether, aber ich kann die Verbindung vom Gerät nicht verwenden. Liegt das daran, dass es nachträglich als USB-Speicher gemountet wird?

Das Gerät wird nicht als Gerät in der Android-Benutzeroberfläche/Statusleiste angezeigt.

Wenn ich die MTP-Unterstützung deaktiviere, wird sich das Gerät cdc_etherüberhaupt nicht registrieren.

dmesg:

[10946.408785] usb 1-1.3: new high-speed USB device number 21 using msm_hsusb_host
[10946.525287] usb 1-1.3: New USB device found, idVendor=19d2, idProduct=1225
[10946.525306] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10946.525316] usb 1-1.3: Product: ZTE Mobile Broadband
[10946.525325] usb 1-1.3: Manufacturer: ZTE,Incorporated
[10946.525335] usb 1-1.3: SerialNumber: MF8610ZTED000000
[10946.529662] usb-storage 1-1.3:1.0: USB Mass Storage device detected
[10946.532702] scsi host19: usb-storage 1-1.3:1.0
[10947.538579] scsi 19:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2
[10952.740595] usb 1-1.3: USB disconnect, device number 21
[10953.087891] usb 1-1.3: new high-speed USB device number 22 using msm_hsusb_host
[10953.232955] usb 1-1.3: New USB device found, idVendor=19d2, idProduct=1405
[10953.232969] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10953.232977] usb 1-1.3: Product: ZTE Mobile Broadband
[10953.232984] usb 1-1.3: Manufacturer: ZTE,Incorporated
[10953.232991] usb 1-1.3: SerialNumber: MF8610ZTED000000
[10953.260856] cdc_ether 1-1.3:1.0 usb0: register 'cdc_ether' at usb-msm_hsusb_host-1.3, CDC Ethernet Device, 36:4b:50:b7:ef:da
[10953.262322] usb-storage 1-1.3:1.2: USB Mass Storage device detected
[10953.262652] scsi host20: usb-storage 1-1.3:1.2
[10954.261139] scsi 20:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2

dmesgmit deaktiviertem MTP:

[10664.987934] usb 1-1.3: new high-speed USB device number 19 using msm_hsusb_host
[10665.105272] usb 1-1.3: New USB device found, idVendor=19d2, idProduct=1225
[10665.105291] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[10665.105301] usb 1-1.3: Product: ZTE Mobile Broadband
[10665.105310] usb 1-1.3: Manufacturer: ZTE,Incorporated
[10665.105320] usb 1-1.3: SerialNumber: MF8610ZTED000000
[10665.110339] usb-storage 1-1.3:1.0: USB Mass Storage device detected
[10665.111320] scsi host17: usb-storage 1-1.3:1.0
[10666.110748] scsi 17:0:0:0: CD-ROM            ZTE      USB SCSI CD-ROM  2.31 PQ: 0 ANSI: 2
[10671.223090] usb 1-1.3: USB disconnect, device number 19
[10671.407859] msm_otg 78db000.usb: OTG runtime idle
[10671.407887] msm_otg 78db000.usb: OTG runtime suspend

ifconfig:

TB-8504F:/ # ifconfig                                                                                                                  
wlan0     Link encap:Ethernet  HWaddr 40:a1:08:36:5b:0d
          inet addr:192.168.1.133  Bcast:192.168.1.255  Mask:255.255.255.0 
          inet6 addr: 2605:a601:ab2b:9900:b19e:4f2e:5d28:5fa9/64 Scope: Global
          inet6 addr: fe80::42a1:8ff:fe36:5b0d/64 Scope: Link
          inet6 addr: 2605:a601:ab2b:9900:42a1:8ff:fe36:5b0d/64 Scope: Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:27906 errors:0 dropped:4 overruns:0 frame:0 
          TX packets:17795 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:14342222 TX bytes:8697917 

dummy0    Link encap:Ethernet  HWaddr c6:b9:c8:82:8f:7e
          inet6 addr: fe80::c4b9:c8ff:fe82:8f7e/64 Scope: Link
          UP BROADCAST RUNNING NOARP  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:0 
          RX bytes:0 TX bytes:210 

p2p0      Link encap:Ethernet  HWaddr 42:a1:08:36:5b:0d
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:1000 
          RX bytes:0 TX bytes:0 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0 
          inet6 addr: ::1/128 Scope: Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:0 
          RX bytes:0 TX bytes:0 

ip l:

255|TB-8504F:/ # ip l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/ether c6:b9:c8:82:8f:7e brd ff:ff:ff:ff:ff:ff
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group default 
    link/sit 0.0.0.0 brd 0.0.0.0
20: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether 40:a1:08:36:5b:0d brd ff:ff:ff:ff:ff:ff
21: p2p0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN mode DORMANT group default qlen 1000
    link/ether 42:a1:08:36:5b:0d brd ff:ff:ff:ff:ff:ff
31: usb0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 36:4b:50:b7:ef:da brd ff:ff:ff:ff:ff:ff

usb0Das Gerät wird mit der in aufgelisteten MAC-Adresse angezeigt dmesg.

aber ich kann die Verbindung vom Gerät nicht verwenden. Wie haben Sie versucht, sie zu verwenden? Android wird es nicht konfigurieren (es sei denn, einigeninitDateien von.rc), Sie müssen es manuell tun. Wird es als Netzwerkschnittstelle angezeigt (überprüfen Sie es mitip loderifconfig)?
vielen Dank für die Antwort - ich habe die angeforderten Protokolle hinzugefügt - haben Sie ein Beispiel dafür, wie Sie einen benutzerdefinierten Eintrag zu init.rc-Dateien hinzufügen? Ich kann die Startpartition auf diesem Gerät ändern
Ich denke, usb0ist die Schnittstelle. Sie können dies jedoch bestätigen, indem Sie den Dongle entfernen. Sie können diese Schnittstelle mit ipBefehlen konfigurieren (einrichten, IP setzen, Route hinzufügen usw.). Das Android-Framework erkennt diese Schnittstelle jedoch nicht, sodass einige APIs das Gerät offline melden würden. Android konfiguriert und verwaltet Hardwareressourcen nicht direkt, sondern über vom Anbieter bereitgestellte HALs. Wenn Sie also eine neue Hardwareressource hinzufügen möchten, müssen Sie deren HAL als nativen Dienst ausführen. Das Android-Framework würde damit interagieren. In einfachen Worten, es muss ein benutzerdefiniertes ROM neu erstellt werden.
Ich habe die Quelle für dieses Gerät und habe das ROM erstellt / modifiziert, um ein Quectel-Modem zu unterstützen. Vielen Dank für Ihre Informationen! usb0 ist die Schnittstelle - sie verschwindet, wenn ich sie entferne
Entwicklungsbezogene Fragen sind hier nicht zum Thema. // Android bietet begrenzte Unterstützung für Ethernet. Sehen Sie dies , dies , dies und dies . Wenn nur das Massenspeichergerät und nicht das Ethernet angezeigt wird, muss Ihr Dongle ein Flip-Flop-Gerät sein, das USB_ModeSwitch benötigt .
Wo sind Entwicklungsfragen erlaubt? Wenn ich in SO frage, werde ich hierher geleitet ...
Moderatoren haben ihre eigenen Zwänge und Vorgehensweisen. Aber Sie sollten AMAP klar sagen, dass Ihre Frage entwicklungsorientiert ist. Wie im Fall dieser Frage scheint es sich um Endbenutzer zu handeln. Aber nach Gespräch erweist es sich als entwicklungsorientiert. Dies kann irreführen.

Antworten (1)

Es gibt eine lange Liste von Ethernet-bezogenen Fragen, aber keine hat eine umfassende Antwort, die alle Aspekte abdeckt. Ich verallgemeinere Ihre Frage, um mein Wissen darüber zu teilen.

Dies ist, was Sie tun müssen, damit Ethernet auf Android funktioniert:

  • Stellen Sie sicher, dass OTG-Unterstützung verfügbar ist
  • Der Kernel muss mit Ethernet- (und USB-Ethernet-) Unterstützung erstellt werden
  • Behandeln Sie den USB-Modusschalter und das Laden des Kernelmoduls (falls zutreffend)
  • Lassen Sie das Android-Framework die Netzwerkkonfiguration durchführen oder führen Sie dies manuell durch

Hinweis: Alles, was unten beschrieben wird, erfordert ein gerootetes Gerät oder zumindest eines mit entsperrtem Bootloader.
Sie sollten mit der Befehlszeilenschnittstelle vertraut sein.


OTG-UNTERSTÜTZUNG

Ihr Gerät muss im USB-Host-Modus betrieben werden können. EthernetServicewird nur gestartetandroid.hardware.usb.host , wenn das Gerät die Funktion USB-Host ( ) oder Ethernet ( ) unterstützt android.hardware.ethernet. Möglicherweise müssen Sie auch einen USB-Hub mit eigener Stromversorgung verwenden, wenn die USB-Stromversorgung von Android für das angeschlossene Gerät nicht ausreicht. Verwandte Frage:

KERNEL-KONFIGURATION

Um Ethernet über USB (Adapter oder modemähnliche Geräte) zu verwenden, muss der Kernel mit CONFIG_USB_USBNETund anderen Konfigurationen wie USB_NET_CDCETHER, USB_NET_HUAWEI_CDC_NCM, USB_NET_CDC_MBIMusw. gebaut werden, abhängig von der Art des angeschlossenen Geräts und dem Protokoll, das es spricht. Verwandte Fragen:

USB-MODUSSCHALTER UND KERNEL-MODUL LADEN

Viele USB-Netzwerkgeräte sind Multimode- oder Flip-Flop- Geräte. Sie werden beim Einstecken als USB-Massenspeichergerät (auch als ZeroCD- Modus bezeichnet) angezeigt und müssen in den Ethernet/PPP-Modus geschaltet werden. USB_ModeSwitch ist ein Linux-Tool, das häufig für diesen Zweck verwendet wird. Sehen Sie hier einige Details , wie es funktioniert. Sie müssen dieses Tool für Ihr Gerät erstellen oder diese Binärdatei für aarch64. Holen Sie sich die Gerätedatenbank von hier .

Um den Modus automatisch zu wechseln, wenn das Gerät mit Android verbunden ist, müssen wir Kernel-USB- uevents abhören , entweder über einen Hotplug-Helfer oder einen Userspace-Daemon (wie udevunter Linux und ueventdunter Android). Zusätzlich kann das Kernelmodul auch automatisch geladen/entladen werden. Ich definiere hier einen initDienst , um dies zu erreichen, Sie können dies auch manuell tun.

Hinweis: Es gibt eine Android-App PPP Widget (vom Entwickler von USB_ModeSwitch, ich habe keine Zugehörigkeit), die den Moduswechsel automatisch handhabt und "keine Kernel-Treibermodule benötigt, die 'Treiber'-Implementierung basiert auf der Android-USB-Host-API" . Das könnte Sie auch interessieren.

# /system/etc/init/custom.rc

# kernel hotplug or uevent daemon service
service cust.udevd /system/sbin/busybox uevent /system/sbin/udev.sh
    seclabel u:r:magisk:s0
    disabled
    writepid /dev/cpuset/system-background/tasks

# set kernel hotplug helper or start uevent daemon on boot
on property:sys.boot_completed=1
    #write /proc/sys/kernel/hotplug /system/sbin/udev.sh
    start cust.udevd

* Im Falle von Hotplug müssen Sie benutzerdefinierte SELinux-Richtlinien definieren, damit der Kernel Änderungen vornehmen kann (siehe diese Antwort für Details).

#!/system/bin/sh

# /system/sbin/udev.sh script is executed from kernel hotplug or uevent daemon

# set PATH where you placed binaries
export PATH=/system/bin

# save log
exec >>/dev/udev.log 2>&1

# don't execute multiple instances
exec 200<>/dev/udev.lock
flock 200

VID="12d1"          # USB vendor ID of a Huawei devcie
PID_UMS="1f01"      # product ID in ZeroCD mode
PID_ETH="14db"      # product ID in Ethernet mode
MODULE="cdc_ether"  # kernel module for USB Ethernet
IFACE="usb0"        # Ethernet interface name

matches() {
    [ -e "/sys/$DEVPATH/$1" ] || return 1
    [ "$(cat "/sys/$DEVPATH/$1")" = "$2" ] || return 1
    return 0
}

# check if a new USB device is added or removed
if [ "$SUBSYSTEM" = "usb" ]
then
    # check if a USB device is added, then match VID and PID for mode switching
    # also device must belong to UMS class: https://www.usb.org/defined-class-codes#anchor_BaseClass08h
    if [ "$ACTION" = "add" ] && echo "$PRODUCT" | grep -q "$VID/$PID_UMS/" &&
        matches bInterfaceClass 08 && matches bInterfaceNumber 00
    then
        echo "Switching USB mode..."

        # USB mode switching of flip flop devices (USB modems, routers etc.)
        # usb_modeswitch_dispatcher needs /system/sbin/usb_modeswitch binary and configuration files in /etc
        # so you need to modify the hard-coded paths in source code as per your requirement
        usb_modeswitch_dispatcher --switch-mode "$(basename "$DEVPATH")"
    fi

    # match VID and PID for module loading
    # modprobe should be built with the hard-coded path to where you place modules e.g. /system/lib
    if echo "$PRODUCT" | grep -q "$VID/$PID_ETH/"
    then
        if [ "$ACTION" = "add" ] && ! grep -q "^$MODULE " /proc/modules
        then
            echo "Loading $MODULE module..."
            modprobe "$MODULE"

        elif [ "$ACTION" = "remove" ] && grep -q "^$MODULE " /proc/modules
        then
            echo "Removing $MODULE module..."
            modprobe -r "$MODULE"
        fi
    fi
fi

# on network interface event
if [ "$SUBSYSTEM" = "net" ] && [ "$INTERFACE" = "$IFACE" ]
then
    if [ "$ACTION" = "add" ]
    then
        echo "Starting cust.eth_config service..."
        #start cust.eth_config    # uncomment if you want to do manual network configuration
    fi

    if [ "$ACTION" = "remove" ]
    then
        echo "Stopping cust.eth_config service..."
        #stop cust.eth_config    # uncomment if you want to do manual network configuration
    fi
fi

NETZWERKKONFIGURATION

Das Android-Framework hat einen fest codierten Namen für die Ethernet-Schnittstelle ( Standard ist eth0, eth1, ...). Immer wenn eine Ethernet-Schnittstelle erscheint, wird ihr Name mit dem fest codierten Wert abgeglichen . Das nachträgliche Umbenennen der Schnittstelle funktioniert nicht, da nur der vom Kernel bereitgestellte Schnittstellenname verfolgt wird .

Daher müssen Sie diese Namenskonvention zwischen Kernel und AOSP konsistent machen, indem Sie eine der beiden ändern (falls erforderlich). Der vom Kernel bereitgestellte Name kann mit ipdem Tool angezeigt werden (wie in Ihrem Fall usb0). Verwenden dumpsysoder dekompilieren Sie /system/framework/framework-res.apkmit apktool , um den AOSP-Wert anzuzeigen.

~$ dumpsys ethernet
...
  Ethernet interface name filter: eth\d
...

Sobald eine Ethernet-Schnittstelle erscheint, konfiguriert Android sie automatisch, NetworkMonitorvalidiert die Konnektivität und ConnectivityServiceschaltet WLAN und mobile Daten aus (falls eingeschaltet). Andere an der Konfiguration beteiligte Dienste und Komponenten umfassen UsbHostManager, EthernetTracker, EthernetNetworkFactory, IpClient.eth0, und .DhcpClientDnsManagerNetd

EthernetService wurde in Android 5 hinzugefügt. Davor wurde AOSP gepatcht, damit Ethernet funktioniert (siehe zB this und this ). Immer noch Standard-Android bietet keine GUI-Einstellungen für Ethernet, aber einige Custom-ROM-Entwickler und OEMs tun dies (siehe z. B. this ). EthernetManagerKlasse, die zum Festlegen und Speichern der manuellen IP-Konfiguration (bis /data/misc/ethernet/ipconfig.txt) verwendet wird , ist ausgeblendet . Standardmäßig wird eine fest codierte Konfiguration (siehe Verwendung dumpsys ethernetunter „IP-Konfigurationen:“) oder eine von DHCP bereitgestellte Konfiguration verwendet .

MANUELLE KONFIGURATION

Möglicherweise möchten Sie eine manuelle Netzwerkkonfiguration durchführen, z. B. wenn:

  • Das Android-Framework konfiguriert die Ethernet-Schnittstelle nicht (auf älteren Geräten oder aufgrund einer Inkonsistenz der Schnittstellennamen).
  • Sie möchten eine statische IP-Adresse oder einen anderen DNS-Server festlegen.
  • Sie möchten Ethernet zusammen mit WLAN oder mobilen Daten verwenden oder das Internet zwischen diesen teilen.

Aber in diesem Fall bleibt der Java-Netzwerkstack von Android inaktiv, sodass sich einige Apps, die von Android-APIs abhängen, möglicherweise nicht normal verhalten. Einzelheiten dazu finden Sie unter Herstellen einer WLAN-Verbindung über ADB Shell .

# /system/etc/init/custom.rc

# Ethernet IP configuration service
service cust.eth_config /system/sbin/eth_config.sh
    seclabel u:r:magisk:s0
    disabled
    writepid /dev/cpuset/system-background/tasks

# clear routing and DNS
on property:init.svc.cust.eth_config=stopped
    exec u:r:magisk:s0 -- /system/sbin/eth_config.sh stop
#!/system/bin/sh

# /system/sbin/eth_config.sh script is executed from eth_config init service

# set PATH where you placed binaries
export PATH=/system/bin

IFACE=usb0                    # Ethernet interface name
DIR=/data/local/tmp/ethernet  # temporary directory
mkdir -p $DIR

# save log
exec >$DIR/eth_config.log 2>&1

if [ "$1" = stop ]
then
    echo "Clearing configuration..."
    ip ru del lookup main
    ip r f table main
    ndc resolver setnetdns 0 '' 0.0.0.0
    exit
fi

# destroy set network if any
ndc network default set 0

# turn WiFi and Mobile Data off
svc wifi disable
svc data disable

# set interfaces up
ip link set dev lo up
ip link set dev $IFACE up

# Android doesn't use main table by default
ip rule add lookup main

# set IP, route and DNS manually here
# or add any other IP/routing configuration
# or run a minimal DHCP client as follows

# create 'udhcpc' script
<<-'SCRIPT' cat >$DIR/udhcpc_default.script
#!/system/bin/sh

case $1 in
    bound|renew)
        echo "Setting IP address, gateway route and DNS for $interface..."
        ip address f dev $interface
        ip route f table main
        ip address add $ip/$mask dev $interface
        ip route add default via $router dev $interface
        ndc resolver setnetdns 0 '' $dns
    ;;
    *)
        echo "Ignoring $1"
    ;;
esac
SCRIPT

# start DHCP client to obtain IP from server
chmod 0755 $DIR/udhcpc_default.script
exec busybox udhcpc -v -f -i $IFACE -s $DIR/udhcpc_default.script

Vergessen Sie nicht, die richtigen Berechtigungen für Datei- und Shell-Skripte festzulegen .rc. Nach der Einrichtung funktioniert Ethernet, sobald Sie den USB-Adapter anschließen.

@moderatoren führen sie bei Bedarf mit einer anderen ähnlichen Frage zusammen.
Das scheint genau das Problem zu sein, mit dem ich konfrontiert bin. Aber ich kann nicht verstehen, wie die usbXSchnittstelle umbenannt wird in ethX... Könnten Sie bitte weitere Details angeben?
@ EM90 Ich denke, ich habe es bereits gut erklärt: " Sie müssen also diese Namenskonvention zwischen Kernel und AOSP konsistent machen, indem Sie eine der beiden ändern ". In einfachen Worten: Bauen Sie Ihren Kernel oder das ROM neu auf. Oder „ Möglicherweise möchten Sie eine manuelle Netzwerkkonfiguration durchführen , wenn das Android-Framework die Ethernet-Schnittstelle aufgrund einer Inkonsistenz des Schnittstellennamens nicht konfiguriert “.
OK danke. Ich lese es mit mehr Sorgfalt. Wenn ich es richtig verstehe, kann ich die obigen Skripte verwenden, um die Netzwerkeinstellungen manuell zu konfigurieren. Probieren Sie diese aus.
+1 Vielen Dank für diese großartige Antwort! Wirklich viele Details, die nirgendwo sonst super schwer zu finden sind ... Wenn ich die Bemerkung "Android verwendet standardmäßig keine Haupttabelle" nicht gefunden hätte, hätte ich wahrscheinlich so viel Zeit damit verschwendet, ein RNDIS zu erstellen Ethernet-Verbindung funktioniert!