Added support for NMEA GPS receiver
authorAndreas.Eversberg <jolly@eversberg.eu>
Tue, 10 Aug 2010 19:56:59 +0000 (19:56 +0000)
committerAndreas.Eversberg <jolly@eversberg.eu>
Tue, 10 Aug 2010 19:56:59 +0000 (19:56 +0000)
This early support does not use the received postion, it just dumps it.

Later it can be used to set clock of the phone. Also it can be used
to calculate the location of a BTS.

src/host/layer23/include/osmocom/bb/mobile/gps.h [new file with mode: 0644]
src/host/layer23/src/mobile/Makefile.am
src/host/layer23/src/mobile/app_mobile.c
src/host/layer23/src/mobile/gps.c [new file with mode: 0644]
src/host/layer23/src/mobile/vty_interface.c

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 (file)
index 0000000..a62eab7
--- /dev/null
@@ -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);
+
+
index 5dbda72..055b3c2 100644 (file)
@@ -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
index 4599f99..9a98f89 100644 (file)
@@ -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 (file)
index 0000000..520aff8
--- /dev/null
@@ -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' */
+}
+
+
index 426c0d8..0c20731 100644 (file)
@@ -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);