GSM 0710 tty 多路複用器 HOWTO

此線路規程實現了以下 3GPP 文件中詳細介紹的 GSM 07.10 多路複用協議

本文件提供了一些關於如何將此驅動程式與連線到物理序列埠的 GPRS 和 3G 調變解調器一起使用的提示。

如何使用它

配置啟動器

  1. 透過其序列埠將調變解調器初始化為 0710 mux 模式(通常是 AT+CMUX= 命令)。 根據所使用的調變解調器,您可以將或多或少的引數傳遞給此命令。

  2. 透過使用 TIOCSETD ioctl 將序列線路切換為使用 n_gsm 線路規程。

  3. 如果需要,使用 GSMIOC_GETCONF_EXT/GSMIOC_SETCONF_EXT ioctl 配置 mux。

  4. 使用 GSMIOC_GETCONF/GSMIOC_SETCONF ioctl 配置 mux。

  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. 將這些裝置用作普通序列埠。

    例如,可能

    • 使用 *gnokii* 在 ttygsm1 上傳送/接收 SMS

    • 使用 *ppp* 在 ttygsm2 上建立資料鏈路

  8. 在關閉物理埠之前,首先關閉所有虛擬埠。

    請注意,關閉物理埠後,調變解調器仍處於多路複用模式。 這可能會阻止以後成功重新開啟埠。 為了避免這種情況,如果您的硬體允許,請重置調變解調器,或者在第二次初始化多路複用模式之前手動傳送斷開連線命令幀。 斷開連線命令幀的位元組序列為

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

配置請求者

  1. 透過其序列埠接收 AT+CMUX= 命令,初始化 mux 模式配置。

  2. 透過使用 TIOCSETD ioctl 將序列線路切換為使用 *n_gsm* 線路規程。

  3. 如果需要,使用 GSMIOC_GETCONF_EXT/GSMIOC_SETCONF_EXT ioctl 配置 mux。

  4. 使用 GSMIOC_GETCONF/GSMIOC_SETCONF ioctl 配置 mux。

  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>