#include <unistd.h>
#include "c.h"
+#include "all-io.h"
#include "nls.h"
#include "strutils.h"
#include "closestream.h"
+#include <signal.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include <linux/tty.h> /* for N_GSM0710 */
+
+#ifdef LINUX_GSMMUX_H
+# include <linux/gsmmux.h> /* Add by guowenxue */
+#else
+struct gsm_config
+{
+ unsigned int adaption;
+ unsigned int encapsulation;
+ unsigned int initiator;
+ unsigned int t1;
+ unsigned int t2;
+ unsigned int t3;
+ unsigned int n2;
+ unsigned int mru;
+ unsigned int mtu;
+ unsigned int k;
+ unsigned int i;
+ unsigned int unused[8]; /* Padding for expansion without
+ breaking stuff */
+};
+# define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config)
+# define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config)
+#endif
+
#ifndef N_GIGASET_M101
# define N_GIGASET_M101 16
#endif
# define N_PPS 18
#endif
+#ifndef N_GSM0710
+# define N_GSM0710 21
+#endif
+
+#define MAXINTROPARMLEN 32
+
/* attach a line discipline ioctl */
#ifndef TIOCSETD
# define TIOCSETD 0x5423
#endif
-static const char *progname;
static int debug = 0;
struct ld_table {
{ "SYNC_PPP", N_SYNC_PPP },
{ "SYNCPPP", N_SYNC_PPP },
{ "HCI", N_HCI },
- { "PPS", N_PPS },
+ { "GIGASET_M101", N_GIGASET_M101 },
{ "M101", N_GIGASET_M101 },
{ "GIGASET", N_GIGASET_M101 },
- { "GIGASET_M101", N_GIGASET_M101 },
- { NULL, 0 }
+ { "PPS", N_PPS },
+ { "GSM0710", N_GSM0710},
+ { NULL, 0 }
};
/* known c_iflag names */
{ NULL, 0 }
};
-void dbg(char *fmt, ...)
+static void dbg(char *fmt, ...)
{
va_list args;
if (debug == 0)
return;
fflush(NULL);
- fprintf(stderr, "%s: ", program_invocation_short_name);
va_start(args, fmt);
+#ifdef HAVE_VWARNX
+ vwarnx(fmt, args);
+#else
+ fprintf(stderr, "%s: ", program_invocation_short_name);
vfprintf(stderr, fmt, args);
- va_end(args);
fprintf(stderr, "\n");
+#endif
+ va_end(args);
fflush(NULL);
return;
}
int i;
for (t = tab, i = 1; t && t->name; t++, i++) {
- fprintf(out, " %-10s", t->name);
- if (!(i % 6))
+ fprintf(out, " %-12s", t->name);
+ if (!(i % 5))
fputc('\n', out);
}
}
if (*s == '-')
s++;
if ((iflag = lookup_table(ld_iflags, s)) < 0)
- iflag = strtol_or_err(s, _("invalid iflag"));
+ iflag = strtos32_or_err(s, _("invalid iflag"));
if (s > str && *(s - 1) == '-')
*clr_iflag |= iflag;
else
}
-static void __attribute__ ((__noreturn__)) usage(int exitcode)
+static void __attribute__((__noreturn__)) usage(void)
{
- FILE *out = exitcode == EXIT_SUCCESS ? stdout : stderr;
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out, _(" %s [options] <ldisc> <device>\n"), program_invocation_short_name);
- fputs(USAGE_OPTIONS, out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Attach a line discipline to a serial line.\n"), out);
+
+ fputs(USAGE_OPTIONS, out);
fputs(_(" -d, --debug print verbose messages to stderr\n"), out);
fputs(_(" -s, --speed <value> set serial line speed\n"), out);
+ fputs(_(" -c, --intro-command <string> intro sent before ldattach\n"), out);
+ fputs(_(" -p, --pause <seconds> pause between intro and ldattach\n"), out);
fputs(_(" -7, --sevenbits set character size to 7 bits\n"), out);
fputs(_(" -8, --eightbits set character size to 8 bits\n"), out);
fputs(_(" -n, --noparity set parity to none\n"), out);
fputs(_(" -i, --iflag [-]<iflag> set input mode flag\n"), out);
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
+ printf(USAGE_HELP_OPTIONS(25));
+
fputs(_("\nKnown <ldisc> names:\n"), out);
print_table(out, ld_discs);
+ fputs(USAGE_SEPARATOR, out);
+
fputs(_("\nKnown <iflag> names:\n"), out);
print_table(out, ld_iflags);
- fputc('\n', out);
- fprintf(out, USAGE_MAN_TAIL("ldattach(8)"));
- exit(exitcode);
+
+ printf(USAGE_MAN_TAIL("ldattach(8)"));
+ exit(EXIT_SUCCESS);
}
static int my_cfsetspeed(struct termios *ts, int speed)
* -- we have to bypass glibc and set the speed manually (because glibc
* checks for speed and supports Bxxx bit rates only)...
*/
-#ifdef _HAVE_STRUCT_TERMIOS_C_ISPEED
+#if _HAVE_STRUCT_TERMIOS_C_ISPEED
# define BOTHER 0010000 /* non standard rate */
dbg("using non-standard speeds");
ts->c_ospeed = ts->c_ispeed = speed;
#endif
}
+static void handler(int s)
+{
+ dbg("got SIG %i -> exiting", s);
+ exit(EXIT_SUCCESS);
+}
+
+static void gsm0710_set_conf(int tty_fd)
+{
+ struct gsm_config c;
+
+ /* Add by guowenxue */
+ /* get n_gsm configuration */
+ ioctl(tty_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(tty_fd, GSMIOC_SETCONF, &c);
+ /* Add by guowenxue end*/
+}
+
int main(int argc, char **argv)
{
int tty_fd;
int ldisc;
int optc;
char *dev;
+ int intropause = 1;
+ char *introparm = NULL;
+
static const struct option opttbl[] = {
{"speed", required_argument, NULL, 's'},
{"sevenbits", no_argument, NULL, '7'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{"debug", no_argument, NULL, 'd'},
+ {"intro-command", no_argument, NULL, 'c'},
+ {"pause", no_argument, NULL, 'p'},
{NULL, 0, NULL, 0}
};
+ signal(SIGKILL, handler);
+ signal(SIGINT, handler);
+
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- atexit(close_stdout);
+ close_stdout_atexit();
/* parse options */
- progname = program_invocation_short_name;
-
if (argc == 0)
- usage(EXIT_SUCCESS);
+ errx(EXIT_FAILURE, _("bad usage"));
+
while ((optc =
- getopt_long(argc, argv, "dhV78neo12s:i:", opttbl,
+ getopt_long(argc, argv, "dhV78neo12s:i:c:p:", opttbl,
NULL)) >= 0) {
switch (optc) {
case 'd':
parity = optc;
break;
case 's':
- speed = strtol_or_err(optarg, _("invalid speed"));
+ speed = strtos32_or_err(optarg, _("invalid speed argument"));
+ break;
+ case 'p':
+ intropause = strtou32_or_err(optarg, _("invalid pause argument"));
+ if (intropause > 10)
+ errx(EXIT_FAILURE, "invalid pause: %s", optarg);
+ break;
+ case 'c':
+ introparm = optarg;
break;
case 'i':
parse_iflag(optarg, &set_iflag, &clr_iflag);
break;
+
case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
+ print_version(EXIT_SUCCESS);
case 'h':
- usage(EXIT_SUCCESS);
+ usage();
default:
- warnx(_("invalid option"));
- usage(EXIT_FAILURE);
+ errtryhelp(EXIT_FAILURE);
}
}
- if (argc - optind != 2)
- usage(EXIT_FAILURE);
-
+ if (argc - optind != 2) {
+ warnx(_("not enough arguments"));
+ errtryhelp(EXIT_FAILURE);
+ }
/* parse line discipline specification */
ldisc = lookup_table(ld_discs, argv[optind]);
if (ldisc < 0)
- ldisc = strtol_or_err(argv[optind], _("invalid line discipline"));
+ ldisc = strtos32_or_err(argv[optind], _("invalid line discipline argument"));
+
+ /* ldisc specific option settings */
+ if (ldisc == N_GIGASET_M101) {
+ /* device specific defaults for line speed and data format */
+ if (speed == 0)
+ speed = 115200;
+ if (bits == '-')
+ bits = '8';
+ if (parity == '-')
+ parity = 'n';
+ if (stop == '-')
+ stop = '1';
+ }
/* open device */
dev = argv[optind + 1];
dbg("set to raw %d %c%c%c: cflag=0x%x",
speed, bits, parity, stop, ts.c_cflag);
- /* Attach the line discpline. */
+ if (introparm && *introparm)
+ {
+ dbg("intro command is '%s'", introparm);
+ if (write_all(tty_fd, introparm, strlen(introparm)) != 0)
+ err(EXIT_FAILURE,
+ _("cannot write intro command to %s"), dev);
+
+ if (intropause) {
+ dbg("waiting for %d seconds", intropause);
+ sleep(intropause);
+ }
+ }
+
+ /* Attach the line discipline. */
if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0)
err(EXIT_FAILURE, _("cannot set line discipline"));
dbg("line discipline set to %d", ldisc);
+ /* ldisc specific post-attach actions */
+ if (ldisc == N_GSM0710)
+ gsm0710_set_conf(tty_fd);
+
/* Go into background if not in debug mode. */
if (!debug && daemon(0, 0) < 0)
err(EXIT_FAILURE, _("cannot daemonize"));