Documentation / driver-api / tty / n_gsm.rst


Based on kernel version 6.8. Page generated on 2024-03-11 21:26 EST.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
==============================
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
----------------

#. 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)::

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

#. 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
----------------

#. 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::

        #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>