UMGUM.COM (лучше) 

Linux + ZTE MF180 + K-Cell ( Запуск GSM модема ZTE MF180 (под брендом "Kcell Connect") в среде Debian Linux Squeeze. )

12 июля 2012  (обновлено 31 января 2015)

OS: Linux Debian Sqeeze.
Hard: "USB modem ZTE MF180" (он же: MF110/180/626/627/628/628/636), выпускаемый в Казахстане под брендом "Kcell Connect".
Applications: UDEV, eject, wvdial.

Задача: обеспечить работу устройства в режиме "подключил и просто пользуешься".

Запускать в работу будем USB модем "ZTE 180" (устройство очень неоднозначно определяется на разных этапах работы с ним; насколько я понял, на начальных этапах у разработчиков программного обеспечения "открытого мира" информации о чипах этого вида модемов было маловато и каждый именовал их "как придётся" - отсюда разнобой в идентификации). Устройство поддерживает стандарты "HSDPA/HSUPA/UMTS" в частотных диапазонах 850/1900/2100 МГц и "GSM/GPRS/EDGE" в частотных диапазонах 850/900/1800/1900 МГц. Пока разбирался, как взаимодействовать с модемом, начитался страстей о "залоченных" на провайдера и просто "сырых" устройствах, сопряжение которых с Linux целесообразно разве-что в качестве упражнения, предваряющего игры разряда "садо-мазо". Печаль прошла мимо, мне попался модем от казахстанского оператора связи "K-Cell", абсолютно чистое, не осквернённое прошивками местного разлива, и работоспособное устройство, готовое служить потребителю в самых произвольных конфигурациях.

В модемах этой серии применяется технология "ZeroCD", суть которой заключается в том, что при подключении устройство сперва представляется как виртуальный "CD-диск", на котором находятся драйвера и сопутствующее программное обеспечение, а функционал модема становится доступен на втором этапе, когда виртуальному "CD-диску" отдаётся команда "извлечения" - контроллер устройства воспринимает это как сигнал для инициализации второго, основного, уровня функциональности, модема как такового. В качестве приятного дополнения на борту устройства размещён слот для карты памяти формата "microSD" (опытным путём мною установлено, что 4-ёх гигабайтные карты поддерживаются), он становится доступен одновременно с модемом.

Для работы всех функций устройства, ядро операционной системы должно быть собрано в комплекте с драйверами "usbserial", "usb-storage" и "sr_mod". Впрочем, начиная с ядра где-то в районе 2.6.28 модем отлично поддерживается драйвером "option" (попросту говоря, для "mainstream" дистрибутивов Linux с 2011 года никаких телодвижений по обеспечению поддержки модема предпринимать не нужно), а без драйвера "usb-storage" рабочую станцию даже как-то странно себе представить.

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


Устанавливаем необходимые пакеты:

# aptitude install usbutils eject ppp wvdial

Подключаем устройство и смотрим, что нам на это скажет система:

# dmesg

....
usb 1-4: New USB device found, idVendor=19d2, idProduct=2000
....
usb 1-4: Product: ZTE WCDMA Technologies MSM
usb 1-4: Manufacturer: ZTE,Incorporated
....
scsi7 : SCSI emulation for USB Mass Storage devices
....
scsi 7:0:0:0: CD-ROM ZTE USB SCSI CD-ROM 2.31 PQ: 0 ANSI: 2
....
ISO 9660 Extensions: Microsoft Joliet Level 1
....

# lsusb

....
Bus 001 Device 006: ID 19d2:2000 ONDA Communication S.p.A. ZTE MF627/MF628/MF628+/MF636+ HSDPA/HSUPA
....

Ага, как я упоминал, нам повезло и устройство вполне корректно опознаётся. Если в окружении рабочего стола настроено автоматическое монтирование "томов" подключаемых носителей информации, можно будет убедится, что да, виртуальный "CD-диск" доступен:

# df -h

Filesystem Size Used Avail Use% Mounted on
....
/dev/sr1    26M  26M     0 100% /media/Kcell Connect
....

Интересующимся чем-нибудь ещё, кроме телевизора, пива и чипсов, настоятельно рекомендую полистать код скриптов управления устройством в среде Linux, имеющихся на виртуальном носителе. Это действительно познавательно. Всё, что мне понадобилось для настройки модема, я почерпнул от-туда, а вовсе не из статеек, коими полон интернет. Справедливости ради, должен заметить, что не менее полезную, но уже ненужную информацию, я вычитал на ресурсах сообществ "Gentoo" и, отчасти, "ArchLinux".

Ранее многие сталкивались с проблемой неправильного определения модема ядром Linux. Приходилось вручную выгружать какие-то модули, загружать другие, с параметрами, разнящимися от устройства к устройству, от модели к модели. Для автоматизации и упрощения процесса даже написали специальную программу "usb_modeswitch", которая, ориентируясь на собственную базу данных о USB-модемах, не полностью поддерживаемых ядром, помогало их инициировать. В моём случае не понадобилось применения "usb_modeswitch" - оборудование отлично отработало "изъятие" виртуального "CD-диска" с помощью утилиты "eject", произвело смену режима с вещанием новых идентификаторов, которые корректно опозналось системой. Для примера, вот моё ядро, на котором проводились эксперименты:

# uname -a

Linux 2.6.32-5-amd64 x86_64 GNU/Linux

Итак, "извлекаем" виртуальный "CD-диск", пока в ручном режиме:

# eject /dev/sr1

Смотрим, как на это отреагировала система:

# dmesg

....
usb 1-4: USB disconnect, address 6
....
usb 1-4: New USB device found, idVendor=19d2, idProduct=0031
....
usb 1-4: Product: ZTE WCDMA Technologies MSM
usb 1-4: Manufacturer: ZTE,Incorporated
usb 1-4: SerialNumber: MF1800KCLD010000
....
USB Serial support registered for GSM modem (1-port)
option 1-4:1.0: GSM modem (1-port) converter detected
usb 1-4: GSM modem (1-port) converter now attached to ttyUSB0
option 1-4:1.1: GSM modem (1-port) converter detected
usb 1-4: GSM modem (1-port) converter now attached to ttyUSB1
option 1-4:1.3: GSM modem (1-port) converter detected
usb 1-4: GSM modem (1-port) converter now attached to ttyUSB2
usbcore: registered new interface driver option
option: v0.7.2:USB Driver for GSM modems
....
scsi8 : SCSI emulation for USB Mass Storage devices
usb-storage: device scan complete
scsi 8:0:0:0: Direct-Access ZTE MMC Storage 2.31 PQ: 0 ANSI: 2
....
sd 8:0:0:0: [sdc] Attached SCSI removable disk
....

Отлично, устройство заявило о наличии трёх последовательных интерфейсов, управление которыми было передано драйверу "option", и одного интерфейса накопителя, управление которым было передано драйверу "usb-storage".

Обращаю внимание на смену идентификаторов устройства, зафиксировать которую можно в выводе утилит "dmesg" или "lsusb", например:

# lsusb

....
Bus 001 Device 007: ID 19d2:0031 ONDA Communication S.p.A. ZTE MF110/MF636
....

Важно понимать, что с точки зрения непосредственных эксплуататоров, то есть операционной системы и приложений пользователя, устройства с различающимися идентификаторами и есть разные, несмотря на то, что для нас они выглядят единым целым. Как минимум это означает, что после того, как мы отработали с одним "устройством", нужно не забыть переключится на "появившееся".

В ручном режиме "извлекать" виртуальный "CD-диск" неприемлемо. Прежде чем перейти к освоению функционала GSM-модема напишем правило для подсистемы UDEV, которое в момент подключения устройства прикрепит к нему статическое символическое имя и, ориентируясь на него-же, отдаст команду стороннему приложению "извлечь" ненужное нам виртуальное устройство:

# touch /etc/udev/rules.d/99-gsm-mobile-net.rules

BUS=="usb", SUBSYSTEM=="block", ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="2000", SYMLINK+="ZTECD", RUN+="/usr/bin/eject /dev/ZTECD"
....

После сохранения файла даём подсистеме UDEV команду перечитать и принять новую конфигурацию:

# udevadm control --reload-rules

Любителям оптимизаций рекомендую ознакомится с выводом утилит UDEV, генерируемым во время или после подключения устройств:

# udevadm monitor --property
# udevadm info --query=env --name=/dev/ttyUSB0
# udevadm info --attribute-walk --name=/dev/ttyUSB0

В принципе, после того, как функционал GSM-модема стал доступным, ничего не мешает нам запустить программу-дозвонщик и подключится к интернету. Смущает то, что последовательных интерфейсов у устройства обнаружилось три штуки. За каким из них модем, и как сделать так, чтобы приложение уровня пользователя могло использовать его в заданной раз и навсегда конфигурации, не гадая, на каком из множества (у меня порой до пяти-семи штук) последовательных портов разместился целевой преобразователь? Важно помнить о том, что стек USB не поддерживает абсолютной адресации вообще и все устройства становятся доступны по уникальному порядковому номеру (типа индекса), выдаваемого в соответствии с последовательностью подключения. В общем, сегодня модем может работать на порту "ttyUSB2", а завтра переехать на порт "ttyUSB5", если перед ним успели включить иное устройство.

Приступим ко второму этапу вживления модема в Linux. Прежде всего более детально ознакомимся с тем, что за "порты" предлагает нам устройство для взаимодействия. Вероятно, как это принято в свежеиспечённых дистрибутивах Linux, файловая система отображения состояния USB устройств не смонтирована. Сделаем это вручную, один раз, для ознакомления:

# mount -t usbfs none /proc/bus/usb

Найдём в файле перечня всех доступных USB устройств наше:

# cat /proc/bus/usb/devices

....
T:  Bus=01 Lev=01 Prnt=01 Port=03 Cnt=02 Dev#= 23 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=19d2 ProdID=0031 Rev= 0.00
S:  Manufacturer=ZTE,Incorporated
S:  Product=ZTE WCDMA Technologies MSM
S:  SerialNumber=MF1800KCLD010000
C:* #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=500mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
E:  Ad=84(I) Atr=03(Int.) MxPS=  64 Ivl=2ms
E:  Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms
....

Что-то мы уже знаем, а о чём-то догадывались. Понятно, что каждый интерфейс устройства предназначен для определённой цели. Так, если идти от востребованного, третий интерфейс является стандартным преобразователем "USB-Serial", к нему подключается драйвер "usbserial" или "option", и через этот интерфейс осуществляется основной обмен данными. Второй интерфейс предоставляет доступ к встроенному слоту для карты памяти "microSD", к данному интерфейсу подключается драйвер "usb-storage". Нулевой и первый интерфейсы предназначены для отправки управляющих последовательностей, речь о которых пойдёт в другой заметке. Я так уверено пишу здесь о назначении интерфейсов не потому, что прочитал об этом в документации, а на основании массы косвенных сведений, которые в сумме позволяют делать достаточно обоснованные выводы. Собственно, далее опросив интерфейсы, мы сами найдём "зерно":

Выше мы уже видели, что для взаимодействия с устройством были созданы три последовательных порта. Вот они:

# ls -l /dev/ttyUSB*

crw-r

1 root dialout 188, 0 Jul  8 14:06 /dev/ttyUSB0
crw-r

1 root dialout 188, 1 Jul  8 14:06 /dev/ttyUSB1
crw-r

1 root dialout 188, 2 Jul  8 14:06 /dev/ttyUSB2

Зашлём в каждый из них управляющую последовательность, отреагировать на которую сочтёт честью любой модем:

# echo -e "AT+CSQ\r" > /dev/ttyUSB0
# echo -e "AT+CSQ\r" > /dev/ttyUSB1
# echo -e "AT+CSQ\r" > /dev/ttyUSB2

Сразу после этого попробуем прочитать ответы: (работа утилиты "cat" прерывается комбинацией "Ctrl+C"):

# cat /dev/ttyUSB0

"Нулевой" интерфейс ввод принимает, но ничего не отдаёт.

# cat /dev/ttyUSB1

AT+CSQ

+CSQ: 10,99

OK

AT+CSQ

+CSQ: 10,99

OK

"Первый" интерфейс вернул ответ как на свой запрос, так и на тот, что был адресован "нулевому".

# cat /dev/ttyUSB2

AT+CSQ
+CSQ: 10,99

OK

"Второй" интерфейс принял ввод и ответил на него, без сюрпризов.

Я мыслю так, что использовать в качестве модема интерфейсы, которые или не отвечают на запросы или добавляют к ответу то, чего от них не простили, не самая лучшая идея. Надо полагать, что непосредственно GSM-модем располагается за "вторым" интерфейсом, а "нулевой" и "первый" предназначены для вспомогательных операций.

Как я упоминал выше, существует вероятность того, что при подключении устройство получит в своё распоряжение адреса в диапазоне ином от "0-2". Чтобы дать возможность приложениям формировать и использовать статические конфигурации с абсолютными именами устройств, зададим правила подсистеме UDEV, в соответствии с которыми при подключении устройства портам интерфейсов будут выдаваться символические имена:

# cat /etc/udev/rules.d/99-gsm-mobile-net.rules

....
# Внимание: строка "ATTRS{modalias}" содержит идентификаторы в верхнем регистре, в отличии от других мест, где они указываются в нижнем.

SUBSYSTEMS=="usb", ACTION=="add", ATTRS{modalias}=="usb:v19D2p0031*", KERNEL=="ttyUSB*", ATTRS{bInterfaceNumber}=="00", ATTRS{bInterfaceProtocol}=="ff", SYMLINK+="zte_mf180_sp"

SUBSYSTEMS=="usb", ACTION=="add", ATTRS{modalias}=="usb:v19D2p0031*", KERNEL=="ttyUSB*", ATTRS{bInterfaceNumber}=="01", ATTRS{bInterfaceProtocol}=="ff", SYMLINK+="zte_mf180_aux"

SUBSYSTEMS=="usb", ACTION=="add", ATTRS{modalias}=="usb:v19D2p0031*", KERNEL=="ttyUSB*", ATTRS{bInterfaceNumber}=="03", ATTRS{bInterfaceProtocol}=="ff", SYMLINK+="zte_mf180_gsm"
....

После сохранения файла даём подсистеме UDEV перечитать и принять изменившуюся конфигурацию:

# udevadm control --reload-rules

Физически отключим и вновь подключим устройство и убедимся, что старания наши не были тщетны:

# ls -l /dev/zte*

lrwxrwxrwx 1 root root 7 Jul 12 12:21 /dev/zte_mf180_aux -> ttyUSB1
lrwxrwxrwx 1 root root 7 Jul 12 12:21 /dev/zte_mf180_gsm -> ttyUSB2
lrwxrwxrwx 1 root root 7 Jul 12 12:21 /dev/zte_mf180_sp -> ttyUSB0

Сомневающимся напомню, что "мягкая ссылка" просто указывает на файл, доступ к которому регламентируется отдельно (грубо говоря - по ссылка может ходить кто угодно, а вот получить доступ к цели - нет). Потому смотрим, кто имеет доступ к последнему узлу цепочки ссылок и обеспечиваем приложениям уровня пользователя возможность работы с ним. В частности, в нашем случае с последовательными портами устройства могут работать пользователь "root" и члены группы "dialout".

Третий этап, подключения к интернету, самый простой. Каждый может использовать то приложение, которое ему более по вкусу. Я продемонстрирую самый простой вариант, с утилитой "интеллектуального дозвона" wvdial.

Создаём минимально достаточный конфигурационный файл:

# touch /usr/local/etc/wvdial-gsm-kcell.conf

[Dialer Defaults]
Init1 = ATZ
Init2 = AT+CGDCONT=1,"IP","Internet"
Abort on No Dialtone = off
Modem Type = Analog Modem
Baud = 460800
Stupid Mode = 1
New PPPD = yes
Modem = /dev/zte_mf180_gsm
ISDN = 0
Phone = *99#
Password = internet
Username = internet

Важно иметь в виду то, что "чистый" GSM-модем, не встроенный в телефон, "не гудит" и не подаёт сигналов, по которым ранее было принято косвенно определять готовность линии к работе; модем лишь отвечает на прямые запросы о состоянии. В связи с этим нельзя, на начальном этапе подключения, использовать опции типа "ABORT NO CARRIER".

Запускаем приложение, указывая ему путь к конфигурационному файлу:

# wvdial --config=/usr/local/etc/wvdial-gsm-kcell.conf

--> WvDial: Internet dialer version 1.60
--> Cannot get information for serial port.
--> Initializing modem.
--> Sending: ATZ
ATZ
OK
--> Sending: AT+CGDCONT=1,"IP","Internet"
AT+CGDCONT=1,"IP","Internet"
OK
--> Modem initialized.
--> Sending: ATDT*99#
--> Waiting for carrier.
ATDT*99#
CONNECT 3600000
--> Carrier detected.  Starting PPP immediately.
....
--> Using interface ppp1
....
--> local  IP address 10.93.198.69
--> remote IP address 10.64.64.65
--> primary   DNS address 2.78.43.17
--> secondary DNS address 2.78.43.18
^CCaught signal 2:  Attempting to exit gracefully...
--> Terminating on signal 15
--> Connect time 0.7 minutes.
....
--> Disconnecting at ....

У меня уже было установлено одно PPP-соединение, моё основное, потому "дозвонщик" создал новое, с порядковым номером большим на единицу:

# ifconfig

....
ppp1  Link encap:Point-to-Point Protocol
  inet addr:10.93.198.69  P-t-P:10.64.64.65  Mask:255.255.255.255
  UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
  RX packets:10 errors:0 dropped:0 overruns:0 frame:0
  TX packets:29 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:3
  RX bytes:214 (214.0 B)  TX bytes:1830 (1.7 KiB)
....

Пробуем на вкус интернет:

# ping ya.ru

64 bytes from www.yandex.ru (93.158.134.203): icmp_req=1 ttl=54 time=255 ms
64 bytes from www.yandex.ru (93.158.134.203): icmp_req=2 ttl=54 time=255 ms
64 bytes from www.yandex.ru (93.158.134.203): icmp_req=3 ttl=54 time=255 ms
64 bytes from www.yandex.ru (93.158.134.203): icmp_req=4 ttl=54 time=259 ms
....

Задержки пакетов в 200-300 миллисекунд не радуют, конечно, но это лучше, чем "интернет от Bee-Line", где 1500-4000 миллисекунд ожидания ответа не редкость.

На этом настройку USB-модема "ZTE MF180" для работы в среде Linux можно считать законченной.

Как я уже упоминал, в устройство интегрирован слот для "карт памяти" формата "microSD". Я сразу воткнул туда карточку на 4 Гигабайта. Удобно, знаете-ли, направлять туда загрузки, не переживая, что встроенный в "нетбук" SSD вырабатывает ресурс на множестве мелких операций записи.

Однако, продающиеся в магазинах карты памяти форматированы начиная с 63-го сектора, в лучших традициях давно почивших версий "MS Windows"; для современных операционных систем, ведущих запись блоками по 512, 1024, 4096 байт, особенно на устройства, которые изначально имеют физику далёкую от дисков прошлого, это просто глупо. Потому, первым делом переразмечаем карту памяти, выравнивая начало раздела по границе блоков физического носителя (собственно, выравнивание сделает за нас утилита разметки, была-бы только она достаточно актуальной):

# fdisk -cu /dev/sdX

Command: d
Selected partition 1

Command: n
Command action
  e   extended
  p   primary partition (1-4)
p
Partition number (1-4): 1
First sector (2048-7882751, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-7882751, default 7882751):
Using default value 7882751

Command: w
The partition table has been altered!

Calling ioctl() to re-read partition table.
....
Syncing disks.

Форматируем вновь созданный раздел:

# mkfs.vfat -v -n ZTE_4G /dev/sdX1

....
Auto-selecting FAT32 for large filesystem
....
Volume ID is ...., volume label ZTE_4G.

В качестве последнего штриха я бы закрепил соответствующими UDEV-правилами символические ссылки за "флешкой", интегрированной в устройство:

# cat /etc/udev/rules.d/99-gsm-mobile-net.rules

....
# Именование носителя информации, "диска" как такового
BUS=="usb", SUBSYSTEM=="block", KERNEL=="sd*", ACTION=="add", ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0031", ATTR{removable}=="1", SYMLINK+="zte_mf180_SD"

# Именование первого (именно первого, с номером "1") раздела
BUS=="usb", SUBSYSTEM=="block", KERNEL=="sd*", ACTION=="add", ATTRS{idVendor}=="19d2", ATTRS{idProduct}=="0031", ATTR{partition}=="1", SYMLINK+="zte_mf180_4G"
....

После сохранения файла даём подсистеме UDEV перечитать и принять изменившуюся конфигурацию:

# udevadm control --reload-rules

Теперь, после подключения устройства, мы сможем обращаться к "флешке" по постоянному символическому имени (это не особо востребовано, но бывает полезно):

# ls -l /dev/zte*

lrwxrwxrwx 1 root root .... /dev/zte_mf180_SD -> sdd
lrwxrwxrwx 1 root root .... /dev/zte_mf180_4G -> sdb1


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )