Как определить, является ли tty, принадлежащий gsm/3g-модему, портом данных или управления?
В настоящее время я пишу небольшой инструмент для маршрутизатора Linux, который устанавливает соединение wwan (gsm/3g), когда я подключаю соответствующий модем к его USB-порту. Когда устройство подключено к сети, несколько ttys зарегистрированы, и я в настоящее время веду список производителей и устройств, и какой из их ttys является портом управления / данных.
Если возможно, я хочу избавиться от этого списка и найти способ как-то напрямую проверить зарегистрированные ttys, чтобы проверить, являются ли они портом управления или портом данных.
Я проверил исходный код wvdial и modem-manager, чтобы увидеть, как эти инструменты обнаруживают правильный порт, но не смогли найти подходящую информацию. Я также пытался найти информацию в sysfs, чтобы различать порты, но это также не увенчалось успехом.
3 ответа
Я использую этот скрипт, чтобы получить данные и порты управления для 3g USB-ключа.
#!/bin/sh
. /usr/share/libubox/jshn.sh
for a in `ls /sys/bus/usb/devices`; do
local vendor product
[ -z "$usb" -a -f /sys/bus/usb/devices/$a/idVendor -a -f /sys/bus/usb/devices/$a/idProduct ] || continue
vendor=$(cat /sys/bus/usb/devices/$a/idVendor)
product=$(cat /sys/bus/usb/devices/$a/idProduct)
echo Vendor $vendor, Product $product
[ -f /lib/network/wwan/$vendor:$product ] && {
usb=/lib/network/wwan/$vendor:$product
devicename=$a
echo usb: $usb devicename: $devicename
}
done
[ -n "$usb" ] && {
local old_cb control data
json_set_namespace wwan old_cb
json_init
json_load "$(cat $usb)"
echo "$(cat $usb)"
json_select
json_get_vars desc control data
json_set_namespace $old_cb
[ -n "$control" -a -n "$data" ] && {
ttys=$(ls -d /sys/bus/usb/devices/$devicename/${devicename}*/tty* | sed "s/.*\///g" | tr "\n" " ")
ctl_device=$(echo $ttys | cut -d" " -f $((control + 1)))
[ -n "$ctl_device" ] && ctl_device=/dev/$ctl_device
dat_device=$(echo $ttys | cut -d" " -f $((data + 1)))
[ -n "$dat_device" ] && dat_device=/dev/$dat_device
echo control_device: $ctl_device, data_device: $dat_device
}
}
Пример выходов:
Подключен ZTE MF667
Vendor 1a40, Product 0101 #this is usb hub
Vendor 19d2, Product 0016
usb: /lib/network/wwan/19d2:0016 devicename: 1-1.2
{
"desc": "ONDA MF110/ZTE",
"control": 1,
"data": 2
}}
control_device: /dev/ttyUSB1, data_device: /dev/ttyUSB2
Подключен Huawei E3131
Vendor 1a40, Product 0101 #this is usb hub
Vendor 12d1, Product 1506
usb: /lib/network/wwan/12d1:1506 devicename: 1-1.2
{
"desc": "Huawei E367/E398",
"control": 2,
"data": 0
}}
control_device: /dev/ttyUSB2, data_device: /dev/ttyUSB0
Вы не можете обнаружить это с помощью внешних средств. Обычной практикой является либо установка правил udev для конкретного производителя и модели модема. Или вы можете последовательно подключиться к каждому tty и проверить через AT-команду, какой это тип порта.
В случае правил udev вы можете следовать этому процессу:
1) Определить модем vid и pid 2) На основе vid/pid создать символические ссылки в /dev/serial/by-id
Например, модем Sierra Wireless MC8795V с vid = 1199 и pid 683c. Я знаю, что порт 3 всегда является каналом AT-команд. Поэтому вы можете создать символьную ссылку с последующим исправлением -AT в конце.
В случае обнаружения с помощью AT-команд лучший и более общий подход состоит в том, чтобы выполнить AT-команду, чтобы увидеть, отвечает ли tty вообще. Вы должны получить ответное эхо или ОК, если ваш модем не настроен на эхо.
Например:
AT
AT
OK
Если вы получили ответ, это означает, что вы нашли порт управления AT или порт PPP. Чтобы проверить это, просто выполните команду ATI. Если ответ содержит APP1, APP2, APP3, вы подключаетесь к порту PPP. В противном случае вы нашли свой порт управления AT.
Например, порт управления AT:
ATI
Manufacturer: Sierra Wireless, Incorporated
Model: MC8795V
Revision: K2_0_7_46AP C:/WS/FW/K2_0_7_46AP/MSM6290/SRC 2010/10/27 22:15:30
IMEI: XXXXXXXXXXXXXXX
IMEI SV: 20
FSN: D9A2160146410
3GPP Release 6
+GCAP: +CGSM,+DS,+ES
OK
Например, порт PPP:
ATI
Sierra Wireless, Incorporated
MC8795V
APP1
OK
Слово предупреждения, хотя. В случае модулей Sierra Wireless они четко показывают, какой порт какой. В случае других производителей вам необходимо проверить руководство по интерфейсу USB, чтобы узнать, можно ли с помощью ATI использовать этот подход.
Это работает для меня:
for device in $(mmcli -L | grep ModemManager | awk '{print $1}'); do
cport=$(mmcli -m $device | awk '/primary port:/{ print $NF }' | tr -d \')
ldevices=($(mmcli -m $device | grep "ports:" | pcregrep -o1 "(\w+) \(at\)"))
dport=$(echo "/dev/${ldevices[@]##$cport}")
[ -c $dport ] && echo $dport
done