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