aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2020-09-18 18:00:50 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2020-10-07 11:39:46 +0000
commit086bd33f18fa79eb239a06e404915f3ba3c20e3f (patch)
tree9c808d123c773b3d13d7fe9fc82121ddefafce29 /include/osmocom
parent87c3afb5a969838446433c6d0d0ece8e9821e2c0 (diff)
add GAD coding for Location Services
GAD, Universal Geographical Area Description: - raw coding for all GAD elements. - SI-units encoding and decoding for Ellipsoid point with uncertainty circle, which I presume is the typical "at most N meters away from cell tower located at X,Y", which corresponds to the TA positioning currently being implemented. - other SI-units GAD element encodings are so far not implemented. Add encoding and decoding tests. In gsm/protocol/gsm_23_032.h are the raw coding structs as defined in 3GPP TS 23.032. In gsm/gad.h are structs carrying consistent units based on meters and degrees, for convenient / less error prone handling of GAD data, and for human readable representations of the GAD data. The separation of the two is desirable because OsmoBSC will receive GAD data from OsmoSMLC on the Lb interface, and pass on this data to the MSC via the A interface. It is better to pass the GAD data as-is without de/encoding. Change-Id: I7a9dd805a91b1ebb6353bde0cd169218acbf223c
Diffstat (limited to 'include/osmocom')
-rw-r--r--include/osmocom/gsm/gad.h190
-rw-r--r--include/osmocom/gsm/protocol/gsm_23_032.h172
2 files changed, 362 insertions, 0 deletions
diff --git a/include/osmocom/gsm/gad.h b/include/osmocom/gsm/gad.h
new file mode 100644
index 00000000..57d0e37a
--- /dev/null
+++ b/include/osmocom/gsm/gad.h
@@ -0,0 +1,190 @@
+/*! \addtogroup gad
+ * @{
+ * \file gad.h
+ * Message encoding and decoding for 3GPP TS 23.032 GAD: Universal Geographical Area Description.
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_23_032.h>
+#include <osmocom/core/utils.h>
+
+struct msgb;
+
+struct osmo_gad_ell_point {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+};
+
+struct osmo_gad_ell_point_unc_circle {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Uncertainty circle radius in millimeters (m * 1e3), 0 .. 18'000'000. */
+ uint32_t unc;
+};
+
+struct osmo_gad_ell_point_unc_ellipse {
+ /*! Latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! Longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_polygon {
+ uint8_t num_points;
+ struct osmo_gad_ell_point point[15];
+};
+
+struct osmo_gad_ell_point_alt {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in meters, -32767 (depth) .. 32767 (height) */
+ int16_t alt;
+};
+
+struct osmo_gad_ell_point_alt_unc_ell {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in meters, -32767 (depth) .. 32767 (height) */
+ int16_t alt;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Uncertainty altitude in millimeters, 0 .. 990'000.
+ * Coding of uncertainty altitude is non-linear, and distinct from the non-altitude uncertainty coding. Use
+ * osmo_gad_dec_unc_alt(osmo_gad_enc_unc_alt(val)) to clamp. */
+ int32_t unc_alt;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_ell_arc {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! inner circle radius in mm (m * 1e3) */
+ uint32_t inner_r;
+ /*! Uncertainty circle radius in millimeters, 0 .. 18'000'000.
+ * Coding of uncertainty is non-linear, use osmo_gad_dec_unc(osmo_gad_enc_unc(val)) to clamp. */
+ uint32_t unc_r;
+ /*! Offset angle of first arc edge in degrees from North clockwise (eastwards), 0..359.
+ * Angle is coded in increments of 2 degrees. */
+ uint16_t ofs_angle;
+ /*! Included angle defining the angular width of the arc, in degrees clockwise, 1..360.
+ * Angle is coded in increments of 2 degrees. */
+ uint16_t incl_angle;
+ /*! Confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t confidence;
+};
+
+struct osmo_gad_ha_ell_point_alt_unc_ell {
+ /*! latitude in micro degrees (degrees * 1e6), -90'000'000 (S) .. 90'000'000 (N). */
+ int32_t lat;
+ /*! longitude in micro degrees (degrees * 1e6), -180'000'000 (W) .. 180'000'000 (E). */
+ int32_t lon;
+ /*! Altitude in millimeters, -500'000 (depth) .. 10'000'000 (height) */
+ int32_t alt;
+ /*! Uncertainty ellipsoid radius of major axis in millimeters, 0 .. 46'491.
+ * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to
+ * clamp. */
+ uint32_t unc_semi_major;
+ /*! Uncertainty ellipsoid radius of minor axis in millimeters, 0 .. 46'491.
+ * Coding of high-accuracy uncertainty is non-linear, use osmo_gad_dec_ha_unc(osmo_gad_enc_ha_unc(val)) to
+ * clamp. */
+ uint32_t unc_semi_minor;
+ /*! Major axis orientation in degrees (DEG), 0 (N) .. 90 (E) .. 179 (SSE). */
+ uint8_t major_ori;
+ /*! Horizontal confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t h_confidence;
+ /*! High-Accuracy uncertainty altitude */
+ int32_t unc_alt;
+ /*! Vertical confidence in percent, 0 = no information, 1..100%, 101..128 = no information. */
+ uint8_t v_confidence;
+};
+
+struct osmo_gad {
+ enum gad_type type;
+ union {
+ struct osmo_gad_ell_point ell_point;
+ struct osmo_gad_ell_point_unc_circle ell_point_unc_circle;
+ struct osmo_gad_ell_point_unc_ellipse ell_point_unc_ellipse;
+ struct osmo_gad_polygon polygon;
+ struct osmo_gad_ell_point_alt ell_point_alt;
+ struct osmo_gad_ell_point_alt_unc_ell ell_point_alt_unc_ell;
+ struct osmo_gad_ell_arc ell_arc;
+ struct osmo_gad_ell_point_unc_ellipse ha_ell_point_unc_ellipse;
+ struct osmo_gad_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell;
+ };
+};
+
+struct osmo_gad_err {
+ int rc;
+ enum gad_type type;
+ char *logmsg;
+};
+
+extern const struct value_string osmo_gad_type_names[];
+static inline const char *osmo_gad_type_name(enum gad_type val)
+{ return get_value_string(osmo_gad_type_names, val); }
+
+int osmo_gad_raw_write(struct msgb *msg, const union gad_raw *gad_raw);
+int osmo_gad_raw_read(union gad_raw *gad_raw, struct osmo_gad_err **err, void *err_ctx, const uint8_t *data, uint8_t len);
+
+int osmo_gad_enc(union gad_raw *gad_raw, const struct osmo_gad *gad);
+int osmo_gad_dec(struct osmo_gad *gad, struct osmo_gad_err **err, void *err_ctx, const union gad_raw *gad_raw);
+
+int osmo_gad_to_str_buf(char *buf, size_t buflen, const struct osmo_gad *gad);
+char *osmo_gad_to_str_c(void *ctx, const struct osmo_gad *gad);
+
+uint32_t osmo_gad_enc_lat(int32_t deg_1e6);
+int32_t osmo_gad_dec_lat(uint32_t lat);
+uint32_t osmo_gad_enc_lon(int32_t deg_1e6);
+int32_t osmo_gad_dec_lon(uint32_t lon);
+uint8_t osmo_gad_enc_unc(uint32_t mm);
+uint32_t osmo_gad_dec_unc(uint8_t unc);
+/*! @} */
diff --git a/include/osmocom/gsm/protocol/gsm_23_032.h b/include/osmocom/gsm/protocol/gsm_23_032.h
new file mode 100644
index 00000000..5be98a29
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_23_032.h
@@ -0,0 +1,172 @@
+/*! \defgroup gad 3GPP TS 23.032 GAD: Universal Geographical Area Description.
+ * @{
+ * \file gsm_23_032.h
+ */
+/*
+ * (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr <neels@hofmeyr.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/endian.h>
+
+enum gad_type {
+ /*! Ellipsoid point */
+ GAD_TYPE_ELL_POINT = 0,
+ /*! Ellipsoid point with uncertainty circle. */
+ GAD_TYPE_ELL_POINT_UNC_CIRCLE = 1,
+ /*! Ellipsoid point with uncertainty ellipse. */
+ GAD_TYPE_ELL_POINT_UNC_ELLIPSE = 3,
+ GAD_TYPE_POLYGON = 5,
+ /*! Ellipsoid point with altitude. */
+ GAD_TYPE_ELL_POINT_ALT = 8,
+ /*! Ellipsoid point with altitude and uncertainty ellipsoid. */
+ GAD_TYPE_ELL_POINT_ALT_UNC_ELL = 9,
+ /*! Ellipsoid arc */
+ GAD_TYPE_ELL_ARC = 10,
+ /*! High accuracy ellipsoid point with uncertainty ellipse. */
+ GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE = 11,
+ /*! High accuracy ellipsoid point with altitude and uncertainty ellipsoid. */
+ GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL = 12,
+};
+
+struct gad_raw_head {
+ uint8_t spare:4,
+ type:4;
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT */
+ uint8_t lat[3];
+ uint8_t lon[3];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_unc_circle {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_CIRCLE */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t unc:7,
+ spare2:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_unc_ellipse {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_UNC_ELLIPSE */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t unc_semi_major:7,
+ spare1:1;
+ uint8_t unc_semi_minor:7,
+ spare2:1;
+ uint8_t major_ori;
+ uint8_t confidence:7,
+ spare3:1;
+} __attribute__ ((packed));
+
+struct gad_raw_polygon {
+ struct {
+ uint8_t num_points:4;
+ uint8_t type:4; /*!< type = GAD_TYPE_POLYGON */
+ } h;
+ struct {
+ uint8_t lat[3];
+ uint8_t lon[3];
+ } point[15];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_alt {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+} __attribute__ ((packed));
+
+struct gad_raw_ell_point_alt_unc_ell {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_POINT_ALT_UNC_ELL */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t alt[2];
+ uint8_t unc_semi_major:7,
+ spare1:1;
+ uint8_t unc_semi_minor:7,
+ spare2:1;
+ uint8_t major_ori;
+ uint8_t unc_alt:7,
+ spare3:1;
+ uint8_t confidence:7,
+ spare4:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ell_arc {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_ELL_ARC */
+ uint8_t lat[3];
+ uint8_t lon[3];
+ uint8_t inner_r[2];
+ uint8_t unc_r:7,
+ spare1:1;
+ uint8_t ofs_angle;
+ uint8_t incl_angle;
+ uint8_t confidence:7,
+ spare2:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ha_ell_point_unc_ell {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_UNC_ELLIPSE */
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t confidence:7,
+ spare1:1;
+} __attribute__ ((packed));
+
+struct gad_raw_ha_ell_point_alt_unc_ell {
+ struct gad_raw_head h; /*!< type = GAD_TYPE_HA_ELL_POINT_ALT_UNC_ELL */
+ uint8_t lat[4];
+ uint8_t lon[4];
+ uint8_t alt[3];
+ uint8_t unc_semi_major;
+ uint8_t unc_semi_minor;
+ uint8_t major_ori;
+ uint8_t h_confidence:7,
+ spare1:1;
+ uint8_t unc_alt;
+ uint8_t v_confidence:7,
+ spare2:1;
+} __attribute__ ((packed));
+
+/*! GAD PDU in network-byte-order according to 3GPP TS 23.032 GAD: Universal Geographical Area Description. */
+union gad_raw {
+ struct gad_raw_head h;
+ struct gad_raw_ell_point ell_point;
+ struct gad_raw_ell_point_unc_circle ell_point_unc_circle;
+ struct gad_raw_ell_point_unc_ellipse ell_point_unc_ellipse;
+ struct gad_raw_polygon polygon;
+ struct gad_raw_ell_point_alt ell_point_alt;
+ struct gad_raw_ell_point_alt_unc_ell ell_point_alt_unc_ell;
+ struct gad_raw_ell_arc ell_arc;
+ struct gad_raw_ha_ell_point_unc_ell ha_ell_point_unc_ell;
+ struct gad_raw_ha_ell_point_alt_unc_ell ha_ell_point_alt_unc_ell;
+} __attribute__ ((packed));
+
+/*! @} */