¿Cómo hacer que Ethernet funcione en Android a través de OTG?

Estoy tratando de usar un módem LTE conectado a un dispositivo Android 7 a través de un cable OTG. El núcleo reconoce el dispositivo y lo registra con cdc_ether, pero no puedo usar la conexión desde el dispositivo. ¿Es esto porque se monta posteriormente como almacenamiento USB?

El dispositivo no aparece como un dispositivo en la barra de estado/IU de Android.

Si desactivo la compatibilidad con MTP, el dispositivo no se registrará cdc_etheren absoluto.

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

dmesgcon MTP deshabilitado:

[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

El dispositivo aparece usb0con la dirección MAC que figura en dmesg.

pero no puedo usar la conexión desde el dispositivo. ¿Cómo intentaste usarlo? Android no lo configurará (a menos que se agregue una configuración personalizada a algunos deinitlos.rcarchivos), debe hacerlo manualmente. ¿Aparece como una interfaz de red (marque usandoip loifconfig)?
gracias por la respuesta, agregué los registros solicitados, ¿tiene un ejemplo de cómo agregar una entrada personalizada a los archivos init.rc? Puedo modificar la partición de arranque en este dispositivo
Creo que usb0es la interfaz. Sin embargo, puede confirmar quitando el dongle. Puede configurar esta interfaz mediante ipcomandos (configurar, configurar IP, agregar ruta, etc.). Pero el marco de trabajo de Android no estará al tanto de esta interfaz, por lo que algunas API informarán que el dispositivo está desconectado. Android no configura ni administra los recursos de hardware directamente, sino a través de las HAL proporcionadas por el proveedor. Entonces, si desea agregar un nuevo recurso de hardware, debe ejecutar su HAL como un servicio nativo. El marco de Android interactuaría con eso. En palabras simples, requiere reconstruir una ROM personalizada.
Tengo la fuente de este dispositivo y he estado creando la ROM/modificándola para admitir un módem quectel. ¡Muchas gracias por tu información! usb0 es la interfaz: desaparece cuando la elimino
Las preguntas relacionadas con el desarrollo están fuera de tema aquí. // Android proporciona soporte limitado para Ethernet. Ver esto , esto , esto y esto . Si solo aparece el dispositivo de almacenamiento masivo y no Ethernet, su dongle debe ser un dispositivo flip flop que necesita USB_ModeSwitch .
¿Dónde están permitidas las preguntas de desarrollo? Si pregunto en SO, me dirigen aquí...
Los moderadores tienen sus propias limitaciones y línea de acción. Pero debe indicar claramente AMAP que su pregunta está orientada al desarrollo. Como en el caso de esta pregunta, parece que está relacionada con los usuarios finales. Pero después de la conversación, resulta estar orientado al desarrollo. Esto puede inducir a error.

Respuestas (1)

Hay una larga lista de preguntas relacionadas con Ethernet, pero ninguna tiene una respuesta completa que cubra todos los aspectos. Estoy generalizando su pregunta para compartir mi conocimiento sobre esto.

Esto es lo que debe hacer para que Ethernet funcione en Android:

  • Asegúrese de que el soporte OTG esté disponible
  • El kernel debe construirse con soporte Ethernet (y USB Ethernet)
  • Manejar el cambio de modo USB y la carga del módulo kernel (si corresponde)
  • Haga que el marco de trabajo de Android realice la configuración de red o hágalo manualmente

Nota: Todo lo que se describe a continuación requiere un dispositivo rooteado , o al menos uno con el gestor de arranque desbloqueado.
Debe estar familiarizado con la interfaz de línea de comandos.


SOPORTE OTG

Su dispositivo debe poder operar en modo host USB. EthernetServicese inicia solo si el dispositivo es compatible con la función USB host ( android.hardware.usb.host) o Ethernet ( android.hardware.ethernet). Es posible que también deba usar un concentrador USB alimentado si la fuente de alimentación USB de Android no es suficiente para el dispositivo conectado. Pregunta relacionada:

CONFIGURACIÓN DEL NÚCLEO

Para usar Ethernet sobre USB (adaptadores o dispositivos similares a módems), el kernel debe construirse con CONFIG_USB_USBNETotras configuraciones como USB_NET_CDCETHER, USB_NET_HUAWEI_CDC_NCM, USB_NET_CDC_MBIMetc. dependiendo del tipo de dispositivo conectado y el protocolo que hable. Preguntas relacionadas:

CAMBIO DE MODO USB Y CARGA DEL MÓDULO KERNEL

Muchos dispositivos de red USB son dispositivos multimodo o biestables . Aparecen como dispositivo de almacenamiento masivo USB (también llamado modo ZeroCD ) cuando se insertan y deben cambiarse al modo Ethernet/PPP. USB_ModeSwitch es una herramienta de Linux comúnmente utilizada para este propósito. Vea aquí algunos detalles de cómo funciona. Debe crear esta herramienta para su dispositivo, o puede descargar este binario para aarch64. Obtenga la base de datos del dispositivo desde aquí .

Para cambiar de modo automáticamente cada vez que el dispositivo está conectado a Android, necesitamos escuchar los uevents USB del kernel , ya sea a través de hotplug helper o un daemon de espacio de usuario (como udeven Linux y ueventden Android). Además, el módulo del kernel también se puede cargar/descargar automáticamente. Estoy definiendo un initservicio aquí para lograr esto, también puede hacerlo manualmente.

Nota: Hay un widget PPP de la aplicación de Android (del desarrollador de USB_ModeSwitch, no tengo afiliación) que maneja el cambio de modo automáticamente y no necesita "módulos de controlador del kernel, la implementación del 'controlador' se basa en la API del host USB de Android" . Usted podría estar interesado en eso también.

# /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

* En caso de hotplug, debe definir políticas personalizadas de SELinux para permitir que el kernel realice cambios (consulte esta respuesta para obtener más detalles).

#!/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

CONFIGURACIÓN DE LA RED

El marco de trabajo de Android tiene un nombre codificado para la interfaz Ethernet ( el valor predeterminado es eth0, eth1, ...). Cada vez que aparece una interfaz Ethernet, su nombre se compara con el valor codificado. Cambiar el nombre de la interfaz después no funciona porque solo se rastrea el nombre de la interfaz proporcionado por el kernel .

Por lo tanto, debe hacer que esta convención de nomenclatura sea coherente entre kernel y AOSP modificando uno de los dos (si es necesario). El nombre proporcionado por el kernel se puede ver usando ipla herramienta (como en su caso, es usb0). Use dumpsyso descompile /system/framework/framework-res.apkusando apktool para ver el valor de AOSP.

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

Tan pronto como aparece una interfaz Ethernet, Android la configura automáticamente, NetworkMonitorvalida la conectividad y ConnectivityServicedesactiva WiFi y datos móviles (si está activado). Otros servicios y componentes involucrados en la configuración incluyen UsbHostManager, EthernetTracker, EthernetNetworkFactory, IpClient.eth0, y .DhcpClientDnsManagerNetd

EthernetService se agregó en Android 5. Antes de eso, AOSP se parcheó para que Ethernet funcionara (por ejemplo, consulte this y this ). Todavía el stock de Android no proporciona configuraciones de GUI para Ethernet, pero algunos desarrolladores de ROM personalizados y OEM sí lo hacen (por ejemplo, vea esto ). EthernetManagerLa clase que se utiliza para establecer y guardar la configuración manual de IP (a /data/misc/ethernet/ipconfig.txt) está oculta . El valor predeterminado es utilizar una configuración codificada (consulte el uso dumpsys etherneten "Configuraciones de IP:") o una configuración proporcionada por DHCP .

CONFIGURACIÓN MANUAL

Es posible que desee realizar una configuración de red manual, por ejemplo, si:

  • El marco de trabajo de Android no configura la interfaz Ethernet (en dispositivos más antiguos o debido a una inconsistencia en el nombre de la interfaz).
  • Desea establecer una dirección IP estática o un servidor DNS diferente.
  • Desea usar Ethernet junto con WiFi o datos móviles, o desea compartir Internet entre cualquiera de estos.

Pero en este caso, la pila de la red Java de Android permanece inactiva, por lo que algunas aplicaciones que dependen de las API de Android pueden no comportarse normalmente. Para obtener detalles relacionados, consulte Conexión a Wi-Fi a través de 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

No olvide establecer los permisos adecuados en .rclos scripts de archivo y shell. Una vez configurado, Ethernet funciona tan pronto como conecta el adaptador USB.

@moderators combínelo con alguna otra pregunta similar si es necesario.
Este parece precisamente el problema al que me enfrento. Pero no puedo entender cómo usbXse cambia el nombre de la interfaz a ethX... ¿Podría proporcionar más detalles?
@ EM90 Creo que ya lo expliqué bien: " Entonces, debe hacer que esta convención de nomenclatura sea consistente entre el kernel y AOSP modificando uno de los dos ". En palabras simples: reconstruya su kernel o la ROM. O " es posible que desee realizar una configuración de red manual si el marco de trabajo de Android no configura la interfaz Ethernet debido a una inconsistencia en el nombre de la interfaz ".
Bueno, gracias. Lo leí con más atención. Si lo entiendo correctamente, puedo usar los scripts anteriores para configurar manualmente la configuración de la red. Probando esos.
+1 ¡Muchas gracias por esta gran respuesta! Realmente hay muchos detalles que son muy difíciles de encontrar en cualquier otro lugar... Si no hubiera encontrado el comentario "Android no usa la tabla principal de forma predeterminada", probablemente habría perdido mucho tiempo tratando de hacer un RNDIS trabajo de conexion ethernet!