GSM 0710 tty 多路复用器 HOWTO

此行规程实现了以下 3GPP 文档中详细说明的 GSM 07.10 多路复用协议

本文档提供了一些关于如何将此驱动程序与连接到物理串行端口的 GPRS 和 3G 调制解调器一起使用的提示。

如何使用它

配置发起者

  1. 通过调制解调器的串行端口,将调制解调器初始化为 0710 多路复用模式(通常是 AT+CMUX= 命令)。根据使用的调制解调器,您可以向此命令传递或多或少的参数。

  2. 通过使用 TIOCSETD ioctl 将串行线路切换为使用 n_gsm 行规程。

  3. 如果需要,使用 GSMIOC_GETCONF_EXT/GSMIOC_SETCONF_EXT ioctl 配置多路复用器。

  4. 使用 GSMIOC_GETCONF/GSMIOC_SETCONF ioctl 配置多路复用器。

  5. 对于非默认值,使用 GSMIOC_GETCONF_DLCI/GSMIOC_SETCONF_DLCI ioctl 配置 DLC。

  6. 获取所用串行端口的基本 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();
    
  7. 将这些设备用作普通的串行端口。

    例如,可以

    • 使用 gnokiittygsm1 上发送/接收 SMS

    • 使用 pppttygsm2 上建立数据链路

  8. 在关闭物理端口之前,首先关闭所有虚拟端口。

    请注意,关闭物理端口后,调制解调器仍处于多路复用模式。这可能会阻止稍后成功重新打开端口。为避免这种情况,如果您的硬件允许,请重置调制解调器,或者在第二次初始化多路复用模式之前手动发送断开连接命令帧。断开连接命令帧的字节序列是

    0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9
    

配置请求者

  1. 通过其串行端口接收 AT+CMUX= 命令,初始化多路复用模式配置。

  2. 通过使用 TIOCSETD ioctl 将串行线路切换为使用 *n_gsm* 行规程。

  3. 如果需要,使用 GSMIOC_GETCONF_EXT/GSMIOC_SETCONF_EXT ioctl 配置多路复用器。

  4. 使用 GSMIOC_GETCONF/GSMIOC_SETCONF ioctl 配置多路复用器。

  5. 对于非默认值,使用 GSMIOC_GETCONF_DLCI/GSMIOC_SETCONF_DLCI ioctl 配置 DLC。

  6. 获取所用串行端口的基本 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>