Index: configure.ac
===================================================================
--- configure.ac	(revision 4804)
+++ configure.ac	(working copy)
@@ -409,6 +409,21 @@
   AC_MSG_RESULT([no])
 fi
 
+dnl check for OceanServer support
+AC_ARG_ENABLE(oceanserver,
+  AC_HELP_STRING([--enable-oceanserver],
+                 [enable OceanServer support]),
+  [ac_oceanserver=$enableval], [ac_oceanserver=no])
+AC_MSG_CHECKING([for OceanServer support])
+if test x"$ac_oceanserver" = "xyes"; then
+    ac_nmea=yes
+    AC_MSG_RESULT([yes])
+	AC_DEFINE([OCEANSERVER_ENABLE], 1, [OceanServer support])
+	AC_DEFINE([NMEA_ENABLE], 1, [OceanServer requires NMEA support])
+else
+  AC_MSG_RESULT([no])
+fi
+
 dnl check for UBX support
 AC_ARG_ENABLE(ubx,
   AC_HELP_STRING([--disable-ubx],
@@ -759,6 +774,7 @@
 echo "Trimble TSIP            : $ac_tsip"
 echo "Tripmate                : $ac_tripmate"
 echo "True North              : $ac_tnt"
+echo "OceanServer             : $ac_oceanserver"
 echo "UBX                     : $ac_ubx"
 echo "GPSclock                : $ac_gpsclock"
 dnl Below this line are non-protocol switches
@@ -793,6 +809,7 @@
     x"$ac_rtcm104v2" = "xno" -a \
     x"$ac_sirf" = "xno" -a \
     x"$ac_tnt" = "xno" -a \
+    x"$ac_oceanserver" = "xno" -a \
     x"$ac_tripmate" = "xno" -a \
     x"$ac_tsip" = "xno" -a \
     x"$ac_ubx" = "xno"; then
Index: drivers.c
===================================================================
--- drivers.c	(revision 4804)
+++ drivers.c	(working copy)
@@ -737,6 +737,153 @@
     .cycle	    = 20,		/* updates per second */
 };
 #endif
+#ifdef OCEANSERVER_ENABLE
+/**************************************************************************
+ * OceanServer - Digital Compass, OS5000 Series
+ *
+ * More info: http://www.ocean-server.com/download/OS5000_Compass_Manual.pdf
+ *
+ * This is a digital compass which uses magnetometers to measure the
+ * strength of the earth's magnetic field. Based on these measurements
+ * it provides a compass heading using NMEA formatted output strings.
+ * This is useful to supplement the heading provided by another GPS
+ * unit. A GPS heading is unreliable at slow speed or no speed.
+ *
+ **************************************************************************/
+
+enum {
+#include "packet_states.h"
+};
+
+static int oceanserver_send(int fd, const char *fmt, ... )
+{
+    int status;
+    char buf[BUFSIZ];
+    va_list ap;
+
+    va_start(ap, fmt) ;
+    (void)vsnprintf(buf, sizeof(buf)-5, fmt, ap);
+    va_end(ap);
+    strlcat(buf, "", BUFSIZ);
+    status = (int)write(fd, buf, strlen(buf));
+    tcdrain(fd);
+    if (status == (int)strlen(buf)) {
+	gpsd_report(LOG_IO, "=> GPS: %s\n", buf);
+	return status;
+    } else {
+	gpsd_report(LOG_WARN, "=> GPS: %s FAILED\n", buf);
+	return -1;
+    }
+}
+
+#ifdef ALLOW_RECONFIGURE
+static void oceanserver_configure(struct gps_device_t *session, unsigned int seq)
+{
+    if (seq == 0){
+	(void)oceanserver_send(session->gpsdata.gps_fd, "2\n");
+	(void)oceanserver_send(session->gpsdata.gps_fd, "X4096 ");
+    }
+}
+#endif /* ALLOW_RECONFIGURE */
+
+#define OCEANSERVER_SNIFF_RETRIES       100
+
+static int oceanserver_packet_sniff(struct gps_device_t *session)
+{
+    unsigned int n, count = 0;
+
+    gpsd_report(LOG_RAW, "oceanserver_packet_sniff begins\n");
+    for (n = 0; n < OCEANSERVER_SNIFF_RETRIES; n++)
+    {
+      count = 0;
+      (void)oceanserver_send(session->gpsdata.gps_fd, "V\n");
+      if (ioctl(session->gpsdata.gps_fd, FIONREAD, &count) < 0)
+	  return BAD_PACKET;
+      if (count == 0) {
+	  //int delay = 10000000000.0 / session->gpsdata.baudrate;
+	  //gpsd_report(LOG_RAW, "usleep(%d)\n", delay);
+	  //usleep(delay);
+	  gpsd_report(LOG_RAW, "sleep(1)\n");
+	  (void)sleep(1);
+      } else if (generic_get(session) >= 0) {
+	if((session->packet.type == NMEA_PACKET)&&(session->packet.state == NMEA_RECOGNIZED))
+	{
+	  gpsd_report(LOG_RAW, "oceanserver_packet_sniff returns %d\n",session->packet.type);
+	  return session->packet.type;
+	}
+      }
+    }
+
+    gpsd_report(LOG_RAW, "oceanserver_packet_sniff found no packet\n");
+    return BAD_PACKET;
+}
+
+/*
+ * The OceanServer compass has different output modes
+ * we would like to make it talk in a NMEA like protocol
+ */
+static bool oceanserver_probe(struct gps_device_t *session)
+{
+  unsigned int *ip;
+#ifdef FIXED_PORT_SPEED
+    /* just the one fixed port speed... */
+    static unsigned int rates[] = {FIXED_PORT_SPEED};
+#else /* FIXED_PORT_SPEED not defined */
+  /* The supported baud rates */
+  static unsigned int rates[] = {4800, 9600, 14400, 19200, 38400, 57600, 115200 };
+#endif /* FIXED_PORT_SPEED defined */
+
+  gpsd_report(LOG_PROG, "Probing OceanServer Compass\n");
+
+  /*
+   * Only block until we get at least one character, whatever the
+   * third arg of read(2) says.
+   */
+  /*@ ignore @*/
+  memset(session->ttyset.c_cc,0,sizeof(session->ttyset.c_cc));
+  session->ttyset.c_cc[VMIN] = 1;
+  /*@ end @*/
+
+  session->ttyset.c_cflag &= ~(PARENB | PARODD | CRTSCTS);
+  session->ttyset.c_cflag |= CREAD | CLOCAL;
+  session->ttyset.c_iflag = session->ttyset.c_oflag = session->ttyset.c_lflag = (tcflag_t) 0;
+
+  session->baudindex = 0;
+  for (ip = rates; ip < rates + sizeof(rates)/sizeof(rates[0]); ip++)
+      if (ip == rates || *ip != rates[0])
+      {
+	  gpsd_report(LOG_PROG, "hunting at speed %d\n", *ip);
+	  gpsd_set_speed(session, *ip, 'N',1);
+	  if (oceanserver_packet_sniff(session) != BAD_PACKET)
+	      return true;
+      }
+  return false;
+}
+
+struct gps_type_t oceanServer = {
+    .type_name      = "OceanServer Digital Compas OS5000", /* full name of type */
+    .trigger	    = " OS5000",
+    .channels       = 0,		/* not an actual GPS at all */
+    .probe_wakeup   = NULL,		/* this will become a real method */
+    .probe_detect   = oceanserver_probe,/* probe by sending ID query */
+    .probe_subtype  = NULL,		/* probe for True North Digital Compass */
+#ifdef ALLOW_RECONFIGURE
+    .configurator   = oceanserver_configure, /* no setting changes */
+#endif /* ALLOW_RECONFIGURE */
+    .get_packet     = generic_get,	/* how to get a packet */
+    .parse_packet   = nmea_parse_input,	/* how to interpret a packet */
+    .rtcm_writer    = NULL,		/* Don't send */
+    .speed_switcher = NULL,		/* no speed switcher */
+    .mode_switcher  = NULL,		/* no mode switcher */
+    .rate_switcher  = NULL,		/* no wrapup */
+    .cycle_chars    = -1,		/* not relevant, no rate switch */
+#ifdef ALLOW_RECONFIGURE
+    .revert	    = NULL,		/* no setting-reversion method */
+#endif /* ALLOW_RECONFIGURE */
+    .wrapup	    = NULL,		/* no wrapup */
+    .cycle	    = 20,		/* updates per second */
+};
+#endif
 #ifdef RTCM104V2_ENABLE
 /**************************************************************************
  *
@@ -912,6 +1059,9 @@
 #ifdef TNT_ENABLE
     &trueNorth,
 #endif /* TSIP_ENABLE */
+#ifdef OCEANSERVER_ENABLE
+    &oceanServer,
+#endif /* OCEANSERVER_ENABLE */
 #ifdef EVERMORE_ENABLE
     &evermore_binary,
 #endif /* EVERMORE_ENABLE */
Index: nmea_parse.c
===================================================================
--- nmea_parse.c	(revision 4804)
+++ nmea_parse.c	(working copy)
@@ -599,6 +599,65 @@
 }
 #endif /* TNT_ENABLE */
 
+#ifdef OCEANSERVER_ENABLE
+static gps_mask_t processOHPR(int c UNUSED, char *field[], struct gps_device_t *session)
+{
+    /*
+     * Proprietary sentence for OceanServer Magnetic Compass.
+
+	OHPR,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x,x.x*hh<cr><lf>
+	Fields in order:
+	1. Azimuth
+	2. Pitch Angle
+	3. Roll Angle
+	4. Temperature
+	5. Depth (feet)
+	6. Magnetic Vector Length
+	7-9. 3 axis Magnetic Field readings x,y,z
+	10. Acceleration Vector Length
+	11-13. 3 axis Acceleration Readings x,y,z
+	14. Reserved
+	15-16. 2 axis Gyro Output, X,y
+	17. Reserved
+	18. Reserved
+	*hh	  mandatory nmea_checksum
+     */
+    gps_mask_t mask;
+    mask = ONLINE_SET;
+
+    //gpsd_zero_satellites(&session->gpsdata);
+
+    /*
+     * Heading maps to track.
+     * Pitch maps to climb.
+     * Roll maps to speed.
+     * Depth maps to altitude.
+     */
+    session->gpsdata.fix.time = timestamp();
+    session->gpsdata.fix.track = atof(field[1]);
+    session->gpsdata.fix.climb = atof(field[2]);
+    session->gpsdata.fix.speed = atof(field[3]);
+    session->gpsdata.temperature = atof(field[4]);
+    session->gpsdata.fix.altitude = atof(field[5]);
+    session->gpsdata.magnetic_length = atof(field[6]);
+    session->gpsdata.magnetic_field_x = atof(field[7]);
+    session->gpsdata.magnetic_field_y = atof(field[8]);
+    session->gpsdata.magnetic_field_z = atof(field[9]);
+    session->gpsdata.acceleration_length = atof(field[10]);
+    session->gpsdata.acceleration_field_x = atof(field[11]);
+    session->gpsdata.acceleration_field_y = atof(field[12]);
+    session->gpsdata.acceleration_field_z = atof(field[13]);
+    session->gpsdata.gyro_output_x = atof(field[15]);
+    session->gpsdata.gyro_output_y = atof(field[16]);
+    session->gpsdata.fix.mode = MODE_3D;
+    mask |= (STATUS_SET | MODE_SET | TRACK_SET | SPEED_SET | CLIMB_SET | ALTITUDE_SET);
+    session->gpsdata.status = STATUS_FIX;	/* could be DGPS_FIX */
+
+    gpsd_report(LOG_RAW, "Heading %lf.\n", session->gpsdata.fix.track);
+    return mask;
+}
+#endif /* OCEANSERVER_ENABLE */
+
 #ifdef ASHTECH_ENABLE
 static gps_mask_t processPASHR(int c UNUSED, char *field[], struct gps_device_t *session)
 {
@@ -705,7 +764,10 @@
 #endif /* TNT_ENABLE */
 #ifdef ASHTECH_ENABLE
 	{"PASHR", 3,	processPASHR},	/* general handler for Ashtech */
-#endif /* TNT_ENABLE */
+#endif /* ASHTECH_ENABLE */
+#ifdef OCEANSERVER_ENABLE
+	{"OHPR", 18,	processOHPR},
+#endif /* OCEANSERVER_ENABLE */
     };
     volatile unsigned char buf[NMEA_MAX+1];
 
Index: gps.h
===================================================================
--- gps.h	(revision 4804)
+++ gps.h	(working copy)
@@ -531,12 +531,28 @@
 #define SAT_FIX_USED	0x40		/* used for position fix */
 #endif
 
+#ifdef TNT_ENABLE
     /* compass status -- TrueNorth (and any similar) devices only */
     char headingStatus;
     char pitchStatus;
     char rollStatus;
     double horzField;   /* Magnitude of horizontal magnetic field */
+#endif
 
+#ifdef OCEANSERVER_ENABLE
+    double magnetic_length; /* unitvector sqrt(x^2 + y^2 +z^2) */
+    double magnetic_field_x;
+    double magnetic_field_y;
+    double magnetic_field_z;
+    double acceleration_length; /* unitvector sqrt(x^2 + y^2 +z^2) */
+    double acceleration_field_x;
+    double acceleration_field_y;
+    double acceleration_field_z;
+    double gyro_output_x;
+    double gyro_output_y;
+    double temperature;
+#endif
+
     /* where and what gpsd thinks the device is */
     char	gps_device[PATH_MAX];	/* only valid if non-null. */
     char	*gps_id;	/* only valid if non-null. */