1 /* line discipline loading daemon
2 * open a serial device and attach a line discipline on it
5 * ldattach GIGASET_M101 /dev/ttyS0
7 * =====================================================================
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 * =====================================================================
21 #include <sys/ioctl.h>
23 #include <sys/types.h>
31 #include "closestream.h"
34 #include <sys/socket.h>
37 #include <linux/tty.h> /* for N_GSM0710 */
40 # include <linux/gsmmux.h> /* Add by guowenxue */
44 unsigned int adaption
;
45 unsigned int encapsulation
;
46 unsigned int initiator
;
55 unsigned int unused
[8]; /* Padding for expansion without
58 # define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config)
59 # define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config)
62 #ifndef N_GIGASET_M101
63 # define N_GIGASET_M101 16
74 #define MAXINTROPARMLEN 32
76 /* attach a line discipline ioctl */
78 # define TIOCSETD 0x5423
88 /* currently supported line disciplines, plus some aliases */
89 static const struct ld_table ld_discs
[] = {
101 { "SYNC_PPP", N_SYNC_PPP
},
102 { "SYNCPPP", N_SYNC_PPP
},
104 { "GIGASET_M101", N_GIGASET_M101
},
105 { "M101", N_GIGASET_M101
},
106 { "GIGASET", N_GIGASET_M101
},
108 { "GSM0710", N_GSM0710
},
112 /* known c_iflag names */
113 static const struct ld_table ld_iflags
[] =
115 { "IGNBRK", IGNBRK
},
116 { "BRKINT", BRKINT
},
117 { "IGNPAR", IGNPAR
},
118 { "PARMRK", PARMRK
},
120 { "ISTRIP", ISTRIP
},
128 { "IMAXBEL", IMAXBEL
},
133 static void dbg(char *fmt
, ...)
144 fprintf(stderr
, "%s: ", program_invocation_short_name
);
145 vfprintf(stderr
, fmt
, args
);
146 fprintf(stderr
, "\n");
153 static int lookup_table(const struct ld_table
*tab
, const char *str
)
155 const struct ld_table
*t
;
157 for (t
= tab
; t
&& t
->name
; t
++)
158 if (!strcasecmp(t
->name
, str
))
163 static void print_table(FILE * out
, const struct ld_table
*tab
)
165 const struct ld_table
*t
;
168 for (t
= tab
, i
= 1; t
&& t
->name
; t
++, i
++) {
169 fprintf(out
, " %-12s", t
->name
);
175 static int parse_iflag(char *str
, int *set_iflag
, int *clr_iflag
)
180 for (s
= strtok(str
, ","); s
!= NULL
; s
= strtok(NULL
, ",")) {
183 if ((iflag
= lookup_table(ld_iflags
, s
)) < 0)
184 iflag
= strtos32_or_err(s
, _("invalid iflag"));
185 if (s
> str
&& *(s
- 1) == '-')
190 dbg("iflag (set/clear): %d/%d", *set_iflag
, *clr_iflag
);
195 static void __attribute__((__noreturn__
)) usage(void)
199 fputs(USAGE_HEADER
, out
);
200 fprintf(out
, _(" %s [options] <ldisc> <device>\n"), program_invocation_short_name
);
202 fputs(USAGE_SEPARATOR
, out
);
203 fputs(_("Attach a line discipline to a serial line.\n"), out
);
205 fputs(USAGE_OPTIONS
, out
);
206 fputs(_(" -d, --debug print verbose messages to stderr\n"), out
);
207 fputs(_(" -s, --speed <value> set serial line speed\n"), out
);
208 fputs(_(" -c, --intro-command <string> intro sent before ldattach\n"), out
);
209 fputs(_(" -p, --pause <seconds> pause between intro and ldattach\n"), out
);
210 fputs(_(" -7, --sevenbits set character size to 7 bits\n"), out
);
211 fputs(_(" -8, --eightbits set character size to 8 bits\n"), out
);
212 fputs(_(" -n, --noparity set parity to none\n"), out
);
213 fputs(_(" -e, --evenparity set parity to even\n"), out
);
214 fputs(_(" -o, --oddparity set parity to odd\n"), out
);
215 fputs(_(" -1, --onestopbit set stop bits to one\n"), out
);
216 fputs(_(" -2, --twostopbits set stop bits to two\n"), out
);
217 fputs(_(" -i, --iflag [-]<iflag> set input mode flag\n"), out
);
219 fputs(USAGE_SEPARATOR
, out
);
220 printf(USAGE_HELP_OPTIONS(25));
222 fputs(_("\nKnown <ldisc> names:\n"), out
);
223 print_table(out
, ld_discs
);
224 fputs(USAGE_SEPARATOR
, out
);
226 fputs(_("\nKnown <iflag> names:\n"), out
);
227 print_table(out
, ld_iflags
);
229 printf(USAGE_MAN_TAIL("ldattach(8)"));
233 static int my_cfsetspeed(struct termios
*ts
, int speed
)
236 * -- cfsetspeed() is able to translate number to Bxxx constants
238 if (cfsetspeed(ts
, speed
) == 0)
241 /* Nonstandard speeds
242 * -- we have to bypass glibc and set the speed manually (because glibc
243 * checks for speed and supports Bxxx bit rates only)...
245 #if _HAVE_STRUCT_TERMIOS_C_ISPEED
246 # define BOTHER 0010000 /* non standard rate */
247 dbg("using non-standard speeds");
248 ts
->c_ospeed
= ts
->c_ispeed
= speed
;
249 ts
->c_cflag
&= ~CBAUD
;
250 ts
->c_cflag
|= BOTHER
;
257 static void handler(int s
)
259 dbg("got SIG %i -> exiting", s
);
263 static void gsm0710_set_conf(int tty_fd
)
267 /* Add by guowenxue */
268 /* get n_gsm configuration */
269 ioctl(tty_fd
, GSMIOC_GETCONF
, &c
);
270 /* we are initiator and need encoding 0 (basic) */
273 /* our modem defaults to a maximum size of 127 bytes */
276 /* set the new configuration */
277 ioctl(tty_fd
, GSMIOC_SETCONF
, &c
);
278 /* Add by guowenxue end*/
281 int main(int argc
, char **argv
)
285 int speed
= 0, bits
= '-', parity
= '-', stop
= '-';
286 int set_iflag
= 0, clr_iflag
= 0;
291 char *introparm
= NULL
;
293 static const struct option opttbl
[] = {
294 {"speed", required_argument
, NULL
, 's'},
295 {"sevenbits", no_argument
, NULL
, '7'},
296 {"eightbits", no_argument
, NULL
, '8'},
297 {"noparity", no_argument
, NULL
, 'n'},
298 {"evenparity", no_argument
, NULL
, 'e'},
299 {"oddparity", no_argument
, NULL
, 'o'},
300 {"onestopbit", no_argument
, NULL
, '1'},
301 {"twostopbits", no_argument
, NULL
, '2'},
302 {"iflag", required_argument
, NULL
, 'i'},
303 {"help", no_argument
, NULL
, 'h'},
304 {"version", no_argument
, NULL
, 'V'},
305 {"debug", no_argument
, NULL
, 'd'},
306 {"intro-command", no_argument
, NULL
, 'c'},
307 {"pause", no_argument
, NULL
, 'p'},
311 signal(SIGKILL
, handler
);
312 signal(SIGINT
, handler
);
314 setlocale(LC_ALL
, "");
315 bindtextdomain(PACKAGE
, LOCALEDIR
);
317 atexit(close_stdout
);
321 errx(EXIT_FAILURE
, _("bad usage"));
324 getopt_long(argc
, argv
, "dhV78neo12s:i:c:p:", opttbl
,
344 speed
= strtos32_or_err(optarg
, _("invalid speed argument"));
347 intropause
= strtou32_or_err(optarg
, _("invalid pause argument"));
349 errx(EXIT_FAILURE
, "invalid pause: %s", optarg
);
355 parse_iflag(optarg
, &set_iflag
, &clr_iflag
);
358 printf(UTIL_LINUX_VERSION
);
363 errtryhelp(EXIT_FAILURE
);
367 if (argc
- optind
!= 2) {
368 warnx(_("not enough arguments"));
369 errtryhelp(EXIT_FAILURE
);
371 /* parse line discipline specification */
372 ldisc
= lookup_table(ld_discs
, argv
[optind
]);
374 ldisc
= strtos32_or_err(argv
[optind
], _("invalid line discipline argument"));
376 /* ldisc specific option settings */
377 if (ldisc
== N_GIGASET_M101
) {
378 /* device specific defaults for line speed and data format */
390 dev
= argv
[optind
+ 1];
391 if ((tty_fd
= open(dev
, O_RDWR
| O_NOCTTY
)) < 0)
392 err(EXIT_FAILURE
, _("cannot open %s"), dev
);
394 errx(EXIT_FAILURE
, _("%s is not a serial line"), dev
);
396 dbg("opened %s", dev
);
398 /* set line speed and format */
399 if (tcgetattr(tty_fd
, &ts
) < 0)
401 _("cannot get terminal attributes for %s"), dev
);
403 if (speed
&& my_cfsetspeed(&ts
, speed
) < 0)
404 errx(EXIT_FAILURE
, _("speed %d unsupported"), speed
);
408 ts
.c_cflag
&= ~CSTOPB
;
411 ts
.c_cflag
|= CSTOPB
;
420 ts
.c_cflag
= (ts
.c_cflag
& ~CSIZE
) | CS7
;
423 ts
.c_cflag
= (ts
.c_cflag
& ~CSIZE
) | CS8
;
432 ts
.c_cflag
&= ~(PARENB
| PARODD
);
435 ts
.c_cflag
|= PARENB
;
436 ts
.c_cflag
&= ~PARODD
;
439 ts
.c_cflag
|= (PARENB
| PARODD
);
447 ts
.c_cflag
|= CREAD
; /* just to be on the safe side */
448 ts
.c_iflag
|= set_iflag
;
449 ts
.c_iflag
&= ~clr_iflag
;
451 if (tcsetattr(tty_fd
, TCSAFLUSH
, &ts
) < 0)
453 _("cannot set terminal attributes for %s"), dev
);
455 dbg("set to raw %d %c%c%c: cflag=0x%x",
456 speed
, bits
, parity
, stop
, ts
.c_cflag
);
458 if (introparm
&& *introparm
)
460 dbg("intro command is '%s'", introparm
);
461 if (write_all(tty_fd
, introparm
, strlen(introparm
)) != 0)
463 _("cannot write intro command to %s"), dev
);
466 dbg("waiting for %d seconds", intropause
);
471 /* Attach the line discipline. */
472 if (ioctl(tty_fd
, TIOCSETD
, &ldisc
) < 0)
473 err(EXIT_FAILURE
, _("cannot set line discipline"));
475 dbg("line discipline set to %d", ldisc
);
477 /* ldisc specific post-attach actions */
478 if (ldisc
== N_GSM0710
)
479 gsm0710_set_conf(tty_fd
);
481 /* Go into background if not in debug mode. */
482 if (!debug
&& daemon(0, 0) < 0)
483 err(EXIT_FAILURE
, _("cannot daemonize"));
485 /* Sleep to keep the line discipline active. */