162306a36Sopenharmony_ci============================== 262306a36Sopenharmony_ciGSM 0710 tty multiplexor HOWTO 362306a36Sopenharmony_ci============================== 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci.. contents:: :local: 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciThis line discipline implements the GSM 07.10 multiplexing protocol 862306a36Sopenharmony_cidetailed in the following 3GPP document: 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciThis document give some hints on how to use this driver with GPRS and 3G 1362306a36Sopenharmony_cimodems connected to a physical serial port. 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciHow to use it 1662306a36Sopenharmony_ci============= 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciConfig Initiator 1962306a36Sopenharmony_ci---------------- 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#. Initialize the modem in 0710 mux mode (usually ``AT+CMUX=`` command) through 2262306a36Sopenharmony_ci its serial port. Depending on the modem used, you can pass more or less 2362306a36Sopenharmony_ci parameters to this command. 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#. Switch the serial line to using the n_gsm line discipline by using 2662306a36Sopenharmony_ci ``TIOCSETD`` ioctl. 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#. Configure the mux using ``GSMIOC_GETCONF_EXT``/``GSMIOC_SETCONF_EXT`` ioctl if needed. 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults. 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#. Obtain base gsmtty number for the used serial port. 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci Major parts of the initialization program 3762306a36Sopenharmony_ci (a good starting point is util-linux-ng/sys-utils/ldattach.c):: 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci #include <stdio.h> 4062306a36Sopenharmony_ci #include <stdint.h> 4162306a36Sopenharmony_ci #include <linux/gsmmux.h> 4262306a36Sopenharmony_ci #include <linux/tty.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci #define DEFAULT_SPEED B115200 4562306a36Sopenharmony_ci #define SERIAL_PORT /dev/ttyS0 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci int ldisc = N_GSM0710; 4862306a36Sopenharmony_ci struct gsm_config c; 4962306a36Sopenharmony_ci struct gsm_config_ext ce; 5062306a36Sopenharmony_ci struct gsm_dlci_config dc; 5162306a36Sopenharmony_ci struct termios configuration; 5262306a36Sopenharmony_ci uint32_t first; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci /* open the serial port connected to the modem */ 5562306a36Sopenharmony_ci fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* configure the serial port : speed, flow control ... */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /* send the AT commands to switch the modem to CMUX mode 6062306a36Sopenharmony_ci and check that it's successful (should return OK) */ 6162306a36Sopenharmony_ci write(fd, "AT+CMUX=0\r", 10); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* experience showed that some modems need some time before 6462306a36Sopenharmony_ci being able to answer to the first MUX packet so a delay 6562306a36Sopenharmony_ci may be needed here in some case */ 6662306a36Sopenharmony_ci sleep(3); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci /* use n_gsm line discipline */ 6962306a36Sopenharmony_ci ioctl(fd, TIOCSETD, &ldisc); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* get n_gsm extended configuration */ 7262306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETCONF_EXT, &ce); 7362306a36Sopenharmony_ci /* use keep-alive once every 5s for modem connection supervision */ 7462306a36Sopenharmony_ci ce.keep_alive = 500; 7562306a36Sopenharmony_ci /* set the new extended configuration */ 7662306a36Sopenharmony_ci ioctl(fd, GSMIOC_SETCONF_EXT, &ce); 7762306a36Sopenharmony_ci /* get n_gsm configuration */ 7862306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETCONF, &c); 7962306a36Sopenharmony_ci /* we are initiator and need encoding 0 (basic) */ 8062306a36Sopenharmony_ci c.initiator = 1; 8162306a36Sopenharmony_ci c.encapsulation = 0; 8262306a36Sopenharmony_ci /* our modem defaults to a maximum size of 127 bytes */ 8362306a36Sopenharmony_ci c.mru = 127; 8462306a36Sopenharmony_ci c.mtu = 127; 8562306a36Sopenharmony_ci /* set the new configuration */ 8662306a36Sopenharmony_ci ioctl(fd, GSMIOC_SETCONF, &c); 8762306a36Sopenharmony_ci /* get DLC 1 configuration */ 8862306a36Sopenharmony_ci dc.channel = 1; 8962306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); 9062306a36Sopenharmony_ci /* the first user channel gets a higher priority */ 9162306a36Sopenharmony_ci dc.priority = 1; 9262306a36Sopenharmony_ci /* set the new DLC 1 specific configuration */ 9362306a36Sopenharmony_ci ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); 9462306a36Sopenharmony_ci /* get first gsmtty device node */ 9562306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETFIRST, &first); 9662306a36Sopenharmony_ci printf("first muxed line: /dev/gsmtty%i\n", first); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* and wait for ever to keep the line discipline enabled */ 9962306a36Sopenharmony_ci daemon(0,0); 10062306a36Sopenharmony_ci pause(); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#. Use these devices as plain serial ports. 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci For example, it's possible: 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci - to use *gnokii* to send / receive SMS on ``ttygsm1`` 10762306a36Sopenharmony_ci - to use *ppp* to establish a datalink on ``ttygsm2`` 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#. First close all virtual ports before closing the physical port. 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci Note that after closing the physical port the modem is still in multiplexing 11262306a36Sopenharmony_ci mode. This may prevent a successful re-opening of the port later. To avoid 11362306a36Sopenharmony_ci this situation either reset the modem if your hardware allows that or send 11462306a36Sopenharmony_ci a disconnect command frame manually before initializing the multiplexing mode 11562306a36Sopenharmony_ci for the second time. The byte sequence for the disconnect command frame is:: 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciConfig Requester 12062306a36Sopenharmony_ci---------------- 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode 12362306a36Sopenharmony_ci config. 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#. Switch the serial line to using the *n_gsm* line discipline by using 12662306a36Sopenharmony_ci ``TIOCSETD`` ioctl. 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci#. Configure the mux using ``GSMIOC_GETCONF_EXT``/``GSMIOC_SETCONF_EXT`` 12962306a36Sopenharmony_ci ioctl if needed. 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#. Configure DLCs using ``GSMIOC_GETCONF_DLCI``/``GSMIOC_SETCONF_DLCI`` ioctl for non-defaults. 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#. Obtain base gsmtty number for the used serial port:: 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci #include <stdio.h> 13862306a36Sopenharmony_ci #include <stdint.h> 13962306a36Sopenharmony_ci #include <linux/gsmmux.h> 14062306a36Sopenharmony_ci #include <linux/tty.h> 14162306a36Sopenharmony_ci #define DEFAULT_SPEED B115200 14262306a36Sopenharmony_ci #define SERIAL_PORT /dev/ttyS0 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci int ldisc = N_GSM0710; 14562306a36Sopenharmony_ci struct gsm_config c; 14662306a36Sopenharmony_ci struct gsm_config_ext ce; 14762306a36Sopenharmony_ci struct gsm_dlci_config dc; 14862306a36Sopenharmony_ci struct termios configuration; 14962306a36Sopenharmony_ci uint32_t first; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* open the serial port */ 15262306a36Sopenharmony_ci fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci /* configure the serial port : speed, flow control ... */ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* get serial data and check "AT+CMUX=command" parameter ... */ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* use n_gsm line discipline */ 15962306a36Sopenharmony_ci ioctl(fd, TIOCSETD, &ldisc); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci /* get n_gsm extended configuration */ 16262306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETCONF_EXT, &ce); 16362306a36Sopenharmony_ci /* use keep-alive once every 5s for peer connection supervision */ 16462306a36Sopenharmony_ci ce.keep_alive = 500; 16562306a36Sopenharmony_ci /* set the new extended configuration */ 16662306a36Sopenharmony_ci ioctl(fd, GSMIOC_SETCONF_EXT, &ce); 16762306a36Sopenharmony_ci /* get n_gsm configuration */ 16862306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETCONF, &c); 16962306a36Sopenharmony_ci /* we are requester and need encoding 0 (basic) */ 17062306a36Sopenharmony_ci c.initiator = 0; 17162306a36Sopenharmony_ci c.encapsulation = 0; 17262306a36Sopenharmony_ci /* our modem defaults to a maximum size of 127 bytes */ 17362306a36Sopenharmony_ci c.mru = 127; 17462306a36Sopenharmony_ci c.mtu = 127; 17562306a36Sopenharmony_ci /* set the new configuration */ 17662306a36Sopenharmony_ci ioctl(fd, GSMIOC_SETCONF, &c); 17762306a36Sopenharmony_ci /* get DLC 1 configuration */ 17862306a36Sopenharmony_ci dc.channel = 1; 17962306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); 18062306a36Sopenharmony_ci /* the first user channel gets a higher priority */ 18162306a36Sopenharmony_ci dc.priority = 1; 18262306a36Sopenharmony_ci /* set the new DLC 1 specific configuration */ 18362306a36Sopenharmony_ci ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); 18462306a36Sopenharmony_ci /* get first gsmtty device node */ 18562306a36Sopenharmony_ci ioctl(fd, GSMIOC_GETFIRST, &first); 18662306a36Sopenharmony_ci printf("first muxed line: /dev/gsmtty%i\n", first); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* and wait for ever to keep the line discipline enabled */ 18962306a36Sopenharmony_ci daemon(0,0); 19062306a36Sopenharmony_ci pause(); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci11-03-08 - Eric Bénard - <eric@eukrea.com> 193