I'm currently writing a small tool for a linux router that sets up a wwan (gsm/3g) connection when I plug an appropriate modem into its USB port. When the device is plugged in several ttys are registered and I currently maintain a list of manufacturers and devices and which of their registered ttys is the control / data port.
If possible I want to get rid of this list and find a way to somehow probe the registered ttys directly to check if they are a control port or a data port.
I examined the sourcecode of wvdial and modem-manager to see how these tools detect the right port but was unable to find suitable information. I also tried to look for information in sysfs to distinguish the ports but this wasn't successful either.
You cannot detect this via external means. The common practise is either to setup udev rules for specific modem manufacturer and model. Or you can sequentially connect to each tty and verify via AT command what type of port it is.
In the case of udev rules you can follow this process:
1) Detect modem vid and pid 2) Based on vid/pid create symlinks in /dev/serial/by-id
For example a Sierra Wireless MC8795V modem with vid = 1199 and pid 683c. I know that port 3 is always the AT command channel. Therefore you could create a symlink post-fixed with -AT at the end.
In the case of detecting via AT commands the best and more common approach is to execute the AT command to see if the tty responds at all. You should get an echo back or an OK if your configured your modem not to echo.
For example:
AT
AT
OK
If you get a response this means you found either an AT control port or a PPP port. To check this simply execute a ATI command. If the response contains APP1, APP2, APP3 then you hit a PPP port. Otherwise you found your AT control port.
For example a AT control port:
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
For example a PPP port:
ATI
Sierra Wireless, Incorporated
MC8795V
APP1
OK
A word of warning though. In the case of Sierra Wireless modules they clearly show which port is which. In the case of other manufacturers you'll need to check the USB interface guide to see if it is possible via ATI to take this approach.
I use this script to get Data and Control ports for 3g usb dongle.
#!/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
}
}
Sample outputs:
Connected 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
Connected 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
This works for me:
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
来源:https://stackoverflow.com/questions/5477882/how-to-i-detect-whether-a-tty-belonging-to-a-gsm-3g-modem-is-a-data-or-control-p