GSM 0710 tty 多路复用器 HOWTO¶
此行规程实现了以下 3GPP 文档中详细说明的 GSM 07.10 多路复用协议
本文档提供了一些关于如何将此驱动程序与连接到物理串行端口的 GPRS 和 3G 调制解调器一起使用的提示。
如何使用它¶
配置发起者¶
通过调制解调器的串行端口,将调制解调器初始化为 0710 多路复用模式(通常是
AT+CMUX=
命令)。根据使用的调制解调器,您可以向此命令传递或多或少的参数。通过使用
TIOCSETD
ioctl 将串行线路切换为使用 n_gsm 行规程。如果需要,使用
GSMIOC_GETCONF_EXT
/GSMIOC_SETCONF_EXT
ioctl 配置多路复用器。使用
GSMIOC_GETCONF
/GSMIOC_SETCONF
ioctl 配置多路复用器。对于非默认值,使用
GSMIOC_GETCONF_DLCI
/GSMIOC_SETCONF_DLCI
ioctl 配置 DLC。获取所用串行端口的基本 gsmtty 编号。
初始化程序的主要部分(一个好的起点是 util-linux-ng/sys-utils/ldattach.c)
#include <stdio.h> #include <stdint.h> #include <linux/gsmmux.h> #include <linux/tty.h> #define DEFAULT_SPEED B115200 #define SERIAL_PORT /dev/ttyS0 int ldisc = N_GSM0710; struct gsm_config c; struct gsm_config_ext ce; struct gsm_dlci_config dc; struct termios configuration; uint32_t first; /* open the serial port connected to the modem */ fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); /* configure the serial port : speed, flow control ... */ /* send the AT commands to switch the modem to CMUX mode and check that it's successful (should return OK) */ write(fd, "AT+CMUX=0\r", 10); /* experience showed that some modems need some time before being able to answer to the first MUX packet so a delay may be needed here in some case */ sleep(3); /* use n_gsm line discipline */ ioctl(fd, TIOCSETD, &ldisc); /* get n_gsm extended configuration */ ioctl(fd, GSMIOC_GETCONF_EXT, &ce); /* use keep-alive once every 5s for modem connection supervision */ ce.keep_alive = 500; /* set the new extended configuration */ ioctl(fd, GSMIOC_SETCONF_EXT, &ce); /* get n_gsm configuration */ ioctl(fd, GSMIOC_GETCONF, &c); /* we are initiator and need encoding 0 (basic) */ c.initiator = 1; c.encapsulation = 0; /* our modem defaults to a maximum size of 127 bytes */ c.mru = 127; c.mtu = 127; /* set the new configuration */ ioctl(fd, GSMIOC_SETCONF, &c); /* get DLC 1 configuration */ dc.channel = 1; ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); /* the first user channel gets a higher priority */ dc.priority = 1; /* set the new DLC 1 specific configuration */ ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); /* get first gsmtty device node */ ioctl(fd, GSMIOC_GETFIRST, &first); printf("first muxed line: /dev/gsmtty%i\n", first); /* and wait for ever to keep the line discipline enabled */ daemon(0,0); pause();
将这些设备用作普通的串行端口。
例如,可以
使用 gnokii 在
ttygsm1
上发送/接收 SMS使用 ppp 在
ttygsm2
上建立数据链路
在关闭物理端口之前,首先关闭所有虚拟端口。
请注意,关闭物理端口后,调制解调器仍处于多路复用模式。这可能会阻止稍后成功重新打开端口。为避免这种情况,如果您的硬件允许,请重置调制解调器,或者在第二次初始化多路复用模式之前手动发送断开连接命令帧。断开连接命令帧的字节序列是
0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9
配置请求者¶
通过其串行端口接收
AT+CMUX=
命令,初始化多路复用模式配置。通过使用
TIOCSETD
ioctl 将串行线路切换为使用 *n_gsm* 行规程。如果需要,使用
GSMIOC_GETCONF_EXT
/GSMIOC_SETCONF_EXT
ioctl 配置多路复用器。使用
GSMIOC_GETCONF
/GSMIOC_SETCONF
ioctl 配置多路复用器。对于非默认值,使用
GSMIOC_GETCONF_DLCI
/GSMIOC_SETCONF_DLCI
ioctl 配置 DLC。获取所用串行端口的基本 gsmtty 编号
#include <stdio.h> #include <stdint.h> #include <linux/gsmmux.h> #include <linux/tty.h> #define DEFAULT_SPEED B115200 #define SERIAL_PORT /dev/ttyS0 int ldisc = N_GSM0710; struct gsm_config c; struct gsm_config_ext ce; struct gsm_dlci_config dc; struct termios configuration; uint32_t first; /* open the serial port */ fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); /* configure the serial port : speed, flow control ... */ /* get serial data and check "AT+CMUX=command" parameter ... */ /* use n_gsm line discipline */ ioctl(fd, TIOCSETD, &ldisc); /* get n_gsm extended configuration */ ioctl(fd, GSMIOC_GETCONF_EXT, &ce); /* use keep-alive once every 5s for peer connection supervision */ ce.keep_alive = 500; /* set the new extended configuration */ ioctl(fd, GSMIOC_SETCONF_EXT, &ce); /* get n_gsm configuration */ ioctl(fd, GSMIOC_GETCONF, &c); /* we are requester and need encoding 0 (basic) */ c.initiator = 0; c.encapsulation = 0; /* our modem defaults to a maximum size of 127 bytes */ c.mru = 127; c.mtu = 127; /* set the new configuration */ ioctl(fd, GSMIOC_SETCONF, &c); /* get DLC 1 configuration */ dc.channel = 1; ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); /* the first user channel gets a higher priority */ dc.priority = 1; /* set the new DLC 1 specific configuration */ ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); /* get first gsmtty device node */ ioctl(fd, GSMIOC_GETFIRST, &first); printf("first muxed line: /dev/gsmtty%i\n", first); /* and wait for ever to keep the line discipline enabled */ daemon(0,0); pause();
11-03-08 - Eric Bénard - <eric@eukrea.com>