Как заставить Ethernet работать на Android через OTG?

Я пытаюсь использовать модем LTE, подключенный к устройству Android 7 через кабель OTG. Ядро распознает устройство и регистрирует его с помощью cdc_ether, но я не могу использовать соединение с устройства. Это потому, что он впоследствии монтируется как USB-накопитель?

Устройство не отображается как устройство в пользовательском интерфейсе Android/строке состояния.

Если я отключу поддержку MTP, то устройство cdc_etherвообще не зарегистрируется.

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

dmesgс отключенным МТР:

[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

Устройство отображается usb0с MAC-адресом, указанным в dmesg.

но я не могу использовать соединение с устройства Как вы пытались его использовать? Android не настроит его (если в некоторые файлы не будет добавлена ​​пользовательская конфигурацияinit).rc, вам придется сделать это вручную. Отображается ли он как сетевой интерфейс (проверьте с помощьюip lилиifconfig)?
спасибо за ответ - я добавил запрошенные журналы - у вас есть пример того, как добавить пользовательскую запись в файлы init.rc? Я могу изменить загрузочный раздел на этом устройстве
Я думаю, usb0это интерфейс. Вы можете подтвердить это, удалив ключ. Вы можете настроить этот интерфейс с помощью ipкоманд (настроить, установить IP, добавить маршрут и т. д.). Но платформа Android не будет знать об этом интерфейсе, поэтому некоторые API будут сообщать об отключении устройства. Android не настраивает и не управляет аппаратными ресурсами напрямую, а через предоставленные поставщиком HAL. Поэтому, если вы хотите добавить новый аппаратный ресурс, вам нужно запустить его HAL как собственный сервис. Платформа Android будет взаимодействовать с этим. Проще говоря, требуется пересборка пользовательского ПЗУ.
У меня есть исходный код для этого устройства, и я собираю ПЗУ / модифицирую его для поддержки модема quectel. Большое спасибо за вашу информацию! usb0 - это интерфейс - он исчезает, когда я его удаляю
Вопросы, связанные с развитием, здесь не по теме. // Android обеспечивает ограниченную поддержку Ethernet. Смотрите это , это , это и это . Если отображается только устройство Mass Storage, а не Ethernet, ваш ключ должен быть флип-флоп устройством, для которого требуется USB_ModeSwitch .
где разрешены вопросы развития? Если я спрошу в SO, меня направят сюда...
У модераторов есть свои ограничения и линия действий. Но вы должны четко указать AMAP, что ваш вопрос ориентирован на развитие. Как и в случае с этим вопросом, похоже, что он связан с конечными пользователями. Но после разговора оказывается ориентированным на развитие. Это может ввести в заблуждение.

Ответы (1)

Существует длинный список вопросов, связанных с Ethernet, но ни один из них не дает исчерпывающего ответа, охватывающего все аспекты. Я обобщаю ваш вопрос, чтобы поделиться своими знаниями об этом.

Вот что вам нужно сделать, чтобы Ethernet работал на Android:

  • Убедитесь, что поддержка OTG доступна
  • Ядро должно быть построено с поддержкой Ethernet (и USB Ethernet)
  • Управление переключением режима USB и загрузкой модуля ядра (если применимо)
  • Заставьте платформу Android выполнить настройку сети или сделайте это вручную

Примечание. Для всего, что описано ниже, требуется рутованное устройство или, по крайней мере, устройство с разблокированным загрузчиком.
Вы должны быть знакомы с интерфейсом командной строки.


ПОДДЕРЖКА ОТГ

Ваше устройство должно иметь возможность работать в режиме USB-хоста. EthernetServiceзапускается только в том случае, если устройство поддерживает функцию USB host ( )android.hardware.usb.host или Ethernet ( android.hardware.ethernet). Вам также может понадобиться использовать USB-концентратор с питанием, если USB-блока питания Android недостаточно для подключенного устройства. Связанный вопрос:

КОНФИГУРАЦИЯ ЯДРА

Чтобы использовать Ethernet через USB (адаптеры или модемоподобные устройства), ядро ​​должно быть собрано с CONFIG_USB_USBNETдругими конфигурациями, такими как USB_NET_CDCETHER, и т. д., в зависимости от типа подключенного устройства и протокола, с которым оно работает USB_NET_HUAWEI_CDC_NCM. USB_NET_CDC_MBIMСвязанные вопросы:

ПЕРЕКЛЮЧАТЕЛЬ РЕЖИМА USB И ЗАГРУЗКА МОДУЛЯ ЯДРА

Многие сетевые USB-устройства являются многорежимными или триггерными устройствами. При подключении они отображаются как запоминающее устройство USB (также называемое режимом ZeroCD ), и их необходимо переключить в режим Ethernet/PPP. USB_ModeSwitch — это инструмент Linux, обычно используемый для этой цели. См. некоторые подробности здесь , как это работает. Вам необходимо собрать этот инструмент для своего устройства или загрузить этот двоичный файл для aarch64. Получите базу данных устройств отсюда .

Чтобы автоматически переключать режим всякий раз, когда устройство подключено к Android, нам нужно прослушивать uevents USB ядра либо через помощник горячего подключения , либо через демон пользовательского пространства (например, udevв Linux и ueventdна Android). Кроме того, модуль ядра также может быть загружен/выгружен автоматически. Я определяю здесь initслужбу для достижения этой цели, вы также можете сделать это вручную.

Примечание. Существует Android-приложение PPP Widget (от разработчика USB_ModeSwitch, я не связан с ним), которое автоматически переключает режимы и не требует «модулей драйвера ядра, реализация драйвера основана на Android USB host API» . Возможно, вас это тоже заинтересует.

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

* В случае горячего подключения вам необходимо определить пользовательские политики SELinux, чтобы ядро ​​могло вносить изменения ( подробности см. в этом ответе ).

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

КОНФИГУРАЦИЯ СЕТИ

Платформа Android имеет жестко заданное имя для интерфейса Ethernet ( по умолчанию , eth0, eth1...). Всякий раз, когда появляется интерфейс Ethernet, его имя сопоставляется с жестко запрограммированным значением. Последующее переименование интерфейса не работает, потому что отслеживается только имя интерфейса , предоставленное ядром .

Таким образом, вам нужно сделать это соглашение об именах согласованным между ядром и AOSP, изменив одно из обоих (при необходимости). Имя, предоставленное ядром, можно увидеть с помощью ipинструмента (как в вашем случае usb0). Используйте dumpsysили декомпилируйте /system/framework/framework-res.apkс помощью apktool , чтобы увидеть значение AOSP.

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

Как только появляется интерфейс Ethernet, Android автоматически настраивает его, NetworkMonitorпроверяет подключение и ConnectivityServiceотключает Wi-Fi и мобильные данные (если они включены). Другие службы и компоненты, участвующие в настройке, включают UsbHostManager, EthernetTracker, , , и .EthernetNetworkFactoryIpClient.eth0DhcpClientDnsManagerNetd

EthernetService был добавлен в Android 5. До этого AOSP был исправлен, чтобы Ethernet работал (например, см. это и это ). Стандартный Android по-прежнему не предоставляет графических настроек для Ethernet, но некоторые разработчики пользовательских ПЗУ и OEM-производители делают это (см., например, это ). EthernetManagerкласс, который используется для установки и сохранения ручной конфигурации IP (до /data/misc/ethernet/ipconfig.txt) , скрыт . По умолчанию используется жестко заданная конфигурация (см. использование dumpsys ethernetв разделе «Конфигурации IP:») или конфигурация, предоставленная DHCP .

РУЧНАЯ КОНФИГУРАЦИЯ

Возможно, вы захотите выполнить настройку сети вручную, например, если:

  • Платформа Android не настраивает интерфейс Ethernet (на старых устройствах или из-за несоответствия имени интерфейса).
  • Вы хотите установить статический IP-адрес или другой DNS-сервер.
  • Вы хотите использовать Ethernet вместе с WiFi или мобильными данными или хотите поделиться Интернетом между любым из них.

Но в этом случае сетевой стек Java Android остается отключенным, поэтому некоторые приложения, зависящие от Android API, могут работать некорректно. Дополнительные сведения см. в разделе «Подключение к WiFi через 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

Не забудьте установить правильные разрешения для .rcфайлов и сценариев оболочки. После настройки Ethernet работает, как только вы подключаете USB-адаптер.

@moderators объединяют его с другим подобным вопросом, если это необходимо.
Кажется, это именно та проблема, с которой я сталкиваюсь. Но я не могу понять, как usbXинтерфейс переименован как ethX... Не могли бы вы предоставить более подробную информацию?
@ EM90 Я думаю, что уже хорошо объяснил: « Итак, вам нужно сделать это соглашение об именах согласованным между ядром и AOSP , изменив одно из обоих ». Проще говоря: пересоберите ядро ​​или ПЗУ. Или « вы можете захотеть выполнить настройку сети вручную, если платформа Android не настраивает интерфейс Ethernet из-за несоответствия имени интерфейса ».
Хорошо спасибо. Я прочитал его более внимательно. Если я правильно понимаю, я могу использовать скрипты выше, чтобы вручную настроить параметры сети. Пробую те.
+1 Большое спасибо за этот отличный ответ! Действительно много деталей, которые очень трудно найти где-либо еще... Если бы я не нашел замечание «Android не использует основную таблицу по умолчанию», я бы, вероятно, потратил столько времени на попытки сделать RNDIS Ethernet-соединение работает!