Documentation/driver-api/tty/n_gsm.rst GitHub 원문 ↗

Linux 6.18.37 · Driver API

GSM 0710 tty multiplexor HOWTO

n_gsm line discipline으로 GSM 07.10 multiplexing을 구성하는 initiator·requester ioctl 절차와 가상 serial port 종료 방법을 설명하는 한국어 전문 번역입니다.

Source pathDocumentation/driver-api/tty/n_gsm.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

n_gsm.rst:1-192

`n_gsm`은 한 물리 serial port 위에 여러 GSM 07.10 channel을 구성합니다. initiator는 `AT+CMUX=`를 보내고 `c.initiator = 1`을, requester는 command를 받고 `c.initiator = 0`을 사용합니다. 두 역할 모두 확장·기본·DLCI 설정과 첫 gsmtty 조회를 수행하며, 종료할 때는 가상 포트를 먼저 닫고 modem의 mux 상태를 정리해야 합니다.

문서 구성
원문 줄핵심 내용
1-17프로토콜과 대상 modem
18-37Initiator 설정 단계
38-100Initiator 코드와 설정값
101-118가상 포트 사용·종료
119-135Requester 설정 단계
136-190Requester 코드와 역할 차이
191-192기여 정보

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ==============================
2 GSM 0710 tty multiplexor HOWTO
3 ==============================
4
5 .. contents:: :local:
6
7 This line discipline implements the GSM 07.10 multiplexing protocol
8 detailed in the following 3GPP document:
9
10 https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
11
12 This document give some hints on how to use this driver with GPRS and 3G
13 modems connected to a physical serial port.
14
15 How to use it
16 =============
17
18 Config Initiator
19 ----------------
20
21 #. Initialize the modem in 0710 mux mode (usually ``AT+CMUX=`` command) through
22 its serial port. Depending on the modem used, you can pass more or less
23 parameters to this command.
24
25 #. Switch the serial line to using the n_gsm line discipline by using
26 ``TIOCSETD`` ioctl.
27
28 #. Configure the mux using ``GSMIOC_GETCONF_EXT``/``GSMIOC_SETCONF_EXT`` ioctl if needed.
29
30 #. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
31
32 #. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults.
33
34 #. Obtain base gsmtty number for the used serial port.
35
36 Major parts of the initialization program
37 (a good starting point is util-linux-ng/sys-utils/ldattach.c)::
38
39 #include <stdio.h>
40 #include <stdint.h>
41 #include <linux/gsmmux.h>
42 #include <linux/tty.h>
43
44 #define DEFAULT_SPEED B115200
45 #define SERIAL_PORT /dev/ttyS0
46
47 int ldisc = N_GSM0710;
48 struct gsm_config c;
49 struct gsm_config_ext ce;
50 struct gsm_dlci_config dc;
51 struct termios configuration;
52 uint32_t first;
53
54 /* open the serial port connected to the modem */
55 fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
56
57 /* configure the serial port : speed, flow control ... */
58
59 /* send the AT commands to switch the modem to CMUX mode
60 and check that it's successful (should return OK) */
61 write(fd, "AT+CMUX=0\r", 10);
62
63 /* experience showed that some modems need some time before
64 being able to answer to the first MUX packet so a delay
65 may be needed here in some case */
66 sleep(3);
67
68 /* use n_gsm line discipline */
69 ioctl(fd, TIOCSETD, &ldisc);
70
71 /* get n_gsm extended configuration */
72 ioctl(fd, GSMIOC_GETCONF_EXT, &ce);
73 /* use keep-alive once every 5s for modem connection supervision */
74 ce.keep_alive = 500;
75 /* set the new extended configuration */
76 ioctl(fd, GSMIOC_SETCONF_EXT, &ce);
77 /* get n_gsm configuration */
78 ioctl(fd, GSMIOC_GETCONF, &c);
79 /* we are initiator and need encoding 0 (basic) */
80 c.initiator = 1;
81 c.encapsulation = 0;
82 /* our modem defaults to a maximum size of 127 bytes */
83 c.mru = 127;
84 c.mtu = 127;
85 /* set the new configuration */
86 ioctl(fd, GSMIOC_SETCONF, &c);
87 /* get DLC 1 configuration */
88 dc.channel = 1;
89 ioctl(fd, GSMIOC_GETCONF_DLCI, &dc);
90 /* the first user channel gets a higher priority */
91 dc.priority = 1;
92 /* set the new DLC 1 specific configuration */
93 ioctl(fd, GSMIOC_SETCONF_DLCI, &dc);
94 /* get first gsmtty device node */
95 ioctl(fd, GSMIOC_GETFIRST, &first);
96 printf("first muxed line: /dev/gsmtty%i\n", first);
97
98 /* and wait for ever to keep the line discipline enabled */
99 daemon(0,0);
100 pause();
101
102 #. Use these devices as plain serial ports.
103
104 For example, it's possible:
105
106 - to use *gnokii* to send / receive SMS on ``ttygsm1``
107 - to use *ppp* to establish a datalink on ``ttygsm2``
108
109 #. First close all virtual ports before closing the physical port.
110
111 Note that after closing the physical port the modem is still in multiplexing
112 mode. This may prevent a successful re-opening of the port later. To avoid
113 this situation either reset the modem if your hardware allows that or send
114 a disconnect command frame manually before initializing the multiplexing mode
115 for the second time. The byte sequence for the disconnect command frame is::
116
117 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9
118
119 Config Requester
120 ----------------
121
122 #. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode
123 config.
124
125 #. Switch the serial line to using the *n_gsm* line discipline by using
126 ``TIOCSETD`` ioctl.
127
128 #. Configure the mux using ``GSMIOC_GETCONF_EXT``/``GSMIOC_SETCONF_EXT``
129 ioctl if needed.
130
131 #. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.
132
133 #. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults.
134
135 #. Obtain base gsmtty number for the used serial port::
136
137 #include <stdio.h>
138 #include <stdint.h>
139 #include <linux/gsmmux.h>
140 #include <linux/tty.h>
141 #define DEFAULT_SPEED B115200
142 #define SERIAL_PORT /dev/ttyS0
143
144 int ldisc = N_GSM0710;
145 struct gsm_config c;
146 struct gsm_config_ext ce;
147 struct gsm_dlci_config dc;
148 struct termios configuration;
149 uint32_t first;
150
151 /* open the serial port */
152 fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
153
154 /* configure the serial port : speed, flow control ... */
155
156 /* get serial data and check "AT+CMUX=command" parameter ... */
157
158 /* use n_gsm line discipline */
159 ioctl(fd, TIOCSETD, &ldisc);
160
161 /* get n_gsm extended configuration */
162 ioctl(fd, GSMIOC_GETCONF_EXT, &ce);
163 /* use keep-alive once every 5s for peer connection supervision */
164 ce.keep_alive = 500;
165 /* set the new extended configuration */
166 ioctl(fd, GSMIOC_SETCONF_EXT, &ce);
167 /* get n_gsm configuration */
168 ioctl(fd, GSMIOC_GETCONF, &c);
169 /* we are requester and need encoding 0 (basic) */
170 c.initiator = 0;
171 c.encapsulation = 0;
172 /* our modem defaults to a maximum size of 127 bytes */
173 c.mru = 127;
174 c.mtu = 127;
175 /* set the new configuration */
176 ioctl(fd, GSMIOC_SETCONF, &c);
177 /* get DLC 1 configuration */
178 dc.channel = 1;
179 ioctl(fd, GSMIOC_GETCONF_DLCI, &dc);
180 /* the first user channel gets a higher priority */
181 dc.priority = 1;
182 /* set the new DLC 1 specific configuration */
183 ioctl(fd, GSMIOC_SETCONF_DLCI, &dc);
184 /* get first gsmtty device node */
185 ioctl(fd, GSMIOC_GETFIRST, &first);
186 printf("first muxed line: /dev/gsmtty%i\n", first);
187
188 /* and wait for ever to keep the line discipline enabled */
189 daemon(0,0);
190 pause();
191
192 11-03-08 - Eric Bénard - <eric@eukrea.com>
193

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

GSM 07.10 TTY multiplexor 개요

1-17

이 line discipline은 아래 3GPP 문서에 정의된 GSM 07.10 multiplexing protocol을 구현합니다.

프로토콜 규격은 `https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip`에서 확인할 수 있습니다. 이 문서는 물리 serial port에 연결한 GPRS 및 3G modem에서 이 드라이버를 사용하는 방법을 안내합니다.

문서 범위
항목내용
구현`n_gsm` line discipline의 GSM 07.10 multiplexing
규격3GPP 07.10 문서
대상물리 serial port에 연결된 GPRS·3G modem

==============================
GSM 0710 tty multiplexor HOWTO
==============================

.. contents:: :local:

This line discipline implements the GSM 07.10 multiplexing protocol
detailed in the following 3GPP document:

        https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip

This document give some hints on how to use this driver with GPRS and 3G
modems connected to a physical serial port.

How to use it
=============

Config Initiator 초기화 절차

18-37

Initiator는 먼저 modem의 serial port를 통해 보통 `AT+CMUX=` command를 보내 0710 mux mode를 초기화합니다. 전달할 수 있는 매개변수의 수와 종류는 modem에 따라 다릅니다.

그 다음 `TIOCSETD` ioctl로 serial line을 `n_gsm` line discipline으로 전환합니다. 필요한 경우 `GSMIOC_GETCONF_EXT`와 `GSMIOC_SETCONF_EXT`로 확장 설정을 조정하고, `GSMIOC_GETCONF`와 `GSMIOC_SETCONF`로 기본 mux 설정을 구성합니다.

기본값과 다른 Data Link Connection Identifier(DLCI)는 `GSMIOC_GETCONF_DLCI`와 `GSMIOC_SETCONF_DLCI`로 설정합니다. 마지막으로 사용 중인 serial port에 할당된 첫 `gsmtty` 번호를 얻습니다. 초기화 프로그램은 `util-linux-ng/sys-utils/ldattach.c`를 좋은 출발점으로 삼을 수 있습니다.

Initiator 설정 순서
`AT+CMUX=`modem을 0710 mux mode로 전환
`TIOCSETD``n_gsm` line discipline 선택
`GSMIOC_*CONF_EXT`확장 mux 설정
`GSMIOC_*CONF`기본 mux 설정
`GSMIOC_*CONF_DLCI`비기본 DLC 설정
`GSMIOC_GETFIRST`base gsmtty 번호 획득

CMUX 진입부터 첫 gsmtty 번호 획득까지의 ioctl 흐름입니다.

Config Initiator
----------------

#. Initialize the modem in 0710 mux mode (usually ``AT+CMUX=`` command) through
   its serial port. Depending on the modem used, you can pass more or less
   parameters to this command.

#. Switch the serial line to using the n_gsm line discipline by using
   ``TIOCSETD`` ioctl.

#. Configure the mux using ``GSMIOC_GETCONF_EXT``/``GSMIOC_SETCONF_EXT`` ioctl if needed.

#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.

#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults.

#. Obtain base gsmtty number for the used serial port.

   Major parts of the initialization program
   (a good starting point is util-linux-ng/sys-utils/ldattach.c)::

Initiator 초기화 코드

38-100

예제는 `stdio.h`, `stdint.h`, `linux/gsmmux.h`, `linux/tty.h`를 포함하고 기본 속도를 `B115200`, serial port를 `/dev/ttyS0`로 정의합니다. `N_GSM0710`, `gsm_config`, `gsm_config_ext`, `gsm_dlci_config`, `termios`, 첫 장치 번호를 담을 `uint32_t` 변수를 준비합니다.

modem에 연결된 serial port를 `O_RDWR | O_NOCTTY | O_NDELAY`로 연 뒤 속도와 flow control을 설정합니다. `AT+CMUX=0 `을 보내고 성공 응답 `OK`를 확인해야 합니다. 일부 modem은 첫 MUX packet에 응답할 준비 시간이 필요하므로 예제는 `sleep(3)` 지연을 둡니다.

`TIOCSETD`로 `n_gsm`을 활성화한 후 확장 설정을 읽어 `ce.keep_alive = 500`으로 지정합니다. 이 값은 modem connection supervision을 위해 5초마다 keep-alive를 사용한다는 뜻이며, 변경한 설정을 `GSMIOC_SETCONF_EXT`로 기록합니다.

기본 설정에서는 이 쪽이 initiator이므로 `c.initiator = 1`, basic encoding을 위해 `c.encapsulation = 0`을 사용합니다. modem의 기본 최대 frame size에 맞춰 `c.mru = 127`, `c.mtu = 127`로 설정하고 `GSMIOC_SETCONF`로 적용합니다.

DLC 1을 읽어 첫 user channel의 우선순위를 높이기 위해 `dc.channel = 1`, `dc.priority = 1`로 설정한 뒤 `GSMIOC_SETCONF_DLCI`로 기록합니다. `GSMIOC_GETFIRST`로 첫 device node 번호를 받아 `/dev/gsmtty%i` 형식으로 출력합니다.

마지막의 `daemon(0,0)`과 `pause()`는 line discipline이 계속 활성화되도록 프로세스를 daemon으로 전환하고 무기한 대기시킵니다.

Initiator 예제의 핵심 설정
필드·호출값·효과
`SERIAL_PORT``/dev/ttyS0`
`write(..., "AT+CMUX=0\r", 10)`modem CMUX mode 요청
`ce.keep_alive`500, 5초 간격 supervision
`c.initiator`1
`c.encapsulation`0, basic encoding
`c.mru` / `c.mtu`127 / 127 bytes
`dc.channel` / `dc.priority`1 / 1
`GSMIOC_GETFIRST`첫 `/dev/gsmtty%i` 번호


#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();

가상 포트 사용과 종료

101-118

생성된 device는 일반 serial port처럼 사용할 수 있습니다. 예를 들어 `gnokii`로 `ttygsm1`에서 SMS를 송수신하거나, `ppp`로 `ttygsm2`에 datalink를 만들 수 있습니다.

물리 port를 닫기 전에 모든 virtual port를 먼저 닫아야 합니다. 물리 port를 닫아도 modem은 multiplexing mode에 남으므로, 나중에 port를 다시 열지 못할 수 있습니다.

재초기화 문제를 피하려면 하드웨어가 허용할 경우 modem을 reset하거나, 두 번째 multiplexing mode 초기화 전에 disconnect command frame을 수동 전송합니다. frame byte sequence는 `0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9`입니다.

안전한 종료와 재연결
`ttygsm*` virtual port 모두 closephysical serial port close
physical port closemodem은 multiplexing mode 유지
재연결 전modem reset 또는 disconnect frame 전송
mux 상태 정리다시 `AT+CMUX=` 초기화

가상 포트부터 닫고 modem의 mux 상태를 명시적으로 정리합니다.


#. Use these devices as plain serial ports.

   For example, it's possible:

   - to use *gnokii* to send / receive SMS on ``ttygsm1``
   - to use *ppp* to establish a datalink on ``ttygsm2``

#. First close all virtual ports before closing the physical port.

   Note that after closing the physical port the modem is still in multiplexing
   mode. This may prevent a successful re-opening of the port later. To avoid
   this situation either reset the modem if your hardware allows that or send
   a disconnect command frame manually before initializing the multiplexing mode
   for the second time. The byte sequence for the disconnect command frame is::

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

Config Requester 초기화 절차

119-135

Requester는 serial port로 `AT+CMUX=` command를 수신하고 그 매개변수에 따라 mux mode 설정을 초기화합니다. 직접 command를 보내는 initiator와 시작 방향이 반대입니다.

그 이후에는 `TIOCSETD`로 `n_gsm` line discipline을 선택하고, 필요할 때 `GSMIOC_GETCONF_EXT`·`GSMIOC_SETCONF_EXT`로 확장 설정을 구성합니다. `GSMIOC_GETCONF`·`GSMIOC_SETCONF`로 기본 mux 설정을, `GSMIOC_GETCONF_DLCI`·`GSMIOC_SETCONF_DLCI`로 비기본 DLC를 설정한 뒤 base gsmtty 번호를 얻습니다.

Requester 설정 순서
`AT+CMUX=` 수신요청 매개변수로 mux mode 초기화
`TIOCSETD``n_gsm` 선택
extended config기본 config
DLCI configbase gsmtty 번호 획득

peer가 보낸 CMUX 요청을 받은 뒤 initiator와 같은 설정 계층을 적용합니다.

Config Requester
----------------

#. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode
   config.

#. Switch the serial line to using the *n_gsm* line discipline by using
   ``TIOCSETD`` ioctl.

#. Configure the mux using ``GSMIOC_GETCONF_EXT``/``GSMIOC_SETCONF_EXT``
   ioctl if needed.

#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl.

#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults.

#. Obtain base gsmtty number for the used serial port::

Requester 초기화 코드

136-190

Requester 예제도 같은 헤더, `B115200`, `/dev/ttyS0`, `N_GSM0710` 및 설정 구조체를 사용합니다. serial port를 연 뒤 속도와 flow control을 설정하고, 수신한 serial data에서 `AT+CMUX=command` 매개변수를 확인합니다.

`TIOCSETD`로 line discipline을 설정한 뒤 `ce.keep_alive = 500`으로 peer connection supervision용 5초 keep-alive를 적용합니다. 기본 encoding과 frame size도 `c.encapsulation = 0`, `c.mru = 127`, `c.mtu = 127`로 initiator 예제와 같습니다.

역할을 구분하는 핵심은 requester가 `c.initiator = 0`을 설정한다는 점입니다. DLC 1의 우선순위는 동일하게 1로 높이고, `GSMIOC_GETFIRST`로 첫 gsmtty 번호를 출력한 뒤 `daemon(0,0)`과 `pause()`로 line discipline을 유지합니다.

Initiator와 Requester 코드 차이
항목InitiatorRequester
CMUX 시작`AT+CMUX=0\r` 송신`AT+CMUX=` 수신·매개변수 확인
`c.initiator`10
keep-alive500500
encapsulation00
MRU / MTU127 / 127127 / 127
DLC 1 priority11


#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();

문서 기여 정보

191-192

문서 끝에는 `11-03-08 - Eric Bénard - <eric@eukrea.com>` 기여 정보가 기록되어 있습니다.

기여 정보
날짜작성자연락처
11-03-08Eric Bénard`eric@eukrea.com`


11-03-08 - Eric Bénard - <eric@eukrea.com>