diff options
-rw-r--r-- | src/host/layer23/include/osmocom/bb/mobile/gps.h | 33 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/Makefile.am | 2 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/app_mobile.c | 2 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/gps.c | 171 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/vty_interface.c | 76 |
5 files changed, 283 insertions, 1 deletions
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gps.h b/src/host/layer23/include/osmocom/bb/mobile/gps.h new file mode 100644 index 00000000..a62eab77 --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/mobile/gps.h @@ -0,0 +1,33 @@ +/* + * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +struct gps { + uint8_t enable; + char device[32]; + uint32_t baud; +}; + +extern struct gps gps; + +int gps_open(void); +void gps_close(void); + + diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am index 5dbda72a..055b3c2a 100644 --- a/src/host/layer23/src/mobile/Makefile.am +++ b/src/host/layer23/src/mobile/Makefile.am @@ -4,7 +4,7 @@ LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) noinst_LIBRARIES = libmobile.a libmobile_a_SOURCES = gsm322.c gsm48_cc.c gsm48_mm.c gsm48_rr.c \ - mnccms.c settings.c subscriber.c support.c \ + mnccms.c settings.c subscriber.c support.c gps.c \ sysinfo.c transaction.c vty_interface.c bin_PROGRAMS = mobile diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c index 4599f99c..9a98f89f 100644 --- a/src/host/layer23/src/mobile/app_mobile.c +++ b/src/host/layer23/src/mobile/app_mobile.c @@ -34,6 +34,7 @@ #include <osmocom/bb/mobile/gsm48_rr.h> #include <osmocom/bb/mobile/sysinfo.h> #include <osmocom/bb/mobile/vty.h> +#include <osmocom/bb/mobile/gps.h> #include <osmocom/vty/telnet_interface.h> #include <osmocore/msgb.h> @@ -127,6 +128,7 @@ int mobile_exit(struct osmocom_ms *ms) signal(SIGPIPE, SIG_DFL); unregister_signal_handler(SS_L1CTL, &signal_cb, NULL); + gps_close(); gsm322_exit(ms); gsm48_mm_exit(ms); gsm48_rr_exit(ms); diff --git a/src/host/layer23/src/mobile/gps.c b/src/host/layer23/src/mobile/gps.c new file mode 100644 index 00000000..520aff82 --- /dev/null +++ b/src/host/layer23/src/mobile/gps.c @@ -0,0 +1,171 @@ +/* + * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <stdio.h> +#include <sys/file.h> +#include <termios.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +#include <osmocore/utils.h> + +#include <osmocom/bb/common/osmocom_data.h> +#include <osmocom/bb/mobile/gps.h> + +struct gps gps = { + 0, + "/dev/ttyACM0", + 0 +}; + +static struct bsc_fd gps_bfd; +static struct termios gps_termios, gps_old_termios; + +static int gps_line(char *line) +{ + if (!!strncmp(line, "$GPGLL", 6)) + return 0; + line += 7; + if (strlen(line) < 37) + return 0; + line[37] = '\0'; + /* ddmm.mmmm,N,dddmm.mmmm,E,hhmmss.mmm,A */ + + printf("'%s'\n", line); + + return 0; +} + +static int nmea_checksum(char *line) +{ + uint8_t checksum = 0; + + while (*line) { + if (*line == '$') { + line++; + continue; + } + if (*line == '*') + break; + checksum ^= *line++; + } + return (strtoul(line+1, NULL, 16) == checksum); +} + +int gps_cb(struct bsc_fd *bfd, unsigned int what) +{ + char buff[128]; + static char line[128]; + static int lpos = 0; + int i = 0, len; + + len = read(bfd->fd, buff, sizeof(buff)); + if (len <= 0) { + fprintf(stderr, "error reading GPS device (errno=%d)\n", errno); + return len; + } + while(i < len) { + if (buff[i] == 13) { + i++; + continue; + } + if (buff[i] == 10) { + line[lpos] = '\0'; + lpos = 0; + i++; + if (!nmea_checksum(line)) + fprintf(stderr, "NMEA checksum error\n"); + else + gps_line(line); + continue; + } + line[lpos++] = buff[i++]; + if (lpos == sizeof(line)) + lpos--; + } + + return 0; +} + +int gps_open(void) +{ + int baud = 0; + + if (gps_bfd.fd > 0) + return 0; + gps_bfd.data = NULL; + gps_bfd.when = BSC_FD_READ; + gps_bfd.cb = gps_cb; + gps_bfd.fd = open(gps.device, O_RDONLY); + if (gps_bfd.fd < 0) + return gps_bfd.fd; + + switch (gps.baud) { + case 4800: + baud = B4800; break; + case 9600: + baud = B9600; break; + case 19200: + baud = B19200; break; + case 38400: + baud = B38400; break; + case 57600: + baud = B57600; break; + case 115200: + baud = B115200; break; + } + + if (isatty(gps_bfd.fd)) + { + /* get termios */ + tcgetattr(gps_bfd.fd, &gps_old_termios); + tcgetattr(gps_bfd.fd, &gps_termios); + /* set baud */ + if (baud) { + gps_termios.c_cflag |= baud; + cfsetispeed(&gps_termios, baud); + cfsetospeed(&gps_termios, baud); + } + if (tcsetattr(gps_bfd.fd, TCSANOW, &gps_termios)) + printf("Failed to set termios for GPS\n"); + } + + bsc_register_fd(&gps_bfd); + + return 0; +} + +void gps_close(void) +{ + if (gps_bfd.fd <= 0) + return; + + bsc_unregister_fd(&gps_bfd); + + if (isatty(gps_bfd.fd)) + tcsetattr(gps_bfd.fd, TCSANOW, &gps_old_termios); + + close(gps_bfd.fd); + gps_bfd.fd = -1; /* -1 or 0 indicates: 'close' */ +} + + diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c index 426c0d82..0c207316 100644 --- a/src/host/layer23/src/mobile/vty_interface.c +++ b/src/host/layer23/src/mobile/vty_interface.c @@ -32,6 +32,7 @@ #include <osmocom/bb/mobile/mncc.h> #include <osmocom/bb/mobile/transaction.h> #include <osmocom/bb/mobile/vty.h> +#include <osmocom/bb/mobile/gps.h> #include <osmocom/vty/telnet_interface.h> int mncc_call(struct osmocom_ms *ms, char *number); @@ -526,6 +527,68 @@ DEFUN(network_search, network_search_cmd, "network search MS_NAME", return CMD_SUCCESS; } +DEFUN(cfg_gps_enable, cfg_gps_enable_cmd, "gps enable", + "GPS receiver") +{ + if (gps_open()) { + gps.enable = 1; + vty_out(vty, "Failed to open GPS device!%s", VTY_NEWLINE); + return CMD_WARNING; + } + gps.enable = 1; + + return CMD_SUCCESS; +} + +DEFUN(cfg_no_gps_enable, cfg_no_gps_enable_cmd, "no gps enable", + NO_STR "Disable GPS receiver") +{ + if (gps.enable) + gps_close(); + gps.enable = 0; + + return CMD_SUCCESS; +} + +DEFUN(cfg_gps_device, cfg_gps_device_cmd, "gps device DEVICE", + "GPS receiver\nSelect serial device\n" + "Full path of serial device including /dev/") +{ + strncpy(gps.device, argv[0], sizeof(gps.device)); + gps.device[sizeof(gps.device) - 1] = '\0'; + if (gps.enable) { + gps_close(); + if (gps_open()) { + vty_out(vty, "Failed to open GPS device!%s", + VTY_NEWLINE); + return CMD_WARNING; + } + } + + return CMD_SUCCESS; +} + +DEFUN(cfg_gps_baud, cfg_gps_baud_cmd, "gps baudrate " + "(default|4800|""9600|19200|38400|57600|115200)", + "GPS receiver\nSelect baud rate\nDefault, don't modify\n\n\n\n\n\n") +{ + if (argv[0][0] == 'd') + gps.baud = 0; + else + gps.baud = atoi(argv[0]); + if (gps.enable) { + gps_close(); + if (gps_open()) { + gps.enable = 0; + vty_out(vty, "Failed to open GPS device!%s", + VTY_NEWLINE); + return CMD_WARNING; + } + } + + return CMD_SUCCESS; +} + /* per MS config */ DEFUN(cfg_ms, cfg_ms_cmd, "ms MS_NAME", "Select a mobile station to configure\nName of MS (see \"show ms\")") @@ -619,6 +682,14 @@ static int config_write_ms(struct vty *vty) { struct osmocom_ms *ms; + vty_out(vty, "gps device %s%s", gps.device, VTY_NEWLINE); + if (gps.baud) + vty_out(vty, "gps baudrate %d%s", gps.baud, VTY_NEWLINE); + else + vty_out(vty, "gps baudrate default%s", VTY_NEWLINE); + vty_out(vty, "%sgps enable%s", (gps.enable) ? "" : "no ", VTY_NEWLINE); + vty_out(vty, "!%s", VTY_NEWLINE); + llist_for_each_entry(ms, &ms_list, entity) config_write_ms_single(vty, ms); @@ -1079,6 +1150,11 @@ int ms_vty_init(void) install_element(ENABLE_NODE, &call_cmd); install_element(ENABLE_NODE, &call_retr_cmd); + install_element(CONFIG_NODE, &cfg_gps_device_cmd); + install_element(CONFIG_NODE, &cfg_gps_baud_cmd); + install_element(CONFIG_NODE, &cfg_gps_enable_cmd); + install_element(CONFIG_NODE, &cfg_no_gps_enable_cmd); + install_element(CONFIG_NODE, &cfg_ms_cmd); install_element(CONFIG_NODE, &ournode_end_cmd); install_node(&ms_node, config_write_ms); |