diff options
Diffstat (limited to 'src/host')
49 files changed, 9598 insertions, 0 deletions
diff --git a/src/host/calypso_pll/pll.pl b/src/host/calypso_pll/pll.pl new file mode 100755 index 00000000..52c91319 --- /dev/null +++ b/src/host/calypso_pll/pll.pl @@ -0,0 +1,10 @@ +#!/usr/bin/perl + +my $f_in = 26*1000*1000; + +for (my $mult = 1; $mult < 31; $mult++) { + for (my $div = 0; $div < 3; $div++) { + my $fout = $f_in * ($mult / ($div+1)); + printf("%03.1f MHz (mult=%2u, div=%1u)\n", $fout/(1000*1000), $mult, $div); + } +} diff --git a/src/host/layer2/.gitignore b/src/host/layer2/.gitignore new file mode 100644 index 00000000..d3594665 --- /dev/null +++ b/src/host/layer2/.gitignore @@ -0,0 +1,14 @@ +Makefile +Makefile.in +aclocal.m4 +configure +missing +*.o +depcomp +config.* +*.sw? +*.deps +layer2 +install-sh +autom4te.cache +*.a diff --git a/src/host/layer2/Makefile.am b/src/host/layer2/Makefile.am new file mode 100644 index 00000000..bc3910fa --- /dev/null +++ b/src/host/layer2/Makefile.am @@ -0,0 +1,3 @@ +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +SUBDIRS = include src diff --git a/src/host/layer2/configure.ac b/src/host/layer2/configure.ac new file mode 100644 index 00000000..72ed2f82 --- /dev/null +++ b/src/host/layer2/configure.ac @@ -0,0 +1,24 @@ +dnl Process this file with autoconf to produce a configure script +AC_INIT + +AM_INIT_AUTOMAKE(layer2, 0.0.0) + +dnl kernel style compile messages +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl checks for programs +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_RANLIB + +dnl checks for header files +AC_HEADER_STDC + +dnl Checks for typedefs, structures and compiler characteristics + +AC_OUTPUT( + src/Makefile + include/Makefile + include/osmocom/Makefile + Makefile) diff --git a/src/host/layer2/include/Makefile.am b/src/host/layer2/include/Makefile.am new file mode 100644 index 00000000..ca774b6b --- /dev/null +++ b/src/host/layer2/include/Makefile.am @@ -0,0 +1,2 @@ +noinst_HEADERS = l1a_l23_interface.h +SUBDIRS = osmocom diff --git a/src/host/layer2/include/l1a_l23_interface.h b/src/host/layer2/include/l1a_l23_interface.h new file mode 120000 index 00000000..2bbc9679 --- /dev/null +++ b/src/host/layer2/include/l1a_l23_interface.h @@ -0,0 +1 @@ +../../../../include/l1a_l23_interface.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/Makefile.am b/src/host/layer2/include/osmocom/Makefile.am new file mode 100644 index 00000000..7a5a088c --- /dev/null +++ b/src/host/layer2/include/osmocom/Makefile.am @@ -0,0 +1,4 @@ +# headers from OpenBSC +noinst_HEADERS = debug.h gsm_04_08.h linuxlist.h meas_rep.h msgb.h \ + select.h talloc.h timer.h +noinst_HEADERS += osmocom_layer2.h osmocom_data.h diff --git a/src/host/layer2/include/osmocom/debug.h b/src/host/layer2/include/osmocom/debug.h new file mode 120000 index 00000000..ae7c52c3 --- /dev/null +++ b/src/host/layer2/include/osmocom/debug.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/debug.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/gsm_04_08.h b/src/host/layer2/include/osmocom/gsm_04_08.h new file mode 120000 index 00000000..64dbbe0b --- /dev/null +++ b/src/host/layer2/include/osmocom/gsm_04_08.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/gsm_04_08.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/linuxlist.h b/src/host/layer2/include/osmocom/linuxlist.h new file mode 120000 index 00000000..40851e84 --- /dev/null +++ b/src/host/layer2/include/osmocom/linuxlist.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/linuxlist.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/meas_rep.h b/src/host/layer2/include/osmocom/meas_rep.h new file mode 120000 index 00000000..2ab68561 --- /dev/null +++ b/src/host/layer2/include/osmocom/meas_rep.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/meas_rep.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/msgb.h b/src/host/layer2/include/osmocom/msgb.h new file mode 120000 index 00000000..eb079008 --- /dev/null +++ b/src/host/layer2/include/osmocom/msgb.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/msgb.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/osmocom_data.h b/src/host/layer2/include/osmocom/osmocom_data.h new file mode 100644 index 00000000..dd930a2f --- /dev/null +++ b/src/host/layer2/include/osmocom/osmocom_data.h @@ -0,0 +1,22 @@ +#ifndef osmocom_data_h +#define osmocom_data_h + +#include <osmocom/select.h> + +/* taken from OpenBSC */ +enum gsm_band { + GSM_BAND_400, + GSM_BAND_850, + GSM_BAND_900, + GSM_BAND_1800, + GSM_BAND_1900, +}; + +/* One Mobilestation for osmocom */ +struct osmocom_ms { + struct bsc_fd bfd; + enum gsm_band band; + int arfcn; +}; + +#endif diff --git a/src/host/layer2/include/osmocom/osmocom_layer2.h b/src/host/layer2/include/osmocom/osmocom_layer2.h new file mode 100644 index 00000000..af71873c --- /dev/null +++ b/src/host/layer2/include/osmocom/osmocom_layer2.h @@ -0,0 +1,12 @@ +#ifndef osmocom_layer2_h +#define osmocom_layer2_h + +#include <osmocom/msgb.h> + +struct osmocom_ms; + +int osmo_recv(struct osmocom_ms *ms, struct msgb *msg); + +extern int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg); + +#endif diff --git a/src/host/layer2/include/osmocom/select.h b/src/host/layer2/include/osmocom/select.h new file mode 120000 index 00000000..557060f7 --- /dev/null +++ b/src/host/layer2/include/osmocom/select.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/select.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/talloc.h b/src/host/layer2/include/osmocom/talloc.h new file mode 120000 index 00000000..7929944b --- /dev/null +++ b/src/host/layer2/include/osmocom/talloc.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/talloc.h
\ No newline at end of file diff --git a/src/host/layer2/include/osmocom/timer.h b/src/host/layer2/include/osmocom/timer.h new file mode 120000 index 00000000..7cffef20 --- /dev/null +++ b/src/host/layer2/include/osmocom/timer.h @@ -0,0 +1 @@ +../../../libosmocom/include/osmocom/timer.h
\ No newline at end of file diff --git a/src/host/layer2/src/Makefile.am b/src/host/layer2/src/Makefile.am new file mode 100644 index 00000000..5cca4afa --- /dev/null +++ b/src/host/layer2/src/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall + +noinst_LIBRARIES = libosmocom.a +libosmocom_a_SOURCES = libosmocom/debug.c libosmocom/msgb.c libosmocom/select.c \ + libosmocom/talloc.c libosmocom/timer.c + +sbin_PROGRAMS = layer2 +layer2_SOURCES = layer2_main.c osmocom_layer2.c +layer2_LDADD = libosmocom.a diff --git a/src/host/layer2/src/layer2_main.c b/src/host/layer2/src/layer2_main.c new file mode 100644 index 00000000..c84cce49 --- /dev/null +++ b/src/host/layer2/src/layer2_main.c @@ -0,0 +1,205 @@ +/* Main method of the layer2 stack */ +/* (C) 2010 by Holger Hans Peter Freyther + * + * 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 <osmocom/osmocom_layer2.h> +#include <osmocom/osmocom_data.h> + +#include <osmocom/debug.h> +#include <osmocom/msgb.h> +#include <osmocom/talloc.h> + +#include <arpa/inet.h> + +#include <sys/socket.h> +#include <sys/un.h> + +#define _GNU_SOURCE +#include <getopt.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +#define GSM_L2_LENGTH 256 + +static void *l2_ctx = NULL; +static char *socket_path = "/tmp/osmocom_l2"; +static struct osmocom_ms *ms = NULL; + +static int layer2_read(struct bsc_fd *fd, unsigned int flags) +{ + struct msgb *msg; + u_int16_t len; + int rc; + + msg = msgb_alloc(GSM_L2_LENGTH, "Layer2"); + if (!msg) { + fprintf(stderr, "Failed to allocate msg.\n"); + return -1; + } + + rc = read(fd->fd, &len, sizeof(len)); + if (rc < sizeof(len)) { + fprintf(stderr, "Short read. Error.\n"); + exit(2); + } + + if (ntohs(len) > GSM_L2_LENGTH) { + fprintf(stderr, "Length is too big: %u\n", ntohs(len)); + msgb_free(msg); + return -1; + } + + + /* blocking read for the poor... we can starve in here... */ + msg->l2h = msgb_put(msg, ntohs(len)); + rc = read(fd->fd, msg->l2h, msgb_l2len(msg)); + if (rc != msgb_l2len(msg)) { + fprintf(stderr, "Can not read data: rc: %d errno: %d\n", rc, errno); + msgb_free(msg); + return -1; + } + + osmo_recv((struct osmocom_ms *) fd->data, msg); + msgb_free(msg); + return 0; +} + +int osmo_send_l1(struct osmocom_ms *ms, struct msgb *msg) +{ + int rc; + uint16_t *len; + + LOGP(DMUX, LOGL_INFO, "Sending: '%s'\n", hexdump(msg->data, msg->len)); + + + len = (uint16_t *) msgb_push(msg, sizeof(*len)); + *len = htons(msg->len - sizeof(*len)); + + /* TODO: just enqueue the message and wait for ready write.. */ + rc = write(ms->bfd.fd, msg->data, msg->len); + if (rc != msg->len) { + fprintf(stderr, "Failed to write data: rc: %d\n", rc); + msgb_free(msg); + return -1; + } + + msgb_free(msg); + return 0; +} + +static void print_usage() +{ + printf("Usage: ./layer2\n"); +} + +static void print_help() +{ + printf(" Some help...\n"); + printf(" -h --help this text\n"); + printf(" -s --socket /tmp/osmocom_l2. Path to the unix domain socket\n"); + printf(" -a --arfcn NR. The ARFCN to be used for layer2.\n"); +} + +static void handle_options(int argc, char **argv) +{ + while (1) { + int option_index = 0, c; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"socket", 1, 0, 's'}, + {"arfcn", 1, 0, 'a'}, + {0, 0, 0, 0}, + }; + + c = getopt_long(argc, argv, "hs:a:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + print_usage(); + print_help(); + exit(0); + break; + case 's': + socket_path = talloc_strdup(l2_ctx, optarg); + break; + case 'a': + ms->arfcn = atoi(optarg); + break; + default: + break; + } + } +} + +int main(int argc, char **argv) +{ + int rc; + struct sockaddr_un local; + + l2_ctx = talloc_named_const(NULL, 1, "layer2 context"); + + ms = talloc_zero(l2_ctx, struct osmocom_ms); + if (!ms) { + fprintf(stderr, "Failed to allocate MS\n"); + exit(1); + } + + ms->arfcn = 871; + + handle_options(argc, argv); + + ms->bfd.fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (ms->bfd.fd < 0) { + fprintf(stderr, "Failed to create unix domain socket.\n"); + exit(1); + } + + local.sun_family = AF_UNIX; + strncpy(local.sun_path, socket_path, sizeof(local.sun_path)); + local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + + rc = connect(ms->bfd.fd, (struct sockaddr *) &local, + sizeof(local.sun_family) + strlen(local.sun_path)); + if (rc < 0) { + fprintf(stderr, "Failed to connect to '%s'.\n", local.sun_path); + exit(1); + } + + ms->bfd.when = BSC_FD_READ; + ms->bfd.cb = layer2_read; + ms->bfd.data = ms; + + if (bsc_register_fd(&ms->bfd) != 0) { + fprintf(stderr, "Failed to register fd.\n"); + exit(1); + } + + while (1) { + bsc_select_main(0); + } + + + return 0; +} diff --git a/src/host/layer2/src/libosmocom/debug.c b/src/host/layer2/src/libosmocom/debug.c new file mode 120000 index 00000000..acf42611 --- /dev/null +++ b/src/host/layer2/src/libosmocom/debug.c @@ -0,0 +1 @@ +../../../libosmocom/src/debug.c
\ No newline at end of file diff --git a/src/host/layer2/src/libosmocom/msgb.c b/src/host/layer2/src/libosmocom/msgb.c new file mode 120000 index 00000000..42624f80 --- /dev/null +++ b/src/host/layer2/src/libosmocom/msgb.c @@ -0,0 +1 @@ +../../../libosmocom/src/msgb.c
\ No newline at end of file diff --git a/src/host/layer2/src/libosmocom/select.c b/src/host/layer2/src/libosmocom/select.c new file mode 120000 index 00000000..005d21bb --- /dev/null +++ b/src/host/layer2/src/libosmocom/select.c @@ -0,0 +1 @@ +../../../libosmocom/src/select.c
\ No newline at end of file diff --git a/src/host/layer2/src/libosmocom/signal.c b/src/host/layer2/src/libosmocom/signal.c new file mode 120000 index 00000000..d1651c39 --- /dev/null +++ b/src/host/layer2/src/libosmocom/signal.c @@ -0,0 +1 @@ +../../../libosmocom/src/signal.c
\ No newline at end of file diff --git a/src/host/layer2/src/libosmocom/talloc.c b/src/host/layer2/src/libosmocom/talloc.c new file mode 120000 index 00000000..dcc53fa7 --- /dev/null +++ b/src/host/layer2/src/libosmocom/talloc.c @@ -0,0 +1 @@ +../../../libosmocom/src/talloc.c
\ No newline at end of file diff --git a/src/host/layer2/src/libosmocom/timer.c b/src/host/layer2/src/libosmocom/timer.c new file mode 120000 index 00000000..142a2aa0 --- /dev/null +++ b/src/host/layer2/src/libosmocom/timer.c @@ -0,0 +1 @@ +../../../libosmocom/src/timer.c
\ No newline at end of file diff --git a/src/host/layer2/src/osmocom_layer2.c b/src/host/layer2/src/osmocom_layer2.c new file mode 100644 index 00000000..0be0a4c4 --- /dev/null +++ b/src/host/layer2/src/osmocom_layer2.c @@ -0,0 +1,226 @@ +/* Layer2 handling code... LAPD and stuff + * + * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org> + * + * 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 <osmocom/osmocom_layer2.h> +#include <osmocom/osmocom_data.h> +#include <osmocom/debug.h> +#include <osmocom/gsm_04_08.h> + +#include <stdio.h> +#include <stdint.h> +#include <l1a_l23_interface.h> + + +static struct msgb *osmo_l1_alloc(uint8_t msg_type) +{ + struct l1_info_ul *ul; + struct msgb *msg = msgb_alloc_headroom(256, 4, "osmo_l1"); + + if (!msg) { + fprintf(stderr, "Failed to allocate memory.\n"); + return NULL; + } + + ul = (struct l1_info_ul *) msgb_put(msg, sizeof(*ul)); + ul->msg_type = msg_type; + + return msg; +} + +static int osmo_make_band_arfcn(struct osmocom_ms *ms) +{ + /* TODO: Include the band */ + return ms->arfcn; +} + +static int osmo_l2_ccch_resp(struct osmocom_ms *ms, struct msgb *msg) +{ + struct l1_info_dl *dl; + struct l1_sync_new_ccch_resp *sb; + + if (msgb_l3len(msg) < sizeof(*sb)) { + fprintf(stderr, "MSG too short for CCCH RESP: %u\n", msgb_l3len(msg)); + return -1; + } + + dl = (struct l1_info_dl *) msg->l2h; + sb = (struct l1_sync_new_ccch_resp *) msg->l3h; + + printf("Found sync burst: SNR: %u TDMA: (%.4u/%.2u/%.2u) bsic: %d\n", + dl->snr[0], dl->time.t1, dl->time.t2, dl->time.t3, sb->bsic); + return 0; +} + +static void dump_bcch(u_int8_t tc, const uint8_t *data) +{ + struct gsm48_system_information_type_header *si_hdr; + si_hdr = (struct gsm48_system_information_type_header *) data;; + + /* GSM 05.02 ยง6.3.1.3 Mapping of BCCH data */ + switch (si_hdr->system_information) { + case GSM48_MT_RR_SYSINFO_1: + fprintf(stderr, "\tSI1"); + if (tc != 0) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_2: + fprintf(stderr, "\tSI2"); + if (tc != 1) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_3: + fprintf(stderr, "\tSI3"); + if (tc != 2 && tc != 6) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_4: + fprintf(stderr, "\tSI4"); + if (tc != 3 && tc != 7) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_5: + fprintf(stderr, "\tSI5"); + break; + case GSM48_MT_RR_SYSINFO_6: + fprintf(stderr, "\tSI6"); + break; + case GSM48_MT_RR_SYSINFO_7: + fprintf(stderr, "\tSI7"); + if (tc != 7) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_8: + fprintf(stderr, "\tSI8"); + if (tc != 3) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_9: + fprintf(stderr, "\tSI9"); + if (tc != 4) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_13: + fprintf(stderr, "\tSI13"); + if (tc != 4 && tc != 0) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_16: + fprintf(stderr, "\tSI16"); + if (tc != 6) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_17: + fprintf(stderr, "\tSI17"); + if (tc != 2) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_2bis: + fprintf(stderr, "\tSI2bis"); + if (tc != 5) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_2ter: + fprintf(stderr, "\tSI2ter"); + if (tc != 5 && tc != 4) + fprintf(stderr, " on wrong TC"); + break; + case GSM48_MT_RR_SYSINFO_5bis: + fprintf(stderr, "\tSI5bis"); + break; + case GSM48_MT_RR_SYSINFO_5ter: + fprintf(stderr, "\tSI5ter"); + break; + default: + fprintf(stderr, "\tUnknown SI"); + break; + }; + + fprintf(stderr, "\n"); +} + +static int osmo_l2_ccch_data(struct osmocom_ms *ms, struct msgb *msg) +{ + struct l1_info_dl *dl; + struct l1_ccch_info_ind *ccch; + + if (msgb_l3len(msg) < sizeof(*ccch)) { + fprintf(stderr, "MSG too short CCCH Data Ind: %u\n", msgb_l3len(msg)); + return -1; + } + + dl = (struct l1_info_dl *) msg->l2h; + ccch = (struct l1_ccch_info_ind *) msg->l3h; + printf("Found CCCH burst(s): TDMA: (%.4u/%.2u/%.2u) tc:%d %s si: 0x%x\n", + dl->time.t1, dl->time.t2, dl->time.t3, dl->time.tc, + hexdump(ccch->data, sizeof(ccch->data)), ccch->data[2]); + + dump_bcch(dl->time.tc, ccch->data); + return 0; +} + +static int osmo_l1_reset(struct osmocom_ms *ms) +{ + struct msgb *msg; + struct l1_sync_new_ccch_req *req; + + msg = osmo_l1_alloc(SYNC_NEW_CCCH_REQ); + if (!msg) + return -1; + + printf("Layer1 Reset.\n"); + req = (struct l1_sync_new_ccch_req *) msgb_put(msg, sizeof(*req)); + req->band_arfcn = osmo_make_band_arfcn(ms); + + return osmo_send_l1(ms, msg); +} + + +int osmo_recv(struct osmocom_ms *ms, struct msgb *msg) +{ + int rc = 0; + struct l1_info_dl *dl; + + if (msgb_l2len(msg) < sizeof(*dl)) { + fprintf(stderr, "Short Layer2 message: %u\n", msgb_l2len(msg)); + return -1; + } + + dl = (struct l1_info_dl *) msg->l2h; + msg->l3h = &msg->l2h[0] + sizeof(*dl); + + switch (dl->msg_type) { + case SYNC_NEW_CCCH_RESP: + rc = osmo_l2_ccch_resp(ms, msg); + break; + case CCCH_INFO_IND: + rc = osmo_l2_ccch_data(ms, msg); + break; + case LAYER1_RESET: + rc = osmo_l1_reset(ms); + break; + default: + fprintf(stderr, "Unknown MSG: %u\n", dl->msg_type); + break; + } + + return rc; +} diff --git a/src/host/libosmocom/README b/src/host/libosmocom/README new file mode 100644 index 00000000..1a97beac --- /dev/null +++ b/src/host/libosmocom/README @@ -0,0 +1 @@ +This is a copy of OpenBSC header and sources. Do not edit them. diff --git a/src/host/libosmocom/include/osmocom/debug.h b/src/host/libosmocom/include/osmocom/debug.h new file mode 100644 index 00000000..c40eec3f --- /dev/null +++ b/src/host/libosmocom/include/osmocom/debug.h @@ -0,0 +1,131 @@ +#ifndef _DEBUG_H +#define _DEBUG_H + +#include <stdio.h> +#include "linuxlist.h" + +#define DEBUG + +/* Debug Areas of the code */ +enum { + DRLL, + DCC, + DMM, + DRR, + DRSL, + DNM, + DMNCC, + DSMS, + DPAG, + DMEAS, + DMI, + DMIB, + DMUX, + DINP, + DSCCP, + DMSC, + DMGCP, + DHO, + DDB, + DREF, + Debug_LastEntry, +}; + +#ifdef DEBUG +#define DEBUGP(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 0, fmt, ## args) +#define DEBUGPC(ss, fmt, args...) debugp(ss, __FILE__, __LINE__, 1, fmt, ## args) +#else +#define DEBUGP(xss, fmt, args...) +#define DEBUGPC(ss, fmt, args...) +#endif + + +#define static_assert(exp, name) typedef int dummy##name [(exp) ? 1 : -1]; + +char *hexdump(const unsigned char *buf, int len); +void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); + +/* new logging interface */ +#define LOGP(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 0, fmt, ##args) +#define LOGPC(ss, level, fmt, args...) debugp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args) + +/* different levels */ +#define LOGL_DEBUG 1 /* debugging information */ +#define LOGL_INFO 3 +#define LOGL_NOTICE 5 /* abnormal/unexpected condition */ +#define LOGL_ERROR 7 /* error condition, requires user action */ +#define LOGL_FATAL 8 /* fatal, program aborted */ + +/* context */ +#define BSC_CTX_LCHAN 0 +#define BSC_CTX_SUBSCR 1 +#define BSC_CTX_BTS 2 +#define BSC_CTX_SCCP 3 + +/* target */ + +enum { + DEBUG_FILTER_IMSI = 1 << 0, + DEBUG_FILTER_ALL = 1 << 1, +}; + +struct debug_category { + int enabled; + int loglevel; +}; + +struct debug_target { + int filter_map; + char *imsi_filter; + + + struct debug_category categories[Debug_LastEntry]; + int use_color; + int print_timestamp; + int loglevel; + + union { + struct { + FILE *out; + } tgt_stdout; + + struct { + int priority; + } tgt_syslog; + + struct { + void *vty; + } tgt_vty; + }; + + void (*output) (struct debug_target *target, const char *string); + + struct llist_head entry; +}; + +/* use the above macros */ +void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 6, 7))); +void debug_init(void); + +/* context management */ +void debug_reset_context(void); +void debug_set_context(int ctx, void *value); + +/* filter on the targets */ +void debug_set_imsi_filter(struct debug_target *target, const char *imsi); +void debug_set_all_filter(struct debug_target *target, int); +void debug_set_use_color(struct debug_target *target, int); +void debug_set_print_timestamp(struct debug_target *target, int); +void debug_set_log_level(struct debug_target *target, int log_level); +void debug_parse_category_mask(struct debug_target *target, const char* mask); +int debug_parse_level(const char *lvl); +int debug_parse_category(const char *category); +void debug_set_category_filter(struct debug_target *target, int category, int enable, int level); + + +/* management of the targets */ +struct debug_target *debug_target_create(void); +struct debug_target *debug_target_create_stderr(void); +void debug_add_target(struct debug_target *target); +void debug_del_target(struct debug_target *target); +#endif /* _DEBUG_H */ diff --git a/src/host/libosmocom/include/osmocom/gsm_04_08.h b/src/host/libosmocom/include/osmocom/gsm_04_08.h new file mode 100644 index 00000000..84b9b5d1 --- /dev/null +++ b/src/host/libosmocom/include/osmocom/gsm_04_08.h @@ -0,0 +1,796 @@ +#ifndef _GSM_04_08_H +#define _GSM_04_08_H + +#include <osmocom/meas_rep.h> + +/* GSM TS 04.08 definitions */ +struct gsm_lchan; + +struct gsm48_classmark1 { + u_int8_t spare:1, + rev_level:2, + es_ind:1, + a5_1:1, + pwr_lev:3; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.5 */ +struct gsm48_chan_desc { + u_int8_t chan_nr; + union { + struct { + u_int8_t maio_high:4, + h:1, + tsc:3; + u_int8_t hsn:6, + maio_low:2; + } h1; + struct { + u_int8_t arfcn_high:2, + spare:2, + h:1, + tsc:3; + u_int8_t arfcn_low; + } h0; + }; +} __attribute__ ((packed)); + +/* Chapter 10.5.2.21aa */ +struct gsm48_multi_rate_conf { + u_int8_t smod : 2, + spare: 1, + icmi : 1, + nscb : 1, + ver : 3; + u_int8_t m4_75 : 1, + m5_15 : 1, + m5_90 : 1, + m6_70 : 1, + m7_40 : 1, + m7_95 : 1, + m10_2 : 1, + m12_2 : 1; +} __attribute__((packed)); + +/* Chapter 10.5.2.30 */ +struct gsm48_req_ref { + u_int8_t ra; + u_int8_t t3_high:3, + t1_:5; + u_int8_t t2:5, + t3_low:3; +} __attribute__ ((packed)); + +/* + * Chapter 9.1.5/9.1.6 + * + * For 9.1.6 the chan_desc has the meaning of 10.5.2.5a + */ +struct gsm48_chan_mode_modify { + struct gsm48_chan_desc chan_desc; + u_int8_t mode; +} __attribute__ ((packed)); + +enum gsm48_chan_mode { + GSM48_CMODE_SIGN = 0x00, + GSM48_CMODE_SPEECH_V1 = 0x01, + GSM48_CMODE_SPEECH_EFR = 0x21, + GSM48_CMODE_SPEECH_AMR = 0x41, + GSM48_CMODE_DATA_14k5 = 0x0f, + GSM48_CMODE_DATA_12k0 = 0x03, + GSM48_CMODE_DATA_6k0 = 0x0b, + GSM48_CMODE_DATA_3k6 = 0x23, +}; + +/* Chapter 9.1.2 */ +struct gsm48_ass_cmd { + /* Semantic is from 10.5.2.5a */ + struct gsm48_chan_desc chan_desc; + u_int8_t power_command; + u_int8_t data[0]; +} __attribute__((packed)); + +/* Chapter 10.5.2.2 */ +struct gsm48_cell_desc { + u_int8_t bcc:3, + ncc:3, + arfcn_hi:2; + u_int8_t arfcn_lo; +} __attribute__((packed)); + +/* Chapter 9.1.15 */ +struct gsm48_ho_cmd { + struct gsm48_cell_desc cell_desc; + struct gsm48_chan_desc chan_desc; + u_int8_t ho_ref; + u_int8_t power_command; + u_int8_t data[0]; +} __attribute__((packed)); + +/* Chapter 9.1.18 */ +struct gsm48_imm_ass { + u_int8_t l2_plen; + u_int8_t proto_discr; + u_int8_t msg_type; + u_int8_t page_mode; + struct gsm48_chan_desc chan_desc; + struct gsm48_req_ref req_ref; + u_int8_t timing_advance; + u_int8_t mob_alloc_len; + u_int8_t mob_alloc[0]; +} __attribute__ ((packed)); + +/* Chapter 10.5.1.3 */ +struct gsm48_loc_area_id { + u_int8_t digits[3]; /* BCD! */ + u_int16_t lac; +} __attribute__ ((packed)); + +/* Section 9.2.2 */ +struct gsm48_auth_req { + u_int8_t key_seq:4, + spare:4; + u_int8_t rand[16]; +} __attribute__ ((packed)); + +/* Section 9.2.15 */ +struct gsm48_loc_upd_req { + u_int8_t type:4, + key_seq:4; + struct gsm48_loc_area_id lai; + struct gsm48_classmark1 classmark1; + u_int8_t mi_len; + u_int8_t mi[0]; +} __attribute__ ((packed)); + +/* Section 10.1 */ +struct gsm48_hdr { + u_int8_t proto_discr; + u_int8_t msg_type; + u_int8_t data[0]; +} __attribute__ ((packed)); + +/* Section 9.1.3x System information Type header */ +struct gsm48_system_information_type_header { + u_int8_t l2_plen; + u_int8_t rr_protocol_discriminator :4, + skip_indicator:4; + u_int8_t system_information; +} __attribute__ ((packed)); + +struct gsm48_rach_control { + u_int8_t re :1, + cell_bar :1, + tx_integer :4, + max_trans :2; + u_int8_t t2; + u_int8_t t3; +} __attribute__ ((packed)); + +/* Section 10.5.2.4 Cell Selection Parameters */ +struct gsm48_cell_sel_par { + u_int8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */ + cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */ + u_int8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */ + neci:1, + acs:1; +} __attribute__ ((packed)); + +/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */ +struct gsm48_control_channel_descr { + u_int8_t ccch_conf :3, + bs_ag_blks_res :3, + att :1, + spare1 :1; + u_int8_t bs_pa_mfrms : 3, + spare2 :5; + u_int8_t t3212; +} __attribute__ ((packed)); + +struct gsm48_cell_options { + u_int8_t radio_link_timeout:4, + dtx:2, + pwrc:1, + spare:1; +} __attribute__ ((packed)); + +/* Section 9.2.9 CM service request */ +struct gsm48_service_request { + u_int8_t cm_service_type : 4, + cipher_key_seq : 4; + /* length + 3 bytes */ + u_int32_t classmark; + u_int8_t mi_len; + u_int8_t mi[0]; + /* optional priority level */ +} __attribute__ ((packed)); + +/* Section 9.1.31 System information Type 1 */ +struct gsm48_system_information_type_1 { + struct gsm48_system_information_type_header header; + u_int8_t cell_channel_description[16]; + struct gsm48_rach_control rach_control; + u_int8_t rest_octets[0]; /* NCH position on the CCCH */ +} __attribute__ ((packed)); + +/* Section 9.1.32 System information Type 2 */ +struct gsm48_system_information_type_2 { + struct gsm48_system_information_type_header header; + u_int8_t bcch_frequency_list[16]; + u_int8_t ncc_permitted; + struct gsm48_rach_control rach_control; +} __attribute__ ((packed)); + +/* Section 9.1.35 System information Type 3 */ +struct gsm48_system_information_type_3 { + struct gsm48_system_information_type_header header; + u_int16_t cell_identity; + struct gsm48_loc_area_id lai; + struct gsm48_control_channel_descr control_channel_desc; + struct gsm48_cell_options cell_options; + struct gsm48_cell_sel_par cell_sel_par; + struct gsm48_rach_control rach_control; + u_int8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.1.36 System information Type 4 */ +struct gsm48_system_information_type_4 { + struct gsm48_system_information_type_header header; + struct gsm48_loc_area_id lai; + struct gsm48_cell_sel_par cell_sel_par; + struct gsm48_rach_control rach_control; + /* optional CBCH conditional CBCH... followed by + mandantory SI 4 Reset Octets + */ + u_int8_t data[0]; +} __attribute__ ((packed)); + +/* Section 9.1.37 System information Type 5 */ +struct gsm48_system_information_type_5 { + u_int8_t rr_protocol_discriminator :4, + skip_indicator:4; + u_int8_t system_information; + u_int8_t bcch_frequency_list[16]; +} __attribute__ ((packed)); + +/* Section 9.1.40 System information Type 6 */ +struct gsm48_system_information_type_6 { + u_int8_t rr_protocol_discriminator :4, + skip_indicator:4; + u_int8_t system_information; + u_int16_t cell_identity; + struct gsm48_loc_area_id lai; + struct gsm48_cell_options cell_options; + u_int8_t ncc_permitted; + u_int8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.1.43a System Information type 13 */ +struct gsm48_system_information_type_13 { + struct gsm48_system_information_type_header header; + u_int8_t rest_octets[0]; +} __attribute__ ((packed)); + +/* Section 9.2.12 IMSI Detach Indication */ +struct gsm48_imsi_detach_ind { + struct gsm48_classmark1 classmark1; + u_int8_t mi_len; + u_int8_t mi[0]; +} __attribute__ ((packed)); + +/* Section 10.2 + GSM 04.07 12.2.3.1.1 */ +#define GSM48_PDISC_GROUP_CC 0x00 +#define GSM48_PDISC_BCAST_CC 0x01 +#define GSM48_PDISC_PDSS1 0x02 +#define GSM48_PDISC_CC 0x03 +#define GSM48_PDISC_PDSS2 0x04 +#define GSM48_PDISC_MM 0x05 +#define GSM48_PDISC_RR 0x06 +#define GSM48_PDISC_MM_GPRS 0x08 +#define GSM48_PDISC_SMS 0x09 +#define GSM48_PDISC_SM_GPRS 0x0a +#define GSM48_PDISC_NC_SS 0x0b +#define GSM48_PDISC_LOC 0x0c +#define GSM48_PDISC_MASK 0x0f +#define GSM48_PDISC_USSD 0x11 + +/* Section 10.4 */ +#define GSM48_MT_RR_INIT_REQ 0x3c +#define GSM48_MT_RR_ADD_ASS 0x3b +#define GSM48_MT_RR_IMM_ASS 0x3f +#define GSM48_MT_RR_IMM_ASS_EXT 0x39 +#define GSM48_MT_RR_IMM_ASS_REJ 0x3a + +#define GSM48_MT_RR_CIPH_M_CMD 0x35 +#define GSM48_MT_RR_CIPH_M_COMPL 0x32 + +#define GSM48_MT_RR_CFG_CHG_CMD 0x30 +#define GSM48_MT_RR_CFG_CHG_ACK 0x31 +#define GSM48_MT_RR_CFG_CHG_REJ 0x33 + +#define GSM48_MT_RR_ASS_CMD 0x2e +#define GSM48_MT_RR_ASS_COMPL 0x29 +#define GSM48_MT_RR_ASS_FAIL 0x2f +#define GSM48_MT_RR_HANDO_CMD 0x2b +#define GSM48_MT_RR_HANDO_COMPL 0x2c +#define GSM48_MT_RR_HANDO_FAIL 0x28 +#define GSM48_MT_RR_HANDO_INFO 0x2d + +#define GSM48_MT_RR_CELL_CHG_ORDER 0x08 +#define GSM48_MT_RR_PDCH_ASS_CMD 0x23 + +#define GSM48_MT_RR_CHAN_REL 0x0d +#define GSM48_MT_RR_PART_REL 0x0a +#define GSM48_MT_RR_PART_REL_COMP 0x0f + +#define GSM48_MT_RR_PAG_REQ_1 0x21 +#define GSM48_MT_RR_PAG_REQ_2 0x22 +#define GSM48_MT_RR_PAG_REQ_3 0x24 +#define GSM48_MT_RR_PAG_RESP 0x27 +#define GSM48_MT_RR_NOTIF_NCH 0x20 +#define GSM48_MT_RR_NOTIF_FACCH 0x25 +#define GSM48_MT_RR_NOTIF_RESP 0x26 + +#define GSM48_MT_RR_SYSINFO_8 0x18 +#define GSM48_MT_RR_SYSINFO_1 0x19 +#define GSM48_MT_RR_SYSINFO_2 0x1a +#define GSM48_MT_RR_SYSINFO_3 0x1b +#define GSM48_MT_RR_SYSINFO_4 0x1c +#define GSM48_MT_RR_SYSINFO_5 0x1d +#define GSM48_MT_RR_SYSINFO_6 0x1e +#define GSM48_MT_RR_SYSINFO_7 0x1f + +#define GSM48_MT_RR_SYSINFO_2bis 0x02 +#define GSM48_MT_RR_SYSINFO_2ter 0x03 +#define GSM48_MT_RR_SYSINFO_5bis 0x05 +#define GSM48_MT_RR_SYSINFO_5ter 0x06 +#define GSM48_MT_RR_SYSINFO_9 0x04 +#define GSM48_MT_RR_SYSINFO_13 0x00 + +#define GSM48_MT_RR_SYSINFO_16 0x3d +#define GSM48_MT_RR_SYSINFO_17 0x3e + +#define GSM48_MT_RR_CHAN_MODE_MODIF 0x10 +#define GSM48_MT_RR_STATUS 0x12 +#define GSM48_MT_RR_CHAN_MODE_MODIF_ACK 0x17 +#define GSM48_MT_RR_FREQ_REDEF 0x14 +#define GSM48_MT_RR_MEAS_REP 0x15 +#define GSM48_MT_RR_CLSM_CHG 0x16 +#define GSM48_MT_RR_CLSM_ENQ 0x13 +#define GSM48_MT_RR_EXT_MEAS_REP 0x36 +#define GSM48_MT_RR_EXT_MEAS_REP_ORD 0x37 +#define GSM48_MT_RR_GPRS_SUSP_REQ 0x34 + +#define GSM48_MT_RR_VGCS_UPL_GRANT 0x08 +#define GSM48_MT_RR_UPLINK_RELEASE 0x0e +#define GSM48_MT_RR_UPLINK_FREE 0x0c +#define GSM48_MT_RR_UPLINK_BUSY 0x2a +#define GSM48_MT_RR_TALKER_IND 0x11 + +#define GSM48_MT_RR_APP_INFO 0x38 + +/* Table 10.2/3GPP TS 04.08 */ +#define GSM48_MT_MM_IMSI_DETACH_IND 0x01 +#define GSM48_MT_MM_LOC_UPD_ACCEPT 0x02 +#define GSM48_MT_MM_LOC_UPD_REJECT 0x04 +#define GSM48_MT_MM_LOC_UPD_REQUEST 0x08 + +#define GSM48_MT_MM_AUTH_REJ 0x11 +#define GSM48_MT_MM_AUTH_REQ 0x12 +#define GSM48_MT_MM_AUTH_RESP 0x14 +#define GSM48_MT_MM_ID_REQ 0x18 +#define GSM48_MT_MM_ID_RESP 0x19 +#define GSM48_MT_MM_TMSI_REALL_CMD 0x1a +#define GSM48_MT_MM_TMSI_REALL_COMPL 0x1b + +#define GSM48_MT_MM_CM_SERV_ACC 0x21 +#define GSM48_MT_MM_CM_SERV_REJ 0x22 +#define GSM48_MT_MM_CM_SERV_ABORT 0x23 +#define GSM48_MT_MM_CM_SERV_REQ 0x24 +#define GSM48_MT_MM_CM_SERV_PROMPT 0x25 +#define GSM48_MT_MM_CM_REEST_REQ 0x28 +#define GSM48_MT_MM_ABORT 0x29 + +#define GSM48_MT_MM_NULL 0x30 +#define GSM48_MT_MM_STATUS 0x31 +#define GSM48_MT_MM_INFO 0x32 + +/* Table 10.3/3GPP TS 04.08 */ +#define GSM48_MT_CC_ALERTING 0x01 +#define GSM48_MT_CC_CALL_CONF 0x08 +#define GSM48_MT_CC_CALL_PROC 0x02 +#define GSM48_MT_CC_CONNECT 0x07 +#define GSM48_MT_CC_CONNECT_ACK 0x0f +#define GSM48_MT_CC_EMERG_SETUP 0x0e +#define GSM48_MT_CC_PROGRESS 0x03 +#define GSM48_MT_CC_ESTAB 0x04 +#define GSM48_MT_CC_ESTAB_CONF 0x06 +#define GSM48_MT_CC_RECALL 0x0b +#define GSM48_MT_CC_START_CC 0x09 +#define GSM48_MT_CC_SETUP 0x05 + +#define GSM48_MT_CC_MODIFY 0x17 +#define GSM48_MT_CC_MODIFY_COMPL 0x1f +#define GSM48_MT_CC_MODIFY_REJECT 0x13 +#define GSM48_MT_CC_USER_INFO 0x10 +#define GSM48_MT_CC_HOLD 0x18 +#define GSM48_MT_CC_HOLD_ACK 0x19 +#define GSM48_MT_CC_HOLD_REJ 0x1a +#define GSM48_MT_CC_RETR 0x1c +#define GSM48_MT_CC_RETR_ACK 0x1d +#define GSM48_MT_CC_RETR_REJ 0x1e + +#define GSM48_MT_CC_DISCONNECT 0x25 +#define GSM48_MT_CC_RELEASE 0x2d +#define GSM48_MT_CC_RELEASE_COMPL 0x2a + +#define GSM48_MT_CC_CONG_CTRL 0x39 +#define GSM48_MT_CC_NOTIFY 0x3e +#define GSM48_MT_CC_STATUS 0x3d +#define GSM48_MT_CC_STATUS_ENQ 0x34 +#define GSM48_MT_CC_START_DTMF 0x35 +#define GSM48_MT_CC_STOP_DTMF 0x31 +#define GSM48_MT_CC_STOP_DTMF_ACK 0x32 +#define GSM48_MT_CC_START_DTMF_ACK 0x36 +#define GSM48_MT_CC_START_DTMF_REJ 0x37 +#define GSM48_MT_CC_FACILITY 0x3a + +/* FIXME: Table 10.4 / 10.4a (GPRS) */ + +/* Section 10.5.2.26, Table 10.5.64 */ +#define GSM48_PM_MASK 0x03 +#define GSM48_PM_NORMAL 0x00 +#define GSM48_PM_EXTENDED 0x01 +#define GSM48_PM_REORG 0x02 +#define GSM48_PM_SAME 0x03 + +/* Chapter 10.5.3.5 / Table 10.5.93 */ +#define GSM48_LUPD_NORMAL 0x0 +#define GSM48_LUPD_PERIODIC 0x1 +#define GSM48_LUPD_IMSI_ATT 0x2 +#define GSM48_LUPD_RESERVED 0x3 + +/* Table 10.5.4 */ +#define GSM_MI_TYPE_MASK 0x07 +#define GSM_MI_TYPE_NONE 0x00 +#define GSM_MI_TYPE_IMSI 0x01 +#define GSM_MI_TYPE_IMEI 0x02 +#define GSM_MI_TYPE_IMEISV 0x03 +#define GSM_MI_TYPE_TMSI 0x04 +#define GSM_MI_ODD 0x08 + +#define GSM48_IE_MUL_RATE_CFG 0x03 /* 10.5.2.21aa */ +#define GSM48_IE_MOBILE_ID 0x17 +#define GSM48_IE_NAME_LONG 0x43 /* 10.5.3.5a */ +#define GSM48_IE_NAME_SHORT 0x45 /* 10.5.3.5a */ +#define GSM48_IE_UTC 0x46 /* 10.5.3.8 */ +#define GSM48_IE_NET_TIME_TZ 0x47 /* 10.5.3.9 */ +#define GSM48_IE_LSA_IDENT 0x48 /* 10.5.3.11 */ + +#define GSM48_IE_BEARER_CAP 0x04 /* 10.5.4.5 */ +#define GSM48_IE_CAUSE 0x08 /* 10.5.4.11 */ +#define GSM48_IE_CC_CAP 0x15 /* 10.5.4.5a */ +#define GSM48_IE_ALERT 0x19 /* 10.5.4.26 */ +#define GSM48_IE_FACILITY 0x1c /* 10.5.4.15 */ +#define GSM48_IE_PROGR_IND 0x1e /* 10.5.4.21 */ +#define GSM48_IE_AUX_STATUS 0x24 /* 10.5.4.4 */ +#define GSM48_IE_NOTIFY 0x27 /* 10.5.4.20 */ +#define GSM48_IE_KPD_FACILITY 0x2c /* 10.5.4.17 */ +#define GSM48_IE_SIGNAL 0x34 /* 10.5.4.23 */ +#define GSM48_IE_CONN_BCD 0x4c /* 10.5.4.13 */ +#define GSM48_IE_CONN_SUB 0x4d /* 10.5.4.14 */ +#define GSM48_IE_CALLING_BCD 0x5c /* 10.5.4.9 */ +#define GSM48_IE_CALLING_SUB 0x5d /* 10.5.4.10 */ +#define GSM48_IE_CALLED_BCD 0x5e /* 10.5.4.7 */ +#define GSM48_IE_CALLED_SUB 0x6d /* 10.5.4.8 */ +#define GSM48_IE_REDIR_BCD 0x74 /* 10.5.4.21a */ +#define GSM48_IE_REDIR_SUB 0x75 /* 10.5.4.21b */ +#define GSM48_IE_LOWL_COMPAT 0x7c /* 10.5.4.18 */ +#define GSM48_IE_HIGHL_COMPAT 0x7d /* 10.5.4.16 */ +#define GSM48_IE_USER_USER 0x7e /* 10.5.4.25 */ +#define GSM48_IE_SS_VERS 0x7f /* 10.5.4.24 */ +#define GSM48_IE_MORE_DATA 0xa0 /* 10.5.4.19 */ +#define GSM48_IE_CLIR_SUPP 0xa1 /* 10.5.4.11a */ +#define GSM48_IE_CLIR_INVOC 0xa2 /* 10.5.4.11b */ +#define GSM48_IE_REV_C_SETUP 0xa3 /* 10.5.4.22a */ +#define GSM48_IE_REPEAT_CIR 0xd1 /* 10.5.4.22 */ +#define GSM48_IE_REPEAT_SEQ 0xd3 /* 10.5.4.22 */ + +/* Section 10.5.4.11 / Table 10.5.122 */ +#define GSM48_CAUSE_CS_GSM 0x60 + +/* Section 9.1.2 / Table 9.3 */ +#define GSM48_IE_FRQLIST_AFTER 0x05 +#define GSM48_IE_CELL_CH_DESC 0x62 +#define GSM48_IE_MSLOT_DESC 0x10 +#define GSM48_IE_CHANMODE_1 0x63 +#define GSM48_IE_CHANMODE_2 0x11 +#define GSM48_IE_CHANMODE_3 0x13 +#define GSM48_IE_CHANMODE_4 0x14 +#define GSM48_IE_CHANMODE_5 0x15 +#define GSM48_IE_CHANMODE_6 0x16 +#define GSM48_IE_CHANMODE_7 0x17 +#define GSM48_IE_CHANMODE_8 0x18 +#define GSM48_IE_CHANDESC_2 0x64 +/* FIXME */ + +/* Section 10.5.4.23 / Table 10.5.130 */ +enum gsm48_signal_val { + GSM48_SIGNAL_DIALTONE = 0x00, + GSM48_SIGNAL_RINGBACK = 0x01, + GSM48_SIGNAL_INTERCEPT = 0x02, + GSM48_SIGNAL_NET_CONG = 0x03, + GSM48_SIGNAL_BUSY = 0x04, + GSM48_SIGNAL_CONFIRM = 0x05, + GSM48_SIGNAL_ANSWER = 0x06, + GSM48_SIGNAL_CALL_WAIT = 0x07, + GSM48_SIGNAL_OFF_HOOK = 0x08, + GSM48_SIGNAL_OFF = 0x3f, + GSM48_SIGNAL_ALERT_OFF = 0x4f, +}; + +enum gsm48_cause_loc { + GSM48_CAUSE_LOC_USER = 0x00, + GSM48_CAUSE_LOC_PRN_S_LU = 0x01, + GSM48_CAUSE_LOC_PUN_S_LU = 0x02, + GSM48_CAUSE_LOC_TRANS_NET = 0x03, + GSM48_CAUSE_LOC_PUN_S_RU = 0x04, + GSM48_CAUSE_LOC_PRN_S_RU = 0x05, + /* not defined */ + GSM48_CAUSE_LOC_INN_NET = 0x07, + GSM48_CAUSE_LOC_NET_BEYOND = 0x0a, +}; + +/* Section 10.5.2.31 RR Cause / Table 10.5.70 */ +enum gsm48_rr_cause { + GSM48_RR_CAUSE_NORMAL = 0x00, + GSM48_RR_CAUSE_ABNORMAL_UNSPEC = 0x01, + GSM48_RR_CAUSE_ABNORMAL_UNACCT = 0x02, + GSM48_RR_CAUSE_ABNORMAL_TIMER = 0x03, + GSM48_RR_CAUSE_ABNORMAL_NOACT = 0x04, + GSM48_RR_CAUSE_PREMPTIVE_REL = 0x05, + GSM48_RR_CAUSE_HNDOVER_IMP = 0x06, + GSM48_RR_CAUSE_CHAN_MODE_UNACCT = 0x07, + GSM48_RR_CAUSE_FREQ_NOT_IMPL = 0x08, + GSM48_RR_CAUSE_CALL_CLEARED = 0x41, + GSM48_RR_CAUSE_SEMANT_INCORR = 0x5f, + GSM48_RR_CAUSE_INVALID_MAND_INF = 0x60, + GSM48_RR_CAUSE_MSG_TYPE_N = 0x61, + GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT= 0x62, + GSM48_RR_CAUSE_COND_IE_ERROR = 0x64, + GSM48_RR_CAUSE_NO_CELL_ALLOC_A = 0x65, + GSM48_RR_CAUSE_PROT_ERROR_UNSPC = 0x6f, +}; + +/* Section 10.5.4.11 CC Cause / Table 10.5.123 */ +enum gsm48_cc_cause { + GSM48_CC_CAUSE_UNASSIGNED_NR = 1, + GSM48_CC_CAUSE_NO_ROUTE = 3, + GSM48_CC_CAUSE_CHAN_UNACCEPT = 6, + GSM48_CC_CAUSE_OP_DET_BARRING = 8, + GSM48_CC_CAUSE_NORM_CALL_CLEAR = 16, + GSM48_CC_CAUSE_USER_BUSY = 17, + GSM48_CC_CAUSE_USER_NOTRESPOND = 18, + GSM48_CC_CAUSE_USER_ALERTING_NA = 19, + GSM48_CC_CAUSE_CALL_REJECTED = 21, + GSM48_CC_CAUSE_NUMBER_CHANGED = 22, + GSM48_CC_CAUSE_PRE_EMPTION = 25, + GSM48_CC_CAUSE_NONSE_USER_CLR = 26, + GSM48_CC_CAUSE_DEST_OOO = 27, + GSM48_CC_CAUSE_INV_NR_FORMAT = 28, + GSM48_CC_CAUSE_FACILITY_REJ = 29, + GSM48_CC_CAUSE_RESP_STATUS_INQ = 30, + GSM48_CC_CAUSE_NORMAL_UNSPEC = 31, + GSM48_CC_CAUSE_NO_CIRCUIT_CHAN = 34, + GSM48_CC_CAUSE_NETWORK_OOO = 38, + GSM48_CC_CAUSE_TEMP_FAILURE = 41, + GSM48_CC_CAUSE_SWITCH_CONG = 42, + GSM48_CC_CAUSE_ACC_INF_DISCARD = 43, + GSM48_CC_CAUSE_REQ_CHAN_UNAVAIL = 44, + GSM48_CC_CAUSE_RESOURCE_UNAVAIL = 47, + GSM48_CC_CAUSE_QOS_UNAVAIL = 49, + GSM48_CC_CAUSE_REQ_FAC_NOT_SUBSC= 50, + GSM48_CC_CAUSE_INC_BARRED_CUG = 55, + GSM48_CC_CAUSE_BEARER_CAP_UNAUTH= 57, + GSM48_CC_CAUSE_BEARER_CA_UNAVAIL= 58, + GSM48_CC_CAUSE_SERV_OPT_UNAVAIL = 63, + GSM48_CC_CAUSE_BEARERSERV_UNIMPL= 65, + GSM48_CC_CAUSE_ACM_GE_ACM_MAX = 68, + GSM48_CC_CAUSE_REQ_FAC_NOTIMPL = 69, + GSM48_CC_CAUSE_RESTR_BCAP_AVAIL = 70, + GSM48_CC_CAUSE_SERV_OPT_UNIMPL = 79, + GSM48_CC_CAUSE_INVAL_TRANS_ID = 81, + GSM48_CC_CAUSE_USER_NOT_IN_CUG = 87, + GSM48_CC_CAUSE_INCOMPAT_DEST = 88, + GSM48_CC_CAUSE_INVAL_TRANS_NET = 91, + GSM48_CC_CAUSE_SEMANTIC_INCORR = 95, + GSM48_CC_CAUSE_INVAL_MAND_INF = 96, + GSM48_CC_CAUSE_MSGTYPE_NOTEXIST = 97, + GSM48_CC_CAUSE_MSGTYPE_INCOMPAT = 98, + GSM48_CC_CAUSE_IE_NOTEXIST = 99, + GSM48_CC_CAUSE_COND_IE_ERR = 100, + GSM48_CC_CAUSE_MSG_INCOMP_STATE = 101, + GSM48_CC_CAUSE_RECOVERY_TIMER = 102, + GSM48_CC_CAUSE_PROTO_ERR = 111, + GSM48_CC_CAUSE_INTERWORKING = 127, +}; + +/* Annex G, GSM specific cause values for mobility management */ +enum gsm48_reject_value { + GSM48_REJECT_IMSI_UNKNOWN_IN_HLR = 2, + GSM48_REJECT_ILLEGAL_MS = 3, + GSM48_REJECT_IMSI_UNKNOWN_IN_VLR = 4, + GSM48_REJECT_IMEI_NOT_ACCEPTED = 5, + GSM48_REJECT_ILLEGAL_ME = 6, + GSM48_REJECT_PLMN_NOT_ALLOWED = 11, + GSM48_REJECT_LOC_NOT_ALLOWED = 12, + GSM48_REJECT_ROAMING_NOT_ALLOWED = 13, + GSM48_REJECT_NETWORK_FAILURE = 17, + GSM48_REJECT_CONGESTION = 22, + GSM48_REJECT_SRV_OPT_NOT_SUPPORTED = 32, + GSM48_REJECT_RQD_SRV_OPT_NOT_SUPPORTED = 33, + GSM48_REJECT_SRV_OPT_TMP_OUT_OF_ORDER = 34, + GSM48_REJECT_CALL_CAN_NOT_BE_IDENTIFIED = 38, + GSM48_REJECT_INCORRECT_MESSAGE = 95, + GSM48_REJECT_INVALID_MANDANTORY_INF = 96, + GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED = 97, + GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE = 98, + GSM48_REJECT_INF_ELEME_NOT_IMPLEMENTED = 99, + GSM48_REJECT_CONDTIONAL_IE_ERROR = 100, + GSM48_REJECT_MSG_NOT_COMPATIBLE = 101, + GSM48_REJECT_PROTOCOL_ERROR = 111, + + /* according to G.6 Additional cause codes for GMM */ + GSM48_REJECT_GPRS_NOT_ALLOWED = 7, + GSM48_REJECT_SERVICES_NOT_ALLOWED = 8, + GSM48_REJECT_MS_IDENTITY_NOT_DERVIVABLE = 9, + GSM48_REJECT_IMPLICITLY_DETACHED = 10, + GSM48_REJECT_GPRS_NOT_ALLOWED_IN_PLMN = 14, + GSM48_REJECT_MSC_TMP_NOT_REACHABLE = 16, +}; + +enum chreq_type { + CHREQ_T_EMERG_CALL, + CHREQ_T_CALL_REEST_TCH_F, + CHREQ_T_CALL_REEST_TCH_H, + CHREQ_T_CALL_REEST_TCH_H_DBL, + CHREQ_T_SDCCH, + CHREQ_T_TCH_F, + CHREQ_T_VOICE_CALL_TCH_H, + CHREQ_T_DATA_CALL_TCH_H, + CHREQ_T_LOCATION_UPD, + CHREQ_T_PAG_R_ANY_NECI0, + CHREQ_T_PAG_R_ANY_NECI1, + CHREQ_T_PAG_R_TCH_F, + CHREQ_T_PAG_R_TCH_FH, + CHREQ_T_LMU, + CHREQ_T_RESERVED_SDCCH, + CHREQ_T_RESERVED_IGNORE, +}; + +/* Chapter 11.3 */ +#define GSM48_T301 180, 0 +#define GSM48_T303 30, 0 +#define GSM48_T305 30, 0 +#define GSM48_T306 30, 0 +#define GSM48_T308 10, 0 +#define GSM48_T310 180, 0 +#define GSM48_T313 30, 0 +#define GSM48_T323 30, 0 +#define GSM48_T331 30, 0 +#define GSM48_T333 30, 0 +#define GSM48_T334 25, 0 /* min 15 */ +#define GSM48_T338 30, 0 + +/* Chapter 5.1.2.2 */ +#define GSM_CSTATE_NULL 0 +#define GSM_CSTATE_INITIATED 1 +#define GSM_CSTATE_MO_CALL_PROC 3 +#define GSM_CSTATE_CALL_DELIVERED 4 +#define GSM_CSTATE_CALL_PRESENT 6 +#define GSM_CSTATE_CALL_RECEIVED 7 +#define GSM_CSTATE_CONNECT_REQUEST 8 +#define GSM_CSTATE_MO_TERM_CALL_CONF 9 +#define GSM_CSTATE_ACTIVE 10 +#define GSM_CSTATE_DISCONNECT_REQ 12 +#define GSM_CSTATE_DISCONNECT_IND 12 +#define GSM_CSTATE_RELEASE_REQ 19 +#define GSM_CSTATE_MO_ORIG_MODIFY 26 +#define GSM_CSTATE_MO_TERM_MODIFY 27 +#define GSM_CSTATE_CONNECT_IND 28 + +#define SBIT(a) (1 << a) +#define ALL_STATES 0xffffffff + +/* Table 10.5.3/3GPP TS 04.08: Location Area Identification information element */ +#define GSM_LAC_RESERVED_DETACHED 0x0 +#define GSM_LAC_RESERVED_ALL_BTS 0xfffe + +/* GSM 04.08 Bearer Capability: Information Transfer Capability */ +enum gsm48_bcap_itcap { + GSM48_BCAP_ITCAP_SPEECH = 0, + GSM48_BCAP_ITCAP_UNR_DIG_INF = 1, + GSM48_BCAP_ITCAP_3k1_AUDIO = 2, + GSM48_BCAP_ITCAP_FAX_G3 = 3, + GSM48_BCAP_ITCAP_OTHER = 5, + GSM48_BCAP_ITCAP_RESERVED = 7, +}; + +/* GSM 04.08 Bearer Capability: Transfer Mode */ +enum gsm48_bcap_tmod { + GSM48_BCAP_TMOD_CIRCUIT = 0, + GSM48_BCAP_TMOD_PACKET = 1, +}; + +/* GSM 04.08 Bearer Capability: Coding Standard */ +enum gsm48_bcap_coding { + GSM48_BCAP_CODING_GSM_STD = 0, +}; + +/* GSM 04.08 Bearer Capability: Radio Channel Requirements */ +enum gsm48_bcap_rrq { + GSM48_BCAP_RRQ_FR_ONLY = 1, + GSM48_BCAP_RRQ_DUAL_HR = 2, + GSM48_BCAP_RRQ_DUAL_FR = 3, +}; + + +#define GSM48_TMSI_LEN 5 +#define GSM48_MID_TMSI_LEN (GSM48_TMSI_LEN + 2) +#define GSM48_MI_SIZE 32 + + +struct msgb; +struct gsm_bts; +struct gsm_subscriber; +struct gsm_network; +struct gsm_trans; + +/* config options controlling the behaviour of the lower leves */ +void gsm0408_allow_everyone(int allow); + +int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id); +void gsm0408_generate_lai(struct gsm48_loc_area_id *lai48, u_int16_t mcc, + u_int16_t mnc, u_int16_t lac); +enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci); +enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci); + +int gsm48_tx_mm_info(struct gsm_lchan *lchan); +int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq); +int gsm48_tx_mm_auth_rej(struct gsm_lchan *lchan); +struct msgb *gsm48_msgb_alloc(void); +int gsm48_sendmsg(struct msgb *msg, struct gsm_trans *trans); +int gsm48_generate_mid_from_tmsi(u_int8_t *buf, u_int32_t tmsi); +int gsm48_generate_mid_from_imsi(u_int8_t *buf, const char* imsi); +int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len); + +int gsm48_send_rr_release(struct gsm_lchan *lchan); +int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv); +int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id, + u_int8_t apdu_len, const u_int8_t *apdu); +int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, u_int8_t power_class); +int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan, + u_int8_t power_command, u_int8_t ho_ref); + +int bsc_upqueue(struct gsm_network *net); + +int mncc_send(struct gsm_network *net, int msg_type, void *arg); + +/* convert a ASCII phone number to call-control BCD */ +int encode_bcd_number(u_int8_t *bcd_lv, u_int8_t max_len, + int h_len, const char *input); +int decode_bcd_number(char *output, int output_len, const u_int8_t *bcd_lv, + int h_len); + +extern const char *gsm0408_cc_msg_names[]; + +int send_siemens_mrpci(struct gsm_lchan *lchan, u_int8_t *classmark2_lv); +int gsm48_paging_extract_mi(struct msgb *msg, char *mi_string, u_int8_t *mi_type); +int gsm48_handle_paging_resp(struct msgb *msg, struct gsm_subscriber *subscr); + +int gsm48_lchan_modify(struct gsm_lchan *lchan, u_int8_t lchan_mode); +int gsm48_rx_rr_modif_ack(struct msgb *msg); +int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg); + + +#endif diff --git a/src/host/libosmocom/include/osmocom/gsmtap.h b/src/host/libosmocom/include/osmocom/gsmtap.h new file mode 100644 index 00000000..316e73d1 --- /dev/null +++ b/src/host/libosmocom/include/osmocom/gsmtap.h @@ -0,0 +1,60 @@ +#ifndef _GSMTAP_H +#define _GSMTAP_H + +/* gsmtap header, pseudo-header in front of the actua GSM payload*/ + +#include <sys/types.h> + +#define GSMTAP_VERSION 0x01 + +#define GSMTAP_TYPE_UM 0x01 +#define GSMTAP_TYPE_ABIS 0x02 +#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */ + +#define GSMTAP_BURST_UNKNOWN 0x00 +#define GSMTAP_BURST_FCCH 0x01 +#define GSMTAP_BURST_PARTIAL_SCH 0x02 +#define GSMTAP_BURST_SCH 0x03 +#define GSMTAP_BURST_CTS_SCH 0x04 +#define GSMTAP_BURST_COMPACT_SCH 0x05 +#define GSMTAP_BURST_NORMAL 0x06 +#define GSMTAP_BURST_DUMMY 0x07 +#define GSMTAP_BURST_ACCESS 0x08 +#define GSMTAP_BURST_NONE 0x09 + +struct gsmtap_hdr { + u_int8_t version; /* version, set to 0x01 currently */ + u_int8_t hdr_len; /* length in number of 32bit words */ + u_int8_t type; /* see GSMTAP_TYPE_* */ + u_int8_t timeslot; /* timeslot (0..7 on Um) */ + + u_int16_t arfcn; /* ARFCN (frequency) */ + u_int8_t noise_db; /* noise figure in dB */ + u_int8_t signal_db; /* signal level in dB */ + + u_int32_t frame_number; /* GSM Frame Number (FN) */ + + u_int8_t burst_type; /* Type of burst, see above */ + u_int8_t antenna_nr; /* Antenna Number */ + u_int16_t res; /* reserved for future use (RFU) */ + +} __attribute__((packed)); + + +/* PCAP related definitions */ +#define TCPDUMP_MAGIC 0xa1b2c3d4 +#ifndef LINKTYPE_GSMTAP +#define LINKTYPE_GSMTAP 2342 +#endif +struct pcap_timeval { + int32_t tv_sec; + int32_t tv_usec; +}; + +struct pcap_sf_pkthdr { + struct pcap_timeval ts; /* time stamp */ + u_int32_t caplen; /* lenght of portion present */ + u_int32_t len; /* length of this packet */ +}; + +#endif /* _GSMTAP_H */ diff --git a/src/host/libosmocom/include/osmocom/linuxlist.h b/src/host/libosmocom/include/osmocom/linuxlist.h new file mode 100644 index 00000000..6b77a31d --- /dev/null +++ b/src/host/libosmocom/include/osmocom/linuxlist.h @@ -0,0 +1,360 @@ +#ifndef _LINUX_LLIST_H +#define _LINUX_LLIST_H + +#include <stddef.h> + +#ifndef inline +#define inline __inline__ +#endif + +static inline void prefetch(const void *x) {;} + +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (typeof( ((type *)0)->member ) *)(ptr); \ + (type *)( (char *)__mptr - offsetof(type, member) );}) + + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized llist entries. + */ +#define LLIST_POISON1 ((void *) 0x00100100) +#define LLIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked llist implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole llists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct llist_head { + struct llist_head *next, *prev; +}; + +#define LLIST_HEAD_INIT(name) { &(name), &(name) } + +#define LLIST_HEAD(name) \ + struct llist_head name = LLIST_HEAD_INIT(name) + +#define INIT_LLIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +static inline void __llist_add(struct llist_head *_new, + struct llist_head *prev, + struct llist_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * llist_add - add a new entry + * @new: new entry to be added + * @head: llist head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void llist_add(struct llist_head *_new, struct llist_head *head) +{ + __llist_add(_new, head, head->next); +} + +/** + * llist_add_tail - add a new entry + * @new: new entry to be added + * @head: llist head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head) +{ + __llist_add(_new, head->prev, head); +} + +/* + * Delete a llist entry by making the prev/next entries + * point to each other. + * + * This is only for internal llist manipulation where we know + * the prev/next entries already! + */ +static inline void __llist_del(struct llist_head * prev, struct llist_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * llist_del - deletes entry from llist. + * @entry: the element to delete from the llist. + * Note: llist_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void llist_del(struct llist_head *entry) +{ + __llist_del(entry->prev, entry->next); + entry->next = (struct llist_head *)LLIST_POISON1; + entry->prev = (struct llist_head *)LLIST_POISON2; +} + +/** + * llist_del_init - deletes entry from llist and reinitialize it. + * @entry: the element to delete from the llist. + */ +static inline void llist_del_init(struct llist_head *entry) +{ + __llist_del(entry->prev, entry->next); + INIT_LLIST_HEAD(entry); +} + +/** + * llist_move - delete from one llist and add as another's head + * @llist: the entry to move + * @head: the head that will precede our entry + */ +static inline void llist_move(struct llist_head *llist, struct llist_head *head) +{ + __llist_del(llist->prev, llist->next); + llist_add(llist, head); +} + +/** + * llist_move_tail - delete from one llist and add as another's tail + * @llist: the entry to move + * @head: the head that will follow our entry + */ +static inline void llist_move_tail(struct llist_head *llist, + struct llist_head *head) +{ + __llist_del(llist->prev, llist->next); + llist_add_tail(llist, head); +} + +/** + * llist_empty - tests whether a llist is empty + * @head: the llist to test. + */ +static inline int llist_empty(const struct llist_head *head) +{ + return head->next == head; +} + +static inline void __llist_splice(struct llist_head *llist, + struct llist_head *head) +{ + struct llist_head *first = llist->next; + struct llist_head *last = llist->prev; + struct llist_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * llist_splice - join two llists + * @llist: the new llist to add. + * @head: the place to add it in the first llist. + */ +static inline void llist_splice(struct llist_head *llist, struct llist_head *head) +{ + if (!llist_empty(llist)) + __llist_splice(llist, head); +} + +/** + * llist_splice_init - join two llists and reinitialise the emptied llist. + * @llist: the new llist to add. + * @head: the place to add it in the first llist. + * + * The llist at @llist is reinitialised + */ +static inline void llist_splice_init(struct llist_head *llist, + struct llist_head *head) +{ + if (!llist_empty(llist)) { + __llist_splice(llist, head); + INIT_LLIST_HEAD(llist); + } +} + +/** + * llist_entry - get the struct for this entry + * @ptr: the &struct llist_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the llist_struct within the struct. + */ +#define llist_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * llist_for_each - iterate over a llist + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __llist_for_each - iterate over a llist + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + * + * This variant differs from llist_for_each() in that it's the + * simplest possible llist iteration code, no prefetching is done. + * Use this for code that knows the llist to be very short (empty + * or 1 entry) most of the time. + */ +#define __llist_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * llist_for_each_prev - iterate over a llist backwards + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * llist_for_each_safe - iterate over a llist safe against removal of llist entry + * @pos: the &struct llist_head to use as a loop counter. + * @n: another &struct llist_head to use as temporary storage + * @head: the head for your llist. + */ +#define llist_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * llist_for_each_entry - iterate over llist of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry(pos, head, member) \ + for (pos = llist_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * llist_for_each_entry_reverse - iterate backwards over llist of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_reverse(pos, head, member) \ + for (pos = llist_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + +/** + * llist_for_each_entry_continue - iterate over llist of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_continue(pos, head, member) \ + for (pos = llist_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * llist_for_each_entry_safe - iterate over llist of given type safe against removal of llist entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_safe(pos, n, head, member) \ + for (pos = llist_entry((head)->next, typeof(*pos), member), \ + n = llist_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = llist_entry(n->member.next, typeof(*n), member)) + +/** + * llist_for_each_rcu - iterate over an rcu-protected llist + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each_rcu(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next)) + +#define __llist_for_each_rcu(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next, ({ smp_read_barrier_depends(); 0;})) + +/** + * llist_for_each_safe_rcu - iterate over an rcu-protected llist safe + * against removal of llist entry + * @pos: the &struct llist_head to use as a loop counter. + * @n: another &struct llist_head to use as temporary storage + * @head: the head for your llist. + */ +#define llist_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next) + +/** + * llist_for_each_entry_rcu - iterate over rcu llist of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your llist. + * @member: the name of the llist_struct within the struct. + */ +#define llist_for_each_entry_rcu(pos, head, member) \ + for (pos = llist_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = llist_entry(pos->member.next, typeof(*pos), member), \ + ({ smp_read_barrier_depends(); 0;}), \ + prefetch(pos->member.next)) + + +/** + * llist_for_each_continue_rcu - iterate over an rcu-protected llist + * continuing after existing point. + * @pos: the &struct llist_head to use as a loop counter. + * @head: the head for your llist. + */ +#define llist_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \ + (pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next)) + + +#endif diff --git a/src/host/libosmocom/include/osmocom/meas_rep.h b/src/host/libosmocom/include/osmocom/meas_rep.h new file mode 100644 index 00000000..3c2c8d1c --- /dev/null +++ b/src/host/libosmocom/include/osmocom/meas_rep.h @@ -0,0 +1,85 @@ +#ifndef _MEAS_REP_H +#define _MEAS_REP_H + +#define MRC_F_PROCESSED 0x0001 + +/* extracted from a L3 measurement report IE */ +struct gsm_meas_rep_cell { + u_int8_t rxlev; + u_int8_t bsic; + u_int8_t neigh_idx; + u_int16_t arfcn; + unsigned int flags; +}; + +/* RX Level and RX Quality */ +struct gsm_rx_lev_qual { + u_int8_t rx_lev; + u_int8_t rx_qual; +}; + +/* unidirectional measumrement report */ +struct gsm_meas_rep_unidir { + struct gsm_rx_lev_qual full; + struct gsm_rx_lev_qual sub; +}; + +#define MEAS_REP_F_UL_DTX 0x01 +#define MEAS_REP_F_DL_VALID 0x02 +#define MEAS_REP_F_BA1 0x04 +#define MEAS_REP_F_DL_DTX 0x08 +#define MEAS_REP_F_MS_TO 0x10 +#define MEAS_REP_F_MS_L1 0x20 +#define MEAS_REP_F_FPC 0x40 + +/* parsed uplink and downlink measurement result */ +struct gsm_meas_rep { + /* back-pointer to the logical channel */ + struct gsm_lchan *lchan; + + /* number of the measurement report */ + u_int8_t nr; + /* flags, see MEAS_REP_F_* */ + unsigned int flags; + + /* uplink and downlink rxlev, rxqual; full and sub */ + struct gsm_meas_rep_unidir ul; + struct gsm_meas_rep_unidir dl; + + u_int8_t bs_power; + u_int8_t ms_timing_offset; + struct { + int8_t pwr; /* MS power in dBm */ + u_int8_t ta; /* MS timing advance */ + } ms_l1; + + /* neighbor measurement reports for up to 6 cells */ + int num_cell; + struct gsm_meas_rep_cell cell[6]; +}; + +enum meas_rep_field { + MEAS_REP_DL_RXLEV_FULL, + MEAS_REP_DL_RXLEV_SUB, + MEAS_REP_DL_RXQUAL_FULL, + MEAS_REP_DL_RXQUAL_SUB, + MEAS_REP_UL_RXLEV_FULL, + MEAS_REP_UL_RXLEV_SUB, + MEAS_REP_UL_RXQUAL_FULL, + MEAS_REP_UL_RXQUAL_SUB, +}; + +/* obtain an average over the last 'num' fields in the meas reps */ +int get_meas_rep_avg(const struct gsm_lchan *lchan, + enum meas_rep_field field, unsigned int num); + +/* Check if N out of M last values for FIELD are >= bd */ +int meas_rep_n_out_of_m_be(const struct gsm_lchan *lchan, + enum meas_rep_field field, + unsigned int n, unsigned int m, int be); + +unsigned int calc_initial_idx(unsigned int array_size, + unsigned int meas_rep_idx, + unsigned int num_values); + +#endif /* _MEAS_REP_H */ diff --git a/src/host/libosmocom/include/osmocom/msgb.h b/src/host/libosmocom/include/osmocom/msgb.h new file mode 100644 index 00000000..d0efc90b --- /dev/null +++ b/src/host/libosmocom/include/osmocom/msgb.h @@ -0,0 +1,114 @@ +#ifndef _MSGB_H +#define _MSGB_H + +/* (C) 2008 by Harald Welte <laforge@gnumonks.org> + * 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 <sys/types.h> +#include "linuxlist.h" + +struct bts_link; + +struct msgb { + struct llist_head list; + + /* ptr to the physical E1 link to the BTS(s) */ + struct gsm_bts_link *bts_link; + + /* Part of which TRX logical channel we were received / transmitted */ + struct gsm_bts_trx *trx; + struct gsm_lchan *lchan; + + unsigned char *l2h; + unsigned char *l3h; + unsigned char *smsh; + + u_int16_t data_len; + u_int16_t len; + + unsigned char *head; + unsigned char *tail; + unsigned char *data; + unsigned char _data[0]; +}; + +extern struct msgb *msgb_alloc(u_int16_t size, const char *name); +extern void msgb_free(struct msgb *m); +extern void msgb_enqueue(struct llist_head *queue, struct msgb *msg); +extern struct msgb *msgb_dequeue(struct llist_head *queue); +extern void msgb_reset(struct msgb *m); + +#define msgb_l2(m) ((void *)(m->l2h)) +#define msgb_l3(m) ((void *)(m->l3h)) +#define msgb_sms(m) ((void *)(m->smsh)) + +static inline unsigned int msgb_l2len(const struct msgb *msgb) +{ + return msgb->tail - (u_int8_t *)msgb_l2(msgb); +} + +static inline unsigned int msgb_l3len(const struct msgb *msgb) +{ + return msgb->tail - (u_int8_t *)msgb_l3(msgb); +} + +static inline unsigned int msgb_headlen(const struct msgb *msgb) +{ + return msgb->len - msgb->data_len; +} +static inline unsigned char *msgb_put(struct msgb *msgb, unsigned int len) +{ + unsigned char *tmp = msgb->tail; + msgb->tail += len; + msgb->len += len; + return tmp; +} +static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len) +{ + msgb->data -= len; + msgb->len += len; + return msgb->data; +} +static inline unsigned char *msgb_pull(struct msgb *msgb, unsigned int len) +{ + msgb->len -= len; + return msgb->data += len; +} +static inline int msgb_tailroom(const struct msgb *msgb) +{ + return (msgb->data + msgb->data_len) - msgb->tail; +} + +/* increase the headroom of an empty msgb, reducing the tailroom */ +static inline void msgb_reserve(struct msgb *msg, int len) +{ + msg->data += len; + msg->tail += len; +} + +static inline struct msgb *msgb_alloc_headroom(int size, int headroom, + const char *name) +{ + struct msgb *msg = msgb_alloc(size, name); + if (msg) + msgb_reserve(msg, headroom); + return msg; +} + +#endif /* _MSGB_H */ diff --git a/src/host/libosmocom/include/osmocom/select.h b/src/host/libosmocom/include/osmocom/select.h new file mode 100644 index 00000000..2d8b3ec0 --- /dev/null +++ b/src/host/libosmocom/include/osmocom/select.h @@ -0,0 +1,22 @@ +#ifndef _BSC_SELECT_H +#define _BSC_SELECT_H + +#include "linuxlist.h" + +#define BSC_FD_READ 0x0001 +#define BSC_FD_WRITE 0x0002 +#define BSC_FD_EXCEPT 0x0004 + +struct bsc_fd { + struct llist_head list; + int fd; + unsigned int when; + int (*cb)(struct bsc_fd *fd, unsigned int what); + void *data; + unsigned int priv_nr; +}; + +int bsc_register_fd(struct bsc_fd *fd); +void bsc_unregister_fd(struct bsc_fd *fd); +int bsc_select_main(int polling); +#endif /* _BSC_SELECT_H */ diff --git a/src/host/libosmocom/include/osmocom/talloc.h b/src/host/libosmocom/include/osmocom/talloc.h new file mode 100644 index 00000000..1c243b80 --- /dev/null +++ b/src/host/libosmocom/include/osmocom/talloc.h @@ -0,0 +1,192 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#define HAVE_VA_COPY + +/* this is only needed for compatibility with the old talloc */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#ifndef __location__ +#define __TALLOC_STRING_LINE1__(s) #s +#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) +#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) +#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ +#endif + +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)); __talloc_steal_ret; }) +#else +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal((ctx),(ptr)) +#endif + +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference((ctx),(ptr)) +#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) + +/* useful macros for creating type checked pointers */ +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) + +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) + +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) + +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) +#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) + +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) + +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) + +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) + +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) +#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) +#endif + +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) + +/* The following definitions come from talloc.c */ +void *_talloc(const void *context, size_t size); +void *talloc_pool(const void *context, size_t size); +void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); +int talloc_increase_ref_count(const void *ptr); +size_t talloc_reference_count(const void *ptr); +void *_talloc_reference(const void *context, const void *ptr); +int talloc_unlink(const void *context, void *ptr); +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void talloc_set_name_const(const void *ptr, const char *name); +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +void *talloc_named_const(const void *context, size_t size, const char *name); +const char *talloc_get_name(const void *ptr); +void *talloc_check_name(const void *ptr, const char *name); +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); +void *talloc_parent(const void *ptr); +const char *talloc_parent_name(const void *ptr); +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +int talloc_free(void *ptr); +void talloc_free_children(void *ptr); +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +void *_talloc_steal(const void *new_ctx, const void *ptr); +void *_talloc_move(const void *new_ctx, const void *pptr); +size_t talloc_total_size(const void *ptr); +size_t talloc_total_blocks(const void *ptr); +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); +void talloc_report_full(const void *ptr, FILE *f); +void talloc_report(const void *ptr, FILE *f); +void talloc_enable_null_tracking(void); +void talloc_disable_null_tracking(void); +void talloc_enable_leak_report(void); +void talloc_enable_leak_report_full(void); +void *_talloc_zero(const void *ctx, size_t size, const char *name); +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); +void *talloc_autofree_context(void); +size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); +int talloc_is_parent(const void *context, const void *ptr); + +char *talloc_strdup(const void *t, const char *p); +char *talloc_strdup_append(char *s, const char *a); +char *talloc_strdup_append_buffer(char *s, const char *a); + +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_strndup_append(char *s, const char *a, size_t n); +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); + +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); + +#endif diff --git a/src/host/libosmocom/include/osmocom/timer.h b/src/host/libosmocom/include/osmocom/timer.h new file mode 100644 index 00000000..fee888bf --- /dev/null +++ b/src/host/libosmocom/include/osmocom/timer.h @@ -0,0 +1,72 @@ +/* + * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org> + * 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. + * + */ + +#ifndef TIMER_H +#define TIMER_H + +#include <sys/time.h> + +#include "linuxlist.h" + +/** + * Timer management: + * - Create a struct timer_list + * - Fill out timeout and use add_timer or + * use schedule_timer to schedule a timer in + * x seconds and microseconds from now... + * - Use del_timer to remove the timer + * + * Internally: + * - We hook into select.c to give a timeval of the + * nearest timer. On already passed timers we give + * it a 0 to immediately fire after the select + * - update_timers will call the callbacks and remove + * the timers. + * + */ +struct timer_list { + struct llist_head entry; + struct timeval timeout; + unsigned int active : 1; + unsigned int handled : 1; + unsigned int in_list : 1; + + void (*cb)(void*); + void *data; +}; + +/** + * timer management + */ +void bsc_add_timer(struct timer_list *timer); +void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds); +void bsc_del_timer(struct timer_list *timer); +int bsc_timer_pending(struct timer_list *timer); + + +/** + * internal timer list management + */ +struct timeval *bsc_nearest_timer(); +void bsc_prepare_timers(); +int bsc_update_timers(); +int bsc_timer_check(void); + +#endif diff --git a/src/host/libosmocom/src/debug.c b/src/host/libosmocom/src/debug.c new file mode 100644 index 00000000..5dc2b225 --- /dev/null +++ b/src/host/libosmocom/src/debug.c @@ -0,0 +1,463 @@ +/* Debugging/Logging support code */ +/* (C) 2008 by Harald Welte <laforge@gnumonks.org> + * (C) 2008 by Holger Hans Peter Freyther <zecke@selfish.org> + * 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 <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <time.h> +#include <errno.h> + +#include <osmocom/debug.h> +#include <osmocom/talloc.h> + +struct value_string { + unsigned int value; + const char *str; +}; + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +struct gsm_bts; +struct gsm_subscriber; +struct gsm_lchan; + +/* default categories */ +static struct debug_category default_categories[Debug_LastEntry] = { + [DRLL] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DCC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DNM] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DRR] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DRSL] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DMM] = { .enabled = 1, .loglevel = LOGL_INFO }, + [DMNCC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DSMS] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DPAG] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DMEAS] = { .enabled = 0, .loglevel = LOGL_NOTICE }, + [DMI] = { .enabled = 0, .loglevel = LOGL_NOTICE }, + [DMIB] = { .enabled = 0, .loglevel = LOGL_NOTICE }, + [DMUX] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DINP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DSCCP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DMSC] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DMGCP] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DHO] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DDB] = { .enabled = 1, .loglevel = LOGL_NOTICE }, + [DREF] = { .enabled = 0, .loglevel = LOGL_NOTICE }, +}; + +const char *get_value_string(const struct value_string *vs, u_int32_t val) +{ + int i; + + for (i = 0;; i++) { + if (vs[i].value == 0 && vs[i].str == NULL) + break; + if (vs[i].value == val) + return vs[i].str; + } + return "unknown"; +} + +int get_string_value(const struct value_string *vs, const char *str) +{ + int i; + + for (i = 0;; i++) { + if (vs[i].value == 0 && vs[i].str == NULL) + break; + if (!strcasecmp(vs[i].str, str)) + return vs[i].value; + } + return -EINVAL; +} + +struct debug_info { + const char *name; + const char *color; + const char *description; + int number; + int position; +}; + +struct debug_context { + struct gsm_lchan *lchan; + struct gsm_subscriber *subscr; + struct gsm_bts *bts; +}; + +static struct debug_context debug_context; +static void *tall_dbg_ctx = NULL; +static LLIST_HEAD(target_list); + +#define DEBUG_CATEGORY(NUMBER, NAME, COLOR, DESCRIPTION) \ + { .name = NAME, .color = COLOR, .description = DESCRIPTION, .number = NUMBER }, + +static const struct debug_info debug_info[] = { + DEBUG_CATEGORY(DRLL, "DRLL", "\033[1;31m", "") + DEBUG_CATEGORY(DCC, "DCC", "\033[1;32m", "") + DEBUG_CATEGORY(DMM, "DMM", "\033[1;33m", "") + DEBUG_CATEGORY(DRR, "DRR", "\033[1;34m", "") + DEBUG_CATEGORY(DRSL, "DRSL", "\033[1;35m", "") + DEBUG_CATEGORY(DNM, "DNM", "\033[1;36m", "") + DEBUG_CATEGORY(DSMS, "DSMS", "\033[1;37m", "") + DEBUG_CATEGORY(DPAG, "DPAG", "\033[1;38m", "") + DEBUG_CATEGORY(DMNCC, "DMNCC","\033[1;39m", "") + DEBUG_CATEGORY(DINP, "DINP", "", "") + DEBUG_CATEGORY(DMI, "DMI", "", "") + DEBUG_CATEGORY(DMIB, "DMIB", "", "") + DEBUG_CATEGORY(DMUX, "DMUX", "", "") + DEBUG_CATEGORY(DMEAS, "DMEAS", "", "") + DEBUG_CATEGORY(DSCCP, "DSCCP", "", "") + DEBUG_CATEGORY(DMSC, "DMSC", "", "") + DEBUG_CATEGORY(DMGCP, "DMGCP", "", "") + DEBUG_CATEGORY(DHO, "DHO", "", "") + DEBUG_CATEGORY(DDB, "DDB", "", "") + DEBUG_CATEGORY(DDB, "DREF", "", "") +}; + +static const struct value_string loglevel_strs[] = { + { 0, "EVERYTHING" }, + { 1, "DEBUG" }, + { 3, "INFO" }, + { 5, "NOTICE" }, + { 7, "ERROR" }, + { 8, "FATAL" }, + { 0, NULL }, +}; + +int debug_parse_level(const char *lvl) +{ + return get_string_value(loglevel_strs, lvl); +} + +int debug_parse_category(const char *category) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { + if (!strcasecmp(debug_info[i].name+1, category)) + return debug_info[i].number; + } + + return -EINVAL; +} + +/* + * Parse the category mask. + * The format can be this: category1:category2:category3 + * or category1,2:category2,3:... + */ +void debug_parse_category_mask(struct debug_target* target, const char *_mask) +{ + int i = 0; + char *mask = strdup(_mask); + char *category_token = NULL; + + /* Disable everything to enable it afterwards */ + for (i = 0; i < ARRAY_SIZE(target->categories); ++i) + target->categories[i].enabled = 0; + + category_token = strtok(mask, ":"); + do { + for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { + char* colon = strstr(category_token, ","); + int length = strlen(category_token); + + if (colon) + length = colon - category_token; + + if (strncasecmp(debug_info[i].name, category_token, length) == 0) { + int number = debug_info[i].number; + int level = 0; + + if (colon) + level = atoi(colon+1); + + target->categories[number].enabled = 1; + target->categories[number].loglevel = level; + } + } + } while ((category_token = strtok(NULL, ":"))); + + free(mask); +} + +static const char* color(int subsys) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(debug_info); ++i) { + if (debug_info[i].number == subsys) + return debug_info[i].color; + } + + return ""; +} + +static void _output(struct debug_target *target, unsigned int subsys, char *file, int line, + int cont, const char *format, va_list ap) +{ + char col[30]; + char sub[30]; + char tim[30]; + char buf[4096]; + char final[4096]; + + /* prepare the data */ + col[0] = '\0'; + sub[0] = '\0'; + tim[0] = '\0'; + buf[0] = '\0'; + + /* are we using color */ + if (target->use_color) { + snprintf(col, sizeof(col), "%s", color(subsys)); + col[sizeof(col)-1] = '\0'; + } + vsnprintf(buf, sizeof(buf), format, ap); + buf[sizeof(buf)-1] = '\0'; + + if (!cont) { + if (target->print_timestamp) { + char *timestr; + time_t tm; + tm = time(NULL); + timestr = ctime(&tm); + timestr[strlen(timestr)-1] = '\0'; + snprintf(tim, sizeof(tim), "%s ", timestr); + tim[sizeof(tim)-1] = '\0'; + } + snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line); + sub[sizeof(sub)-1] = '\0'; + } + + snprintf(final, sizeof(final), "%s%s%s%s\033[0;m", col, tim, sub, buf); + final[sizeof(final)-1] = '\0'; + target->output(target, final); +} + + +static void _debugp(unsigned int subsys, int level, char *file, int line, + int cont, const char *format, va_list ap) +{ + struct debug_target *tar; + + llist_for_each_entry(tar, &target_list, entry) { + struct debug_category *category; + int output = 0; + + category = &tar->categories[subsys]; + /* subsystem is not supposed to be debugged */ + if (!category->enabled) + continue; + + /* Check the global log level */ + if (tar->loglevel != 0 && level < tar->loglevel) + continue; + + /* Check the category log level */ + if (category->loglevel != 0 && level < category->loglevel) + continue; + + /* + * Apply filters here... if that becomes messy we will need to put + * filters in a list and each filter will say stop, continue, output + */ + if ((tar->filter_map & DEBUG_FILTER_ALL) != 0) { + output = 1; +#if 0 + } else if ((tar->filter_map & DEBUG_FILTER_IMSI) != 0 + && debug_context.subscr && strcmp(debug_context.subscr->imsi, tar->imsi_filter) == 0) { + output = 1; +#endif + } + + if (output) { + /* FIXME: copying the va_list is an ugly workaround against a bug + * hidden somewhere in _output. If we do not copy here, the first + * call to _output() will corrupt the va_list contents, and any + * further _output() calls with the same va_list will segfault */ + va_list bp; + va_copy(bp, ap); + _output(tar, subsys, file, line, cont, format, bp); + va_end(bp); + } + } +} + +void debugp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _debugp(subsys, LOGL_DEBUG, file, line, cont, format, ap); + va_end(ap); +} + +void debugp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + _debugp(subsys, level, file, line, cont, format, ap); + va_end(ap); +} + +static char hexd_buff[4096]; + +char *hexdump(const unsigned char *buf, int len) +{ + int i; + char *cur = hexd_buff; + + hexd_buff[0] = 0; + for (i = 0; i < len; i++) { + int len_remain = sizeof(hexd_buff) - (cur - hexd_buff); + int rc = snprintf(cur, len_remain, "%02x ", buf[i]); + if (rc <= 0) + break; + cur += rc; + } + hexd_buff[sizeof(hexd_buff)-1] = 0; + return hexd_buff; +} + + + +void debug_add_target(struct debug_target *target) +{ + llist_add_tail(&target->entry, &target_list); +} + +void debug_del_target(struct debug_target *target) +{ + llist_del(&target->entry); +} + +void debug_reset_context(void) +{ + memset(&debug_context, 0, sizeof(debug_context)); +} + +/* currently we are not reffing these */ +void debug_set_context(int ctx, void *value) +{ + switch (ctx) { + case BSC_CTX_LCHAN: + debug_context.lchan = (struct gsm_lchan *) value; + break; + case BSC_CTX_SUBSCR: + debug_context.subscr = (struct gsm_subscriber *) value; + break; + case BSC_CTX_BTS: + debug_context.bts = (struct gsm_bts *) value; + break; + case BSC_CTX_SCCP: + break; + default: + break; + } +} + +void debug_set_imsi_filter(struct debug_target *target, const char *imsi) +{ + if (imsi) { + target->filter_map |= DEBUG_FILTER_IMSI; + target->imsi_filter = talloc_strdup(target, imsi); + } else if (target->imsi_filter) { + target->filter_map &= ~DEBUG_FILTER_IMSI; + talloc_free(target->imsi_filter); + target->imsi_filter = NULL; + } +} + +void debug_set_all_filter(struct debug_target *target, int all) +{ + if (all) + target->filter_map |= DEBUG_FILTER_ALL; + else + target->filter_map &= ~DEBUG_FILTER_ALL; +} + +void debug_set_use_color(struct debug_target *target, int use_color) +{ + target->use_color = use_color; +} + +void debug_set_print_timestamp(struct debug_target *target, int print_timestamp) +{ + target->print_timestamp = print_timestamp; +} + +void debug_set_log_level(struct debug_target *target, int log_level) +{ + target->loglevel = log_level; +} + +void debug_set_category_filter(struct debug_target *target, int category, int enable, int level) +{ + if (category >= Debug_LastEntry) + return; + target->categories[category].enabled = !!enable; + target->categories[category].loglevel = level; +} + +static void _stderr_output(struct debug_target *target, const char *log) +{ + fprintf(target->tgt_stdout.out, "%s", log); + fflush(target->tgt_stdout.out); +} + +struct debug_target *debug_target_create(void) +{ + struct debug_target *target; + + target = talloc_zero(tall_dbg_ctx, struct debug_target); + if (!target) + return NULL; + + INIT_LLIST_HEAD(&target->entry); + memcpy(target->categories, default_categories, sizeof(default_categories)); + target->use_color = 1; + target->print_timestamp = 0; + target->loglevel = 0; + return target; +} + +struct debug_target *debug_target_create_stderr(void) +{ + struct debug_target *target; + + target = debug_target_create(); + if (!target) + return NULL; + + target->tgt_stdout.out = stderr; + target->output = _stderr_output; + return target; +} + +void debug_init(void) +{ + tall_dbg_ctx = talloc_named_const(NULL, 1, "debug"); +} diff --git a/src/host/libosmocom/src/msgb.c b/src/host/libosmocom/src/msgb.c new file mode 100644 index 00000000..2c794125 --- /dev/null +++ b/src/host/libosmocom/src/msgb.c @@ -0,0 +1,97 @@ +/* (C) 2008 by Harald Welte <laforge@gnumonks.org> + * 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 <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> + +#include <osmocom/msgb.h> +#include <osmocom/talloc.h> +#include <osmocom/debug.h> + +void *tall_msgb_ctx; + +struct msgb *msgb_alloc(u_int16_t size, const char *name) +{ + struct msgb *msg; + + msg = _talloc_zero(tall_msgb_ctx, sizeof(*msg) + size, name); + + if (!msg) { + LOGP(DRSL, LOGL_FATAL, "unable to allocate msgb\n"); + return NULL; + } + + msg->data_len = size; + msg->len = 0; + msg->data = msg->_data; + + msg->head = msg->data; + msg->data = msg->data; + /* reset tail pointer */ + msg->tail = msg->data; + //msg->end = msg->tail + size; + + return msg; +} + +void msgb_free(struct msgb *m) +{ + talloc_free(m); +} + +void msgb_enqueue(struct llist_head *queue, struct msgb *msg) +{ + llist_add_tail(&msg->list, queue); +} + +struct msgb *msgb_dequeue(struct llist_head *queue) +{ + struct llist_head *lh; + + if (llist_empty(queue)) + return NULL; + + lh = queue->next; + llist_del(lh); + + return llist_entry(lh, struct msgb, list); +} + +void msgb_reset(struct msgb *msg) +{ + msg->len = 0; + msg->len = 0; + msg->data = msg->_data; + + msg->head = msg->data; + msg->data = msg->data; + /* reset tail pointer */ + msg->tail = msg->data; + + /* reset pointers */ + msg->bts_link = NULL; + msg->trx = NULL; + msg->lchan = NULL; + msg->l2h = NULL; + msg->l3h = NULL; + msg->smsh = NULL; +} diff --git a/src/host/libosmocom/src/select.c b/src/host/libosmocom/src/select.c new file mode 100644 index 00000000..c212cc79 --- /dev/null +++ b/src/host/libosmocom/src/select.c @@ -0,0 +1,124 @@ +/* select filedescriptor handling, taken from: + * userspace logging daemon for the iptables ULOG target + * of the linux 2.4 netfilter subsystem. + * + * (C) 2000-2009 by Harald Welte <laforge@gnumonks.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <fcntl.h> +#include <osmocom/select.h> +#include <osmocom/linuxlist.h> +#include <osmocom/timer.h> + +static int maxfd = 0; +static LLIST_HEAD(bsc_fds); +static int unregistered_count; + +int bsc_register_fd(struct bsc_fd *fd) +{ + int flags; + + /* make FD nonblocking */ + flags = fcntl(fd->fd, F_GETFL); + if (flags < 0) + return flags; + flags |= O_NONBLOCK; + flags = fcntl(fd->fd, F_SETFL, flags); + if (flags < 0) + return flags; + + /* Register FD */ + if (fd->fd > maxfd) + maxfd = fd->fd; + + llist_add_tail(&fd->list, &bsc_fds); + + return 0; +} + +void bsc_unregister_fd(struct bsc_fd *fd) +{ + unregistered_count++; + llist_del(&fd->list); +} + +int bsc_select_main(int polling) +{ + struct bsc_fd *ufd, *tmp; + fd_set readset, writeset, exceptset; + int work = 0, rc; + struct timeval no_time = {0, 0}; + + FD_ZERO(&readset); + FD_ZERO(&writeset); + FD_ZERO(&exceptset); + + /* prepare read and write fdsets */ + llist_for_each_entry(ufd, &bsc_fds, list) { + if (ufd->when & BSC_FD_READ) + FD_SET(ufd->fd, &readset); + + if (ufd->when & BSC_FD_WRITE) + FD_SET(ufd->fd, &writeset); + + if (ufd->when & BSC_FD_EXCEPT) + FD_SET(ufd->fd, &exceptset); + } + + bsc_timer_check(); + + if (!polling) + bsc_prepare_timers(); + rc = select(maxfd+1, &readset, &writeset, &exceptset, polling ? &no_time : bsc_nearest_timer()); + if (rc < 0) + return 0; + + /* fire timers */ + bsc_update_timers(); + + /* call registered callback functions */ +restart: + unregistered_count = 0; + llist_for_each_entry_safe(ufd, tmp, &bsc_fds, list) { + int flags = 0; + + if (FD_ISSET(ufd->fd, &readset)) { + flags |= BSC_FD_READ; + FD_CLR(ufd->fd, &readset); + } + + if (FD_ISSET(ufd->fd, &writeset)) { + flags |= BSC_FD_WRITE; + FD_CLR(ufd->fd, &writeset); + } + + if (FD_ISSET(ufd->fd, &exceptset)) { + flags |= BSC_FD_EXCEPT; + FD_CLR(ufd->fd, &exceptset); + } + + if (flags) { + work = 1; + ufd->cb(ufd, flags); + } + /* ugly, ugly hack. If more than one filedescriptors were + * unregistered, they might have been consecutive and + * llist_for_each_entry_safe() is no longer safe */ + if (unregistered_count > 1) + goto restart; + } + return work; +} diff --git a/src/host/libosmocom/src/signal.c b/src/host/libosmocom/src/signal.c new file mode 100644 index 00000000..d45e94e6 --- /dev/null +++ b/src/host/libosmocom/src/signal.c @@ -0,0 +1,83 @@ +/* Generic signalling/notification infrastructure */ +/* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org> + * 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 <osmocom/signal.h> +#include <osmocom/talloc.h> +#include <stdlib.h> +#include <string.h> + + +void *tall_sigh_ctx; +static LLIST_HEAD(signal_handler_list); + +struct signal_handler { + struct llist_head entry; + unsigned int subsys; + signal_cbfn *cbfn; + void *data; +}; + + +int register_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data) +{ + struct signal_handler *sig_data; + + sig_data = talloc(tall_sigh_ctx, struct signal_handler); + if (!sig_data) + return -ENOMEM; + + memset(sig_data, 0, sizeof(*sig_data)); + + sig_data->subsys = subsys; + sig_data->data = data; + sig_data->cbfn = cbfn; + + /* FIXME: check if we already have a handler for this subsys/cbfn/data */ + + llist_add_tail(&sig_data->entry, &signal_handler_list); + + return 0; +} + +void unregister_signal_handler(unsigned int subsys, signal_cbfn *cbfn, void *data) +{ + struct signal_handler *handler; + + llist_for_each_entry(handler, &signal_handler_list, entry) { + if (handler->cbfn == cbfn && handler->data == data + && subsys == handler->subsys) { + llist_del(&handler->entry); + talloc_free(handler); + break; + } + } +} + + +void dispatch_signal(unsigned int subsys, unsigned int signal, void *signal_data) +{ + struct signal_handler *handler; + + llist_for_each_entry(handler, &signal_handler_list, entry) { + if (handler->subsys != subsys) + continue; + (*handler->cbfn)(subsys, signal, handler->data, signal_data); + } +} diff --git a/src/host/libosmocom/src/talloc.c b/src/host/libosmocom/src/talloc.c new file mode 100644 index 00000000..5b8bc274 --- /dev/null +++ b/src/host/libosmocom/src/talloc.c @@ -0,0 +1,1805 @@ +/* + Samba Unix SMB/CIFS implementation. + + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +/* + inspired by http://swapped.cc/halloc/ +*/ + +#ifdef _SAMBA_BUILD_ +#include "version.h" +#if (SAMBA_VERSION_MAJOR<4) +#include "includes.h" +/* This is to circumvent SAMBA3's paranoid malloc checker. Here in this file + * we trust ourselves... */ +#ifdef malloc +#undef malloc +#endif +#ifdef realloc +#undef realloc +#endif +#define _TALLOC_SAMBA3 +#endif /* (SAMBA_VERSION_MAJOR<4) */ +#endif /* _SAMBA_BUILD_ */ + +#ifndef _TALLOC_SAMBA3 +//#include "replace.h" +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> +#include <stdbool.h> +#define __USE_GNU +#include <string.h> +#undef __USE_GNU +#include <osmocom/talloc.h> +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif /* not _TALLOC_SAMBA3 */ + +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + +#define MAX_TALLOC_SIZE 0x10000000 +#define TALLOC_MAGIC 0xe814ec70 +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 +#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ +#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ +#define TALLOC_MAGIC_REFERENCE ((const char *)1) + +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) +#else +# define discard_const_p(type, ptr) ((type *)(ptr)) +#endif +#endif + +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + +#ifdef __APPLE__ +/* taken from http://insanecoding.blogspot.com/2007/03/methods-for-safe-string-handling.html */ +size_t strnlen(const char *s, size_t n) +{ + const char *p = (const char *)memchr(s, 0, n); + return(p ? p-s : n); +} +#endif + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ +static void *null_context; +static void *autofree_context; + +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; +}; + +typedef int (*talloc_destructor_t)(void *); + +struct talloc_chunk { + struct talloc_chunk *next, *prev; + struct talloc_chunk *parent, *child; + struct talloc_reference_handle *refs; + talloc_destructor_t destructor; + const char *name; + size_t size; + unsigned flags; + + /* + * "pool" has dual use: + * + * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool" + * marks the end of the currently allocated area. + * + * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool" + * is a pointer to the struct talloc_chunk of the pool that it was + * allocated from. This way children can quickly find the pool to chew + * from. + */ + void *pool; +}; + +/* 16 byte alignment seems to keep everyone happy */ +#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) + +static void (*talloc_abort_fn)(const char *reason); + +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) +{ + talloc_abort_fn = abort_fn; +} + +static void talloc_abort(const char *reason) +{ + if (!talloc_abort_fn) { + TALLOC_ABORT(reason); + } + + talloc_abort_fn(reason); +} + +static void talloc_abort_double_free(void) +{ + talloc_abort("Bad talloc magic value - double free"); +} + +static void talloc_abort_unknown_value(void) +{ + talloc_abort("Bad talloc magic value - unknown value"); +} + +/* panic if we get a bad magic value */ +static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +{ + const char *pp = (const char *)ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { + if (tc->flags & TALLOC_FLAG_FREE) { + talloc_abort_double_free(); + } else { + talloc_abort_unknown_value(); + } + } + return tc; +} + +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + + +/* + return the parent chunk of a pointer +*/ +static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + + return tc->parent; +} + +void *talloc_parent(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; +} + +/* + find parents name +*/ +const char *talloc_parent_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? tc->name : NULL; +} + +/* + A pool carries an in-pool object count count in the first 16 bytes. + bytes. This is done to support talloc_steal() to a parent outside of the + pool. The count includes the pool itself, so a talloc_free() on a pool will + only destroy the pool if the count has dropped to zero. A talloc_free() of a + pool member will reduce the count, and eventually also call free(3) on the + pool memory. + + The object count is not put into "struct talloc_chunk" because it is only + relevant for talloc pools and the alignment to 16 bytes would increase the + memory footprint of each talloc chunk by those 16 bytes. +*/ + +#define TALLOC_POOL_HDR_SIZE 16 + +static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) +{ + return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk)); +} + +/* + Allocate from a pool +*/ + +static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, + size_t size) +{ + struct talloc_chunk *pool_ctx = NULL; + size_t space_left; + struct talloc_chunk *result; + size_t chunk_size; + + if (parent == NULL) { + return NULL; + } + + if (parent->flags & TALLOC_FLAG_POOL) { + pool_ctx = parent; + } + else if (parent->flags & TALLOC_FLAG_POOLMEM) { + pool_ctx = (struct talloc_chunk *)parent->pool; + } + + if (pool_ctx == NULL) { + return NULL; + } + + space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size) + - ((char *)pool_ctx->pool); + + /* + * Align size to 16 bytes + */ + chunk_size = ((size + 15) & ~15); + + if (space_left < chunk_size) { + return NULL; + } + + result = (struct talloc_chunk *)pool_ctx->pool; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(result, size); +#endif + + pool_ctx->pool = (void *)((char *)result + chunk_size); + + result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM; + result->pool = pool_ctx; + + *talloc_pool_objectcount(pool_ctx) += 1; + + return result; +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +static inline void *__talloc(const void *context, size_t size) +{ + struct talloc_chunk *tc = NULL; + + if (unlikely(context == NULL)) { + context = null_context; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + if (context != NULL) { + tc = talloc_alloc_pool(talloc_chunk_from_ptr(context), + TC_HDR_SIZE+size); + } + + if (tc == NULL) { + tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); + if (unlikely(tc == NULL)) return NULL; + tc->flags = TALLOC_MAGIC; + tc->pool = NULL; + } + + tc->size = size; + tc->destructor = NULL; + tc->child = NULL; + tc->name = NULL; + tc->refs = NULL; + + if (likely(context)) { + struct talloc_chunk *parent = talloc_chunk_from_ptr(context); + + if (parent->child) { + parent->child->parent = NULL; + tc->next = parent->child; + tc->next->prev = tc; + } else { + tc->next = NULL; + } + tc->parent = parent; + tc->prev = NULL; + parent->child = tc; + } else { + tc->next = tc->prev = tc->parent = NULL; + } + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + * Create a talloc pool + */ + +void *talloc_pool(const void *context, size_t size) +{ + void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); + struct talloc_chunk *tc; + + if (unlikely(result == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(result); + + tc->flags |= TALLOC_FLAG_POOL; + tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE; + + *talloc_pool_objectcount(tc) = 1; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size); +#endif + + return result; +} + +/* + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used +*/ +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. +*/ +int talloc_increase_ref_count(const void *ptr) +{ + if (unlikely(!talloc_reference(null_context, ptr))) { + return -1; + } + return 0; +} + +/* + helper for talloc_reference() + + this is referenced by a function pointer and should not be inline +*/ +static int talloc_reference_destructor(struct talloc_reference_handle *handle) +{ + struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); + _TLIST_REMOVE(ptr_tc->refs, handle); + return 0; +} + +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +static inline void _talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + internal talloc_named_const() +*/ +static inline void *_talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) { + return NULL; + } + + _talloc_set_name_const(ptr, name); + + return ptr; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *_talloc_reference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *handle; + if (unlikely(ptr == NULL)) return NULL; + + tc = talloc_chunk_from_ptr(ptr); + handle = (struct talloc_reference_handle *)_talloc_named_const(context, + sizeof(struct talloc_reference_handle), + TALLOC_MAGIC_REFERENCE); + if (unlikely(handle == NULL)) return NULL; + + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + handle->ptr = discard_const_p(void, ptr); + _TLIST_ADD(tc->refs, handle); + return handle->ptr; +} + + +/* + internal talloc_free call +*/ +static inline int _talloc_free(void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs)) { + int is_child; + /* check this is a reference from a child or grantchild + * back to it's parent or grantparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + _talloc_free(tc->refs); + if (is_child) { + return _talloc_free(ptr); + } + return -1; + } + + if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { + /* we have a free loop - stop looping */ + return 0; + } + + if (unlikely(tc->destructor)) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_talloc_free(child) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + talloc_steal(new_parent, child); + } + } + + tc->flags |= TALLOC_FLAG_FREE; + + if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) { + struct talloc_chunk *pool; + unsigned int *pool_object_count; + + pool = (tc->flags & TALLOC_FLAG_POOL) + ? tc : (struct talloc_chunk *)tc->pool; + + pool_object_count = talloc_pool_objectcount(pool); + + if (*pool_object_count == 0) { + talloc_abort("Pool object count zero!"); + } + + *pool_object_count -= 1; + + if (*pool_object_count == 0) { + free(pool); + } + } + else { + free(tc); + } + return 0; +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +void *_talloc_steal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (unlikely(!ptr)) { + return NULL; + } + + if (unlikely(new_ctx == NULL)) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(new_ctx == NULL)) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (unlikely(tc == new_tc || tc->parent == new_tc)) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + + + +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +static inline int talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (unlikely(context == NULL)) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *p = talloc_parent_chunk(h); + if (p == NULL) { + if (context == NULL) break; + } else if (TC_PTR_FROM_CHUNK(p) == context) { + break; + } + } + if (h == NULL) { + return -1; + } + + return _talloc_free(h); +} + +/* + remove a specific parent context from a pointer. This is a more + controlled varient of talloc_free() +*/ +int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p; + void *new_parent; + + if (ptr == NULL) { + return -1; + } + + if (context == NULL) { + context = null_context; + } + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context == NULL) { + if (talloc_parent_chunk(ptr) != NULL) { + return -1; + } + } else { + if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { + return -1; + } + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return _talloc_free(ptr); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = TC_PTR_FROM_CHUNK(new_p); + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + talloc_steal(new_parent, ptr); + + return 0; +} + +/* + add a name to an existing pointer - va_list version +*/ +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = talloc_vasprintf(ptr, fmt, ap); + if (likely(tc->name)) { + _talloc_set_name_const(tc->name, ".name"); + } + return tc->name; +} + +/* + add a name to an existing pointer +*/ +const char *talloc_set_name(const void *ptr, const char *fmt, ...) +{ + const char *name; + va_list ap; + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + return name; +} + + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named(const void *context, size_t size, const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free(ptr); + return NULL; + } + + return ptr; +} + +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +const char *talloc_get_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { + return ".reference"; + } + if (likely(tc->name)) { + return tc->name; + } + return "UNNAMED"; +} + + +/* + check if a pointer has the given name. If it does, return the pointer, + otherwise return NULL +*/ +void *talloc_check_name(const void *ptr, const char *name) +{ + const char *pname; + if (unlikely(ptr == NULL)) return NULL; + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + return NULL; +} + +static void talloc_abort_type_missmatch(const char *location, + const char *name, + const char *expected) +{ + const char *reason; + + reason = talloc_asprintf(NULL, + "%s: Type mismatch: name[%s] expected[%s]", + location, + name?name:"NULL", + expected); + if (!reason) { + reason = "Type mismatch"; + } + + talloc_abort(reason); +} + +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) +{ + const char *pname; + + if (unlikely(ptr == NULL)) { + talloc_abort_type_missmatch(location, NULL, name); + return NULL; + } + + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + + talloc_abort_type_missmatch(location, pname, name); + return NULL; +} + +/* + this is for compatibility with older versions of talloc +*/ +void *talloc_init(const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + + /* + * samba3 expects talloc_report_depth_cb(NULL, ...) + * reports all talloc'ed memory, so we need to enable + * null_tracking + */ + talloc_enable_null_tracking(); + + ptr = __talloc(NULL, 0); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free(ptr); + return NULL; + } + + return ptr; +} + +/* + this is a replacement for the Samba3 talloc_destroy_pool functionality. It + should probably not be used in new code. It's in here to keep the talloc + code consistent across Samba 3 and 4. +*/ +void talloc_free_children(void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return; + } + + tc = talloc_chunk_from_ptr(ptr); + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_talloc_free(child) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + talloc_steal(new_parent, child); + } + } + + if ((tc->flags & TALLOC_FLAG_POOL) + && (*talloc_pool_objectcount(tc) == 1)) { + tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE); +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS( + tc->pool, tc->size - TALLOC_POOL_HDR_SIZE); +#endif + } +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +void *_talloc(const void *context, size_t size) +{ + return __talloc(context, size); +} + +/* + externally callable talloc_set_name_const() +*/ +void talloc_set_name_const(const void *ptr, const char *name) +{ + _talloc_set_name_const(ptr, name); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(const void *context, size_t size, const char *name) +{ + return _talloc_named_const(context, size, name); +} + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero +*/ +int talloc_free(void *ptr) +{ + return _talloc_free(ptr); +} + + + +/* + A talloc version of realloc. The context argument is only used if + ptr is NULL +*/ +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) +{ + struct talloc_chunk *tc; + void *new_ptr; + bool malloced = false; + + /* size zero is equivalent to free() */ + if (unlikely(size == 0)) { + _talloc_free(ptr); + return NULL; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + /* realloc(NULL) is equivalent to malloc() */ + if (ptr == NULL) { + return _talloc_named_const(context, size, name); + } + + tc = talloc_chunk_from_ptr(ptr); + + /* don't allow realloc on referenced pointers */ + if (unlikely(tc->refs)) { + return NULL; + } + + /* don't let anybody try to realloc a talloc_pool */ + if (unlikely(tc->flags & TALLOC_FLAG_POOL)) { + return NULL; + } + + /* don't shrink if we have less than 1k to gain */ + if ((size < tc->size) && ((tc->size - size) < 1024)) { + tc->size = size; + return ptr; + } + + /* by resetting magic we catch users of the old memory */ + tc->flags |= TALLOC_FLAG_FREE; + +#if ALWAYS_REALLOC + new_ptr = malloc(size + TC_HDR_SIZE); + if (new_ptr) { + memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE); + free(tc); + } +#else + if (tc->flags & TALLOC_FLAG_POOLMEM) { + + new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); + *talloc_pool_objectcount((struct talloc_chunk *) + (tc->pool)) -= 1; + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + } + } + else { + new_ptr = realloc(tc, size + TC_HDR_SIZE); + } +#endif + if (unlikely(!new_ptr)) { + tc->flags &= ~TALLOC_FLAG_FREE; + return NULL; + } + + tc = (struct talloc_chunk *)new_ptr; + tc->flags &= ~TALLOC_FLAG_FREE; + if (malloced) { + tc->flags &= ~TALLOC_FLAG_POOLMEM; + } + if (tc->parent) { + tc->parent->child = tc; + } + if (tc->child) { + tc->child->parent = tc; + } + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + tc->size = size; + _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + a wrapper around talloc_steal() for situations where you are moving a pointer + between two structures, and want the old pointer to be set to NULL +*/ +void *_talloc_move(const void *new_ctx, const void *_pptr) +{ + const void **pptr = discard_const_p(const void *,_pptr); + void *ret = _talloc_steal(new_ctx, *pptr); + (*pptr) = NULL; + return ret; +} + +/* + return the total size of a talloc pool (subtree) +*/ +size_t talloc_total_size(const void *ptr) +{ + size_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + total = tc->size; + for (c=tc->child;c;c=c->next) { + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the total number of blocks in a talloc pool (subtree) +*/ +size_t talloc_total_blocks(const void *ptr) +{ + size_t total = 0; + struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + total++; + for (c=tc->child;c;c=c->next) { + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the number of external references to a pointer +*/ +size_t talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + size_t ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data) +{ + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + callback(ptr, depth, max_depth, 0, private_data); + + if (max_depth >= 0 && depth >= max_depth) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); + callback(h->ptr, depth + 1, max_depth, 1, private_data); + } else { + talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) +{ + const char *name = talloc_get_name(ptr); + FILE *f = (FILE *)_f; + + if (is_ref) { + fprintf(f, "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + (int)talloc_reference_count(ptr), ptr); + +#if 0 + fprintf(f, "content: "); + if (talloc_total_size(ptr)) { + int tot = talloc_total_size(ptr); + int i; + + for (i = 0; i < tot; i++) { + if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { + fprintf(f, "%c", ((char *)ptr)[i]); + } else { + fprintf(f, "~%02x", ((char *)ptr)[i]); + } + } + } + fprintf(f, "\n"); +#endif +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) +{ + talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); + fflush(f); +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, -1, f); +} + +/* + report on memory usage by all children of a pointer +*/ +void talloc_report(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, 1, f); +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report(null_context, stderr); + } +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null_full(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report_full(null_context, stderr); + } +} + +/* + enable tracking of the NULL context +*/ +void talloc_enable_null_tracking(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + } +} + +/* + disable tracking of the NULL context +*/ +void talloc_disable_null_tracking(void) +{ + _talloc_free(null_context); + null_context = NULL; +} + +/* + enable leak reporting on exit +*/ +void talloc_enable_leak_report(void) +{ + talloc_enable_null_tracking(); + atexit(talloc_report_null); +} + +/* + enable full leak reporting on exit +*/ +void talloc_enable_leak_report_full(void) +{ + talloc_enable_null_tracking(); + atexit(talloc_report_null_full); +} + +/* + talloc and zero memory. +*/ +void *_talloc_zero(const void *ctx, size_t size, const char *name) +{ + void *p = _talloc_named_const(ctx, size, name); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + +/* + memdup with a talloc. +*/ +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) +{ + void *newp = _talloc_named_const(t, size, name); + + if (likely(newp)) { + memcpy(newp, p, size); + } + + return newp; +} + +static inline char *__talloc_strlendup(const void *t, const char *p, size_t len) +{ + char *ret; + + ret = (char *)__talloc(t, len + 1); + if (unlikely(!ret)) return NULL; + + memcpy(ret, p, len); + ret[len] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + strdup with a talloc +*/ +char *talloc_strdup(const void *t, const char *p) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strlen(p)); +} + +/* + strndup with a talloc +*/ +char *talloc_strndup(const void *t, const char *p, size_t n) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strnlen(p, n)); +} + +static inline char *__talloc_strlendup_append(char *s, size_t slen, + const char *a, size_t alen) +{ + char *ret; + + ret = talloc_realloc(NULL, s, char, slen + alen + 1); + if (unlikely(!ret)) return NULL; + + /* append the string and the trailing \0 */ + memcpy(&ret[slen], a, alen); + ret[slen+alen] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + * Appends at the end of the string. + */ +char *talloc_strdup_append(char *s, const char *a) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strlen(a)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +char *talloc_strdup_append_buffer(char *s, const char *a) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strlen(a)); +} + +/* + * Appends at the end of the string. + */ +char *talloc_strndup_append(char *s, const char *a, size_t n) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strnlen(a, n)); +} + +#ifndef HAVE_VA_COPY +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) +#else +#define va_copy(dest, src) (dest) = (src) +#endif +#endif + +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) +{ + int len; + char *ret; + va_list ap2; + char c; + + /* this call looks strange, but it makes it work on older solaris boxes */ + va_copy(ap2, ap); + len = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + if (unlikely(len < 0)) { + return NULL; + } + + ret = (char *)__talloc(t, len+1); + if (unlikely(!ret)) return NULL; + + va_copy(ap2, ap); + vsnprintf(ret, len+1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(ret, ret); + return ret; +} + + +/* + Perform string formatting, and return a pointer to newly allocated + memory holding the result, inside a memory pool. + */ +char *talloc_asprintf(const void *t, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = talloc_vasprintf(t, fmt, ap); + va_end(ap); + return ret; +} + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) + PRINTF_ATTRIBUTE(3,0); + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) +{ + ssize_t alen; + va_list ap2; + char c; + + va_copy(ap2, ap); + alen = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + + if (alen <= 0) { + /* Either the vsnprintf failed or the format resulted in + * no characters being formatted. In the former case, we + * ought to return NULL, in the latter we ought to return + * the original string. Most current callers of this + * function expect it to never return NULL. + */ + return s; + } + + s = talloc_realloc(NULL, s, char, slen + alen + 1); + if (!s) return NULL; + + va_copy(ap2, ap); + vsnprintf(s + slen, alen + 1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(s, s); + return s; +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Good for gradually + * accumulating output into a string buffer. Appends at the end + * of the string. + **/ +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +{ + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap); +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Always appends at the + * end of the talloc'ed buffer, not the end of the string. + **/ +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_vaslenprintf_append(s, slen, fmt, ap); +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a string buffer. + */ +char *talloc_asprintf_append(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append(s, fmt, ap); + va_end(ap); + return s; +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a buffer. + */ +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append_buffer(s, fmt, ap); + va_end(ap); + return s; +} + +/* + alloc an array, checking for integer overflow in the array size +*/ +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_named_const(ctx, el_size * count, name); +} + +/* + alloc an zero array, checking for integer overflow in the array size +*/ +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_realloc(ctx, ptr, el_size * count, name); +} + +/* + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) +*/ +void *talloc_realloc_fn(const void *context, void *ptr, size_t size) +{ + return _talloc_realloc(context, ptr, size, NULL); +} + + +static int talloc_autofree_destructor(void *ptr) +{ + autofree_context = NULL; + return 0; +} + +static void talloc_autofree(void) +{ + _talloc_free(autofree_context); +} + +/* + return a context which will be auto-freed on exit + this is useful for reducing the noise in leak reports +*/ +void *talloc_autofree_context(void) +{ + if (autofree_context == NULL) { + autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); + talloc_set_destructor(autofree_context, talloc_autofree_destructor); + atexit(talloc_autofree); + } + return autofree_context; +} + +size_t talloc_get_size(const void *context) +{ + struct talloc_chunk *tc; + + if (context == NULL) + return 0; + + tc = talloc_chunk_from_ptr(context); + + return tc->size; +} + +/* + find a parent of this context that has the given name, if any +*/ +void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + return NULL; +} + +/* + show the parentage of a context +*/ +void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + fflush(file); +} + +/* + return 1 if ptr is a parent of context +*/ +int talloc_is_parent(const void *context, const void *ptr) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + return 0; +} diff --git a/src/host/libosmocom/src/timer.c b/src/host/libosmocom/src/timer.c new file mode 100644 index 00000000..acb4d923 --- /dev/null +++ b/src/host/libosmocom/src/timer.c @@ -0,0 +1,185 @@ +/* + * (C) 2008,2009 by Holger Hans Peter Freyther <zecke@selfish.org> + * 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 <assert.h> +#include <string.h> +#include <osmocom/timer.h> + +static LLIST_HEAD(timer_list); +static struct timeval s_nearest_time; +static struct timeval s_select_time; + +#define MICRO_SECONDS 1000000LL + +#define TIME_SMALLER(left, right) \ + (left.tv_sec*MICRO_SECONDS+left.tv_usec) <= (right.tv_sec*MICRO_SECONDS+right.tv_usec) + +void bsc_add_timer(struct timer_list *timer) +{ + struct timer_list *list_timer; + + /* TODO: Optimize and remember the closest item... */ + timer->active = 1; + + /* this might be called from within update_timers */ + llist_for_each_entry(list_timer, &timer_list, entry) + if (timer == list_timer) + return; + + timer->in_list = 1; + llist_add(&timer->entry, &timer_list); +} + +void bsc_schedule_timer(struct timer_list *timer, int seconds, int microseconds) +{ + struct timeval current_time; + + gettimeofday(¤t_time, NULL); + unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec; + currentTime += seconds * MICRO_SECONDS + microseconds; + timer->timeout.tv_sec = currentTime / MICRO_SECONDS; + timer->timeout.tv_usec = currentTime % MICRO_SECONDS; + bsc_add_timer(timer); +} + +void bsc_del_timer(struct timer_list *timer) +{ + if (timer->in_list) { + timer->active = 0; + timer->in_list = 0; + llist_del(&timer->entry); + } +} + +int bsc_timer_pending(struct timer_list *timer) +{ + return timer->active; +} + +/* + * if we have a nearest time return the delta between the current + * time and the time of the nearest timer. + * If the nearest timer timed out return NULL and then we will + * dispatch everything after the select + */ +struct timeval *bsc_nearest_timer() +{ + struct timeval current_time; + + if (s_nearest_time.tv_sec == 0 && s_nearest_time.tv_usec == 0) + return NULL; + + if (gettimeofday(¤t_time, NULL) == -1) + return NULL; + + unsigned long long nearestTime = s_nearest_time.tv_sec * MICRO_SECONDS + s_nearest_time.tv_usec; + unsigned long long currentTime = current_time.tv_sec * MICRO_SECONDS + current_time.tv_usec; + + if (nearestTime < currentTime) { + s_select_time.tv_sec = 0; + s_select_time.tv_usec = 0; + } else { + s_select_time.tv_sec = (nearestTime - currentTime) / MICRO_SECONDS; + s_select_time.tv_usec = (nearestTime - currentTime) % MICRO_SECONDS; + } + + return &s_select_time; +} + +/* + * Find the nearest time and update s_nearest_time + */ +void bsc_prepare_timers() +{ + struct timer_list *timer, *nearest_timer = NULL; + llist_for_each_entry(timer, &timer_list, entry) { + if (!nearest_timer || TIME_SMALLER(timer->timeout, nearest_timer->timeout)) { + nearest_timer = timer; + } + } + + if (nearest_timer) { + s_nearest_time = nearest_timer->timeout; + } else { + memset(&s_nearest_time, 0, sizeof(struct timeval)); + } +} + +/* + * fire all timers... and remove them + */ +int bsc_update_timers() +{ + struct timeval current_time; + struct timer_list *timer, *tmp; + int work = 0; + + gettimeofday(¤t_time, NULL); + + /* + * The callbacks might mess with our list and in this case + * even llist_for_each_entry_safe is not safe to use. To allow + * del_timer, add_timer, schedule_timer to be called from within + * the callback we jump through some loops. + * + * First we set the handled flag of each active timer to zero, + * then we iterate over the list and execute the callbacks. As the + * list might have been changed (specially the next) from within + * the callback we have to start over again. Once every callback + * is dispatched we will remove the non-active from the list. + * + * TODO: If this is a performance issue we can poison a global + * variable in add_timer and del_timer and only then restart. + */ + llist_for_each_entry(timer, &timer_list, entry) { + timer->handled = 0; + } + +restart: + llist_for_each_entry(timer, &timer_list, entry) { + if (!timer->handled && TIME_SMALLER(timer->timeout, current_time)) { + timer->handled = 1; + timer->active = 0; + (*timer->cb)(timer->data); + work = 1; + goto restart; + } + } + + llist_for_each_entry_safe(timer, tmp, &timer_list, entry) { + timer->handled = 0; + if (!timer->active) { + bsc_del_timer(timer); + } + } + + return work; +} + +int bsc_timer_check(void) +{ + struct timer_list *timer; + int i = 0; + + llist_for_each_entry(timer, &timer_list, entry) { + i++; + } + return i; +} diff --git a/src/host/osmocon/.gitignore b/src/host/osmocon/.gitignore new file mode 100644 index 00000000..a9966b12 --- /dev/null +++ b/src/host/osmocon/.gitignore @@ -0,0 +1,9 @@ +*.o +osmocon +*.id* +*.nam +*.til +*.dump +*.bin +*.log +version.h diff --git a/src/host/osmocon/Makefile b/src/host/osmocon/Makefile new file mode 100644 index 00000000..9cb11d2d --- /dev/null +++ b/src/host/osmocon/Makefile @@ -0,0 +1,19 @@ +all: osmocon + +OSMOCOM_SRC=../libosmocom/src/select.c ../libosmocom/src/timer.c \ + ../libosmocom/src/msgb.c ../libosmocom/src/talloc.c \ + ../libosmocom/src/debug.c +SERCOMM_SRC=../../target/hello_world/comm/sercomm.c +INCLUDES=-I../libosmocom/include -I../../target/hello_world/include/comm + +.PHONY: version.h +version.h: + @echo -n \#define VERSION \"git- > version.h + @git log --oneline -n1 osmocon.c|cut -d ' ' -f 1 |tr -d '\n' >> version.h + @echo \" >> version.h + +osmocon: version.h $(OSMOCOM_SRC) $(SERCOMM_SRC) + $(CC) $(CFLAGS) -DHOST_BUILD $(INCLUDES) -o $@ $(OSMOCOM_SRC) $(SERCOMM_SRC) osmocon.c + +clean: + @rm -f osmocon version.h diff --git a/src/host/osmocon/memdump_convert.pl b/src/host/osmocon/memdump_convert.pl new file mode 100755 index 00000000..3d18a0b3 --- /dev/null +++ b/src/host/osmocon/memdump_convert.pl @@ -0,0 +1,29 @@ +#!/usr/bin/perl + +my $num_line = 0; +my $num_hex = 0; +my $oldaddr; + +while (my $line = <STDIN>) { + chomp($line); + $num_line++; + my (@hex) = $line =~ /(\w{8}): (\w{8}) (\w{8}) (\w{8}) (\w{8}) (\w{8}) (\w{8}) (\w{8}) (\w{8})/; + my $addr = hex(shift @hex); + if ($addr != 0 && $addr != $oldaddr + 0x20) { + printf(STDERR "gap of %u between 0x%08x and 0x%08x\n%s\n", + $addr - $oldaddr, $addr, $oldaddr, $line); + } + foreach my $h (@hex) { + $num_hex++; + # poor mans endian conversion + my ($a, $b, $c, $d) = $h =~/(\w\w)(\w\w)(\w\w)(\w\w)/; + my $h_reorder = $d . $c . $b . $a; + # convert into actual binary number + my $tmp = pack('H8', $h_reorder); + syswrite(STDOUT, $tmp, 4); + } + $oldaddr = $addr; +} + +printf(STDERR "num lines/num hex: %u/%u\n", $num_line, $num_hex); + diff --git a/src/host/osmocon/osmocon.c b/src/host/osmocon/osmocon.c new file mode 100644 index 00000000..094dbeb2 --- /dev/null +++ b/src/host/osmocon/osmocon.c @@ -0,0 +1,660 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> + +#include <sercomm.h> + +#include <osmocom/linuxlist.h> +#include <osmocom/select.h> +#include <osmocom/talloc.h> + +#include "version.h" + +#define MODEM_BAUDRATE B115200 +#define MAX_DNLOAD_SIZE 0xFFFF +#define MAX_HDR_SIZE 128 + +enum dnload_state { + WAITING_PROMPT1, + WAITING_PROMPT2, + DOWNLOADING, +}; + +enum dnload_mode { + MODE_C123, + MODE_C123xor, + MODE_C155, +}; + +struct dnload { + enum dnload_state state; + enum dnload_mode mode; + struct bsc_fd serial_fd; + char *filename; + + int print_hdlc; + + /* data to be downloaded */ + uint8_t *data; + int data_len; + + uint8_t *write_ptr; + + /* sockaddr in */ + struct bsc_fd socket; +}; + +/** + * a connection of the layer2 + */ +struct layer2_connection { + struct llist_head entry; + struct bsc_fd fd; +}; + +static LLIST_HEAD(connections); +static struct dnload dnload; + +static const uint8_t phone_prompt1[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x01, 0x40 }; +static const uint8_t dnload_cmd[] = { 0x1b, 0xf6, 0x02, 0x00, 0x52, 0x01, 0x53 }; +static const uint8_t phone_prompt2[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x02, 0x43 }; +static const uint8_t phone_ack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x42 }; +static const uint8_t phone_nack_magic[]= { 0x1b, 0xf6, 0x02, 0x00, 0x41, 0x03, 0x57 }; +static const uint8_t phone_nack[] = { 0x1b, 0xf6, 0x02, 0x00, 0x45, 0x53, 0x16 }; +static const uint8_t ftmtool[] = { "ftmtool" }; + +/* The C123 has a hard-coded check inside the ramloder that requires the following + * bytes to be always the first four bytes of the image */ +static const uint8_t data_hdr_c123[] = { 0xee, 0x4c, 0x9f, 0x63 }; + +/* The C155 doesn't have some strange restriction on what the first four bytes have + * to be, but it starts the ramloader in THUMB mode. We use the following four bytes + * to switch back to ARM mode: + 800100: 4778 bx pc + 800102: 46c0 nop ; (mov r8, r8) + */ +static const uint8_t data_hdr_c155[] = { 0x78, 0x47, 0xc0, 0x46 }; + +static const uint8_t dummy_data[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde }; + +static int serial_init(const char *serial_dev) +{ + struct termios options; + int fd, v24; + + fd = open(serial_dev, O_RDWR | O_NOCTTY | O_NDELAY); + if (fd < 0) + return fd; + + fcntl(fd, F_SETFL, 0); + + /* Configure serial interface */ + tcgetattr(fd, &options); + + cfsetispeed(&options, MODEM_BAUDRATE); + cfsetospeed(&options, MODEM_BAUDRATE); + + /* local read */ + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + + /* hardware flow control off */ + options.c_cflag &= ~CRTSCTS; + + /* software flow control off */ + options.c_iflag &= ~(IXON | IXOFF | IXANY); + + /* we want raw i/o */ + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_iflag &= ~(INLCR | ICRNL | IGNCR); + options.c_oflag &= ~(ONLCR); + + options.c_cc[VMIN] = 1; + options.c_cc[VTIME] = 0; + options.c_cc[VINTR] = 0; + options.c_cc[VQUIT] = 0; + options.c_cc[VSTART] = 0; + options.c_cc[VSTOP] = 0; + options.c_cc[VSUSP] = 0; + + tcsetattr(fd, TCSANOW, &options); + + /* set ready to read/write */ + v24 = TIOCM_DTR | TIOCM_RTS; + ioctl(fd, TIOCMBIS, &v24); + + return fd; +} + +/* Read the to-be-downloaded file, prepend header and length, append XOR sum */ +int read_file(const char *filename) +{ + int fd, rc, i; + struct stat st; + const uint8_t *hdr; + int hdr_len = 0; + uint8_t *file_data; + uint16_t tot_len; + uint8_t nibble; + uint8_t running_xor = 0x02; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror("opening file"); + exit(1); + } + + rc = fstat(fd, &st); + if (st.st_size > MAX_DNLOAD_SIZE) { + fprintf(stderr, "The maximum file size is 64kBytes (%u bytes)\n", + MAX_DNLOAD_SIZE); + return -EFBIG; + } + + if (dnload.data) { + free(dnload.data); + dnload.data = NULL; + } + + dnload.data = malloc(MAX_HDR_SIZE + st.st_size); + if (!dnload.data) { + close(fd); + fprintf(stderr, "No memory\n"); + return -ENOMEM; + } + + /* copy in the header, if any */ + switch (dnload.mode) { + case MODE_C155: + hdr = data_hdr_c155; + hdr_len = sizeof(data_hdr_c155); + break; + case MODE_C123: + case MODE_C123xor: + hdr = data_hdr_c123; + hdr_len = sizeof(data_hdr_c123); + break; + default: + break; + } + + if (hdr && hdr_len) + memcpy(dnload.data, hdr, hdr_len); + + /* 2 bytes for length + header */ + file_data = dnload.data + 2 + hdr_len; + + /* write the length, keep running XOR */ + tot_len = hdr_len + st.st_size; + nibble = tot_len >> 8; + dnload.data[0] = nibble; + running_xor ^= nibble; + nibble = tot_len & 0xff; + dnload.data[1] = nibble; + running_xor ^= nibble; + + if (hdr_len && hdr) { + memcpy(dnload.data+2, hdr, hdr_len); + + for (i = 0; i < hdr_len; i++) + running_xor ^= hdr[i]; + } + + rc = read(fd, file_data, st.st_size); + if (rc < 0) { + perror("error reading file\n"); + free(dnload.data); + dnload.data = NULL; + close(fd); + return -EIO; + } + if (rc < st.st_size) { + free(dnload.data); + dnload.data = NULL; + close(fd); + fprintf(stderr, "Short read of file (%d < %d)\n", + rc, (int)st.st_size); + return -EIO; + } + + close(fd); + + dnload.data_len = (file_data+st.st_size) - dnload.data; + + /* calculate XOR sum */ + for (i = 0; i < st.st_size; i++) + running_xor ^= file_data[i]; + + dnload.data[dnload.data_len++] = running_xor; + + /* initialize write pointer to start of data */ + dnload.write_ptr = dnload.data; + + printf("read_file(%s): file_size=%u, hdr_len=%u, dnload_len=%u\n", + filename, (int)st.st_size, hdr_len, dnload.data_len); + + return 0; +} + +static void hexdump(const uint8_t *data, unsigned int len) +{ + const uint8_t *bufptr = data; + int n; + + for (n=0; bufptr, n < len; n++, bufptr++) + printf("%02x ", *bufptr); + printf("\n"); +} + +#define WRITE_BLOCK 4096 + +static int handle_write(void) +{ + int bytes_left, write_len, rc; + + printf("handle_write(): "); + if (dnload.write_ptr == dnload.data) { + /* no bytes have been transferred yet */ + if (dnload.mode == MODE_C155 || + dnload.mode == MODE_C123xor) { + uint8_t xor_init = 0x02; + write(dnload.serial_fd.fd, &xor_init, 1); + } else + usleep(1); + } else if (dnload.write_ptr >= dnload.data + dnload.data_len) { + printf("finished\n"); + dnload.write_ptr = dnload.data; + return 1; + } + + /* try to write a maximum of WRITE_BLOCK bytes */ + bytes_left = (dnload.data + dnload.data_len) - dnload.write_ptr; + write_len = WRITE_BLOCK; + if (bytes_left < WRITE_BLOCK) + write_len = bytes_left; + + rc = write(dnload.serial_fd.fd, dnload.write_ptr, write_len); + if (rc < 0) { + perror("Error during write"); + return rc; + } + + dnload.write_ptr += rc; + + printf("%u bytes (%tu/%u)\n", rc, dnload.write_ptr - dnload.data, dnload.data_len); + + return 0; +} + +static uint8_t buffer[sizeof(phone_prompt1)]; +static uint8_t *bufptr = buffer; + +static void hdlc_send_to_phone(uint8_t dlci, uint8_t *data, int len) +{ + struct msgb *msg; + uint8_t c, *dest; + + if (len > 512) { + fprintf(stderr, "Too much data to send. %u\n", len); + return; + } + + /* push the message into the stack */ + msg = sercomm_alloc_msgb(512); + if (!msg) { + fprintf(stderr, "Failed to create data for the frame.\n"); + return; + } + + /* copy the data */ + dest = msgb_put(msg, len); + memcpy(dest, data, len); + + sercomm_sendmsg(dlci, msg); + + /* drain the queue: TODO: do this through the select */ + while (sercomm_drv_pull(&c) != 0) + if (write(dnload.serial_fd.fd, &c, 1) != 1) + perror("short write"); +} + +static void hdlc_console_cb(uint8_t dlci, struct msgb *msg) +{ + write(1, msg->data, msg->len); + msgb_free(msg); +} + +static void hdlc_l1a_cb(uint8_t dlci, struct msgb *msg) +{ + struct layer2_connection *con; + u_int16_t *len; + + len = (u_int16_t *) msgb_push(msg, 2); + *len = htons(msg->len - sizeof(*len)); + + llist_for_each_entry(con, &connections, entry) { + if (write(con->fd.fd, msg->data, msg->len) != msg->len) { + fprintf(stderr, "Failed to write msg to the socket..\n"); + continue; + } + } + + msgb_free(msg); +} + +static void print_hdlc(uint8_t *buffer, int length) +{ + int i; + + for (i = 0; i < length; ++i) + if (sercomm_drv_rx_char(buffer[i]) == 0) + printf("Dropping sample '%c'\n", buffer[i]); +} + +static int handle_read(void) +{ + int rc, nbytes, buf_left; + + buf_left = sizeof(buffer) - (bufptr - buffer); + if (buf_left <= 0) { + memmove(buffer, buffer+1, sizeof(buffer)-1); + bufptr -= 1; + buf_left = 1; + } + + nbytes = read(dnload.serial_fd.fd, bufptr, buf_left); + if (nbytes <= 0) + return nbytes; + + if (!dnload.print_hdlc) { + printf("got %i bytes from modem, ", nbytes); + printf("data looks like: "); + hexdump(bufptr, nbytes); + } else { + print_hdlc(bufptr, nbytes); + } + + if (!memcmp(buffer, phone_prompt1, sizeof(phone_prompt1))) { + printf("Received PROMPT1 from phone, responding with CMD\n"); + dnload.print_hdlc = 0; + dnload.state = WAITING_PROMPT2; + rc = write(dnload.serial_fd.fd, dnload_cmd, sizeof(dnload_cmd)); + + /* re-read file */ + rc = read_file(dnload.filename); + if (rc < 0) { + fprintf(stderr, "read_file(%s) failed with %d\n", dnload.filename, rc); + exit(1); + } + } else if (!memcmp(buffer, phone_prompt2, sizeof(phone_prompt2))) { + printf("Received PROMPT2 from phone, starting download\n"); + dnload.serial_fd.when = BSC_FD_READ | BSC_FD_WRITE; + dnload.state = DOWNLOADING; + } else if (!memcmp(buffer, phone_ack, sizeof(phone_ack))) { + printf("Received DOWNLOAD ACK from phone, your code is running now!\n"); + dnload.serial_fd.when = BSC_FD_READ; + dnload.state = WAITING_PROMPT1; + dnload.write_ptr = dnload.data; + dnload.print_hdlc = 1; + } else if (!memcmp(buffer, phone_nack, sizeof(phone_nack))) { + printf("Received DOWNLOAD NACK from phone, something went wrong :(\n"); + dnload.serial_fd.when = BSC_FD_READ; + dnload.state = WAITING_PROMPT1; + dnload.write_ptr = dnload.data; + } else if (!memcmp(buffer, phone_nack_magic, sizeof(phone_nack_magic))) { + printf("Received MAGIC NACK from phone, you need to have \"1003\" at 0x803ce0\n"); + dnload.serial_fd.when = BSC_FD_READ; + dnload.state = WAITING_PROMPT1; + dnload.write_ptr = dnload.data; + } else if (!memcmp(buffer, ftmtool, sizeof(ftmtool))) { + printf("Received FTMTOOL from phone, ramolader has aborted\n"); + dnload.serial_fd.when = BSC_FD_READ; + dnload.state = WAITING_PROMPT1; + dnload.write_ptr = dnload.data; + } + bufptr += nbytes; + + return nbytes; +} + +static int serial_read(struct bsc_fd *fd, unsigned int flags) +{ + int rc; + + if (flags & BSC_FD_READ) { + rc = handle_read(); + if (rc == 0) + exit(2); + } + + if (flags & BSC_FD_WRITE) { + rc = handle_write(); + if (rc == 1) + dnload.state = WAITING_PROMPT1; + } +} + +static int parse_mode(const char *arg) +{ + if (!strcasecmp(arg, "c123") || + !strcasecmp(arg, "c140")) + return MODE_C123; + else if (!strcasecmp(arg, "c123xor")) + return MODE_C123xor; + else if (!strcasecmp(arg, "c155")) + return MODE_C155; + + return -1; +} + + +static int usage(const char *name) +{ + printf("\nUsage: %s [ -v | -h ] [ -p /dev/ttyXXXX ] [ -s /tmp/osmocom_l2 ] ][ -m {c123,c123xor,c155} ] file.bin\n", name); + printf("\t* Open serial port /dev/ttyXXXX (connected to your phone)\n" + "\t* Perform handshaking with the ramloader in the phone\n" + "\t* Download file.bin to the attached phone (base address 0x00800100)\n"); + exit(2); +} + +static int version(const char *name) +{ + printf("\n%s version %s\n", name, VERSION); + exit(2); +} + +static int un_layer2_read(struct bsc_fd *fd, unsigned int flags) +{ + int rc; + u_int16_t length = 0xffff; + char buf[4096]; + struct layer2_connection *con; + + + rc = read(fd->fd, &length, sizeof(length)); + if (rc <= 0 || ntohs(length) > 512) { + fprintf(stderr, "Unexpected result from socket. rc: %d len: %d\n", + rc, ntohs(length)); + goto close; + } + + rc = read(fd->fd, buf, ntohs(length)); + if (rc != ntohs(length)) { + fprintf(stderr, "Could not read data.\n"); + goto close; + } + + hdlc_send_to_phone(SC_DLCI_L1A_L23, buf, ntohs(length)); + + return 0; +close: + con = (struct layer2_connection *) fd->data; + + close(fd->fd); + bsc_unregister_fd(fd); + llist_del(&con->entry); + talloc_free(con); + return -1; +} + +/* accept a new connection */ +static int un_layer2_accept(struct bsc_fd *fd, unsigned int flags) +{ + struct layer2_connection *con; + struct sockaddr_un un_addr; + socklen_t len; + int rc; + + len = sizeof(un_addr); + rc = accept(fd->fd, (struct sockaddr *) &un_addr, &len); + if (rc < 0) { + fprintf(stderr, "Failed to accept a new connection.\n"); + return -1; + } + + con = talloc_zero(NULL, struct layer2_connection); + if (!con) { + fprintf(stderr, "Failed to create layer2 connection.\n"); + return -1; + } + + con->fd.fd = rc; + con->fd.when = BSC_FD_READ; + con->fd.cb = un_layer2_read; + con->fd.data = con; + if (bsc_register_fd(&con->fd) != 0) { + fprintf(stderr, "Failed to register the fd.\n"); + return -1; + } + + llist_add(&con->entry, &connections); +} + +/* + * Create a server socket for the layer2 stack + */ +static int register_af_unix(const char *un_path) +{ + struct sockaddr_un local; + int rc; + + dnload.socket.fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if (dnload.socket.fd < 0) { + fprintf(stderr, "Failed to create Unix Domain Socket.\n"); + return -1; + } + + local.sun_family = AF_UNIX; + strncpy(local.sun_path, un_path, sizeof(local.sun_path)); + local.sun_path[sizeof(local.sun_path) - 1] = '\0'; + unlink(local.sun_path); + rc = bind(dnload.socket.fd, (struct sockaddr *) &local, + sizeof(local.sun_family) + strlen(local.sun_path)); + if (rc != 0) { + fprintf(stderr, "Failed to bind the unix domain socket. '%s'\n", + local.sun_path); + return -1; + } + + if (listen(dnload.socket.fd, 0) != 0) { + fprintf(stderr, "Failed to listen.\n"); + return -1; + } + + dnload.socket.when = BSC_FD_READ; + dnload.socket.cb = un_layer2_accept; + + if (bsc_register_fd(&dnload.socket) != 0) { + fprintf(stderr, "Failed to register the bfd.\n"); + return -1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + int opt, flags; + char *serial_dev = "/dev/ttyUSB1"; + char *un_path = "/tmp/osmocom_l2"; + + dnload.mode = MODE_C123; + + while ((opt = getopt(argc, argv, "hp:m:s:v")) != -1) { + switch (opt) { + case 'p': + serial_dev = optarg; + break; + case 'm': + dnload.mode = parse_mode(optarg); + if (dnload.mode < 0) + usage(argv[0]); + break; + case 's': + un_path = optarg; + break; + case 'v': + version(argv[0]); + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + if (argc <= optind) { + fprintf(stderr, "You have to specify the filename\n"); + usage(argv[0]); + } + + dnload.filename = argv[optind]; + + dnload.serial_fd.fd = serial_init(serial_dev); + if (dnload.serial_fd.fd < 0) { + fprintf(stderr, "Cannot open serial device %s\n", serial_dev); + exit(1); + } + + if (bsc_register_fd(&dnload.serial_fd) != 0) { + fprintf(stderr, "Failed to register the serial.\n"); + exit(1); + } + + /* Set serial socket to non-blocking mode of operation */ + flags = fcntl(dnload.serial_fd.fd, F_GETFL); + flags |= O_NONBLOCK; + fcntl(dnload.serial_fd.fd, F_SETFL, flags); + + dnload.serial_fd.when = BSC_FD_READ; + dnload.serial_fd.cb = serial_read; + + /* unix domain socket handling */ + if (register_af_unix(un_path) != 0) + exit(1); + + + /* initialize the HDLC layer */ + sercomm_init(); + sercomm_register_rx_cb(SC_DLCI_CONSOLE, hdlc_console_cb); + sercomm_register_rx_cb(SC_DLCI_L1A_L23, hdlc_l1a_cb); + while (1) + bsc_select_main(0); + + close(dnload.serial_fd.fd); + + exit(0); +} diff --git a/src/host/rita_pll/rita_pll.pl b/src/host/rita_pll/rita_pll.pl new file mode 100755 index 00000000..7de1aec4 --- /dev/null +++ b/src/host/rita_pll/rita_pll.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl + +sub pll_rx($$$$$) { + my ($a, $b, $p, $r, $l) = @_; + + return (($b*$p+$a)/($r*$l))*26; +} + +sub pll_rx_low_band($$) { + my ($a, $b) = @_; + my $p = 64; my $r = 65; my $l = 4; + return pll_rx($a, $b, $p, $r, $l); +} + +sub pll_rx_high_band($$) { + my ($a, $b) = @_; + my $p = 64; my $r = 65; my $l = 2; + return pll_rx($a, $b, $p, $r, $l); +} + +sub pll_tx_gsm850_1($$) { + my ($a, $b) = @_; + my $p = 64; my $r = 55; my $l = 4; my $m = 26; + + my $left = ((1/$l) - (1/$m)); + my $right = (($b*$p+$a)/$r); + + return $left * $right * 26; +} + +sub pll_tx_gsm850_2($$) { + my ($a, $b) = @_; + my $p = 64; my $r = 30; my $l = 4; my $m = 52; + + my $left = ((1/$l) - (1/$m)); + my $right = (($b*$p+$a)/$r); + + return $left * $right * 26; +} + +sub pll_tx_gsm900($$) { + my ($a, $b) = @_; + my $p = 64; my $r = 35; my $l = 4; my $m = 52; + + my $left = ((1/$l) + (1/$m)); + my $right = (($b*$p+$a)/$r); + + return $left * $right * 26; +} + +sub pll_tx_high($$) { + my ($a, $b) = @_; + my $p = 64; my $r = 70; my $l = 2; my $m = 26; + + my $left = ((1/$l) + (1/$m)); + my $right = (($b*$p+$a)/$r); + + return $left * $right * 26; +} + +sub hr() { + printf("======================================================================\n"); +} + +printf("PLL Rx Low Band:\n"); +for (my $b = 135; $b <= 150; $b++) { + for (my $a = 0; $a <= 62; $a++) { + printf("Fout=%4.2f (A=%03u, B=%03u)\n", pll_rx_low_band($a, $b), $a, $b); + } +} + +hr(); +printf("PLL Rx High Band:\n"); +for (my $b = 141; $b <= 155; $b++) { + for (my $a = 0; $a <= 62; $a++) { + printf("Fout=%4.2f (A=%03u, B=%03u)\n", pll_rx_high_band($a, $b), $a, $b); + } +} + +hr(); +printf("PLL Tx GSM850_1\n"); +for (my $b = 128; $b <= 130; $b++) { + for (my $a = 0; $a <= 62; $a++) { + printf("Fout=%4.2f (A=%03u, B=%03u)\n", pll_tx_gsm850_1($a, $b), $a, $b); + } +} + +hr(); +printf("PLL Tx GSM850_2\n"); +for (my $b = 65; $b <= 66; $b++) { + for (my $a = 0; $a <= 63; $a++) { + printf("Fout=%4.2f (A=%03u, B=%03u)\n", pll_tx_gsm850_2($a, $b), $a, $b); + } +} + +hr(); +printf("PLL Tx GSM900\n"); +for (my $b = 68; $b <= 71; $b++) { + for (my $a = 0; $a <= 63; $a++) { + printf("Fout=%4.2f (A=%03u, B=%03u)\n", pll_tx_gsm900($a, $b), $a, $b); + } +} + +hr(); +printf("PLL Tx GSM1800/1900\n"); +for (my $b = 133; $b <= 149; $b++) { + for (my $a = 0; $a <= 63; $a++) { + printf("Fout=%4.2f (A=%03u, B=%03u)\n", pll_tx_high($a, $b), $a, $b); + } +} + diff --git a/src/host/rita_pll/rita_pll.txt b/src/host/rita_pll/rita_pll.txt new file mode 100644 index 00000000..cac2cac2 --- /dev/null +++ b/src/host/rita_pll/rita_pll.txt @@ -0,0 +1,3625 @@ +PLL Rx Low Band: +Fout=864.00 (A=000, B=135) +Fout=864.10 (A=001, B=135) +Fout=864.20 (A=002, B=135) +Fout=864.30 (A=003, B=135) +Fout=864.40 (A=004, B=135) +Fout=864.50 (A=005, B=135) +Fout=864.60 (A=006, B=135) +Fout=864.70 (A=007, B=135) +Fout=864.80 (A=008, B=135) +Fout=864.90 (A=009, B=135) +Fout=865.00 (A=010, B=135) +Fout=865.10 (A=011, B=135) +Fout=865.20 (A=012, B=135) +Fout=865.30 (A=013, B=135) +Fout=865.40 (A=014, B=135) +Fout=865.50 (A=015, B=135) +Fout=865.60 (A=016, B=135) +Fout=865.70 (A=017, B=135) +Fout=865.80 (A=018, B=135) +Fout=865.90 (A=019, B=135) +Fout=866.00 (A=020, B=135) +Fout=866.10 (A=021, B=135) +Fout=866.20 (A=022, B=135) +Fout=866.30 (A=023, B=135) +Fout=866.40 (A=024, B=135) +Fout=866.50 (A=025, B=135) +Fout=866.60 (A=026, B=135) +Fout=866.70 (A=027, B=135) +Fout=866.80 (A=028, B=135) +Fout=866.90 (A=029, B=135) +Fout=867.00 (A=030, B=135) +Fout=867.10 (A=031, B=135) +Fout=867.20 (A=032, B=135) +Fout=867.30 (A=033, B=135) +Fout=867.40 (A=034, B=135) +Fout=867.50 (A=035, B=135) +Fout=867.60 (A=036, B=135) +Fout=867.70 (A=037, B=135) +Fout=867.80 (A=038, B=135) +Fout=867.90 (A=039, B=135) +Fout=868.00 (A=040, B=135) +Fout=868.10 (A=041, B=135) +Fout=868.20 (A=042, B=135) +Fout=868.30 (A=043, B=135) +Fout=868.40 (A=044, B=135) +Fout=868.50 (A=045, B=135) +Fout=868.60 (A=046, B=135) +Fout=868.70 (A=047, B=135) +Fout=868.80 (A=048, B=135) +Fout=868.90 (A=049, B=135) +Fout=869.00 (A=050, B=135) +Fout=869.10 (A=051, B=135) +Fout=869.20 (A=052, B=135) +Fout=869.30 (A=053, B=135) +Fout=869.40 (A=054, B=135) +Fout=869.50 (A=055, B=135) +Fout=869.60 (A=056, B=135) +Fout=869.70 (A=057, B=135) +Fout=869.80 (A=058, B=135) +Fout=869.90 (A=059, B=135) +Fout=870.00 (A=060, B=135) +Fout=870.10 (A=061, B=135) +Fout=870.20 (A=062, B=135) +Fout=870.40 (A=000, B=136) +Fout=870.50 (A=001, B=136) +Fout=870.60 (A=002, B=136) +Fout=870.70 (A=003, B=136) +Fout=870.80 (A=004, B=136) +Fout=870.90 (A=005, B=136) +Fout=871.00 (A=006, B=136) +Fout=871.10 (A=007, B=136) +Fout=871.20 (A=008, B=136) +Fout=871.30 (A=009, B=136) +Fout=871.40 (A=010, B=136) +Fout=871.50 (A=011, B=136) +Fout=871.60 (A=012, B=136) +Fout=871.70 (A=013, B=136) +Fout=871.80 (A=014, B=136) +Fout=871.90 (A=015, B=136) +Fout=872.00 (A=016, B=136) +Fout=872.10 (A=017, B=136) +Fout=872.20 (A=018, B=136) +Fout=872.30 (A=019, B=136) +Fout=872.40 (A=020, B=136) +Fout=872.50 (A=021, B=136) +Fout=872.60 (A=022, B=136) +Fout=872.70 (A=023, B=136) +Fout=872.80 (A=024, B=136) +Fout=872.90 (A=025, B=136) +Fout=873.00 (A=026, B=136) +Fout=873.10 (A=027, B=136) +Fout=873.20 (A=028, B=136) +Fout=873.30 (A=029, B=136) +Fout=873.40 (A=030, B=136) +Fout=873.50 (A=031, B=136) +Fout=873.60 (A=032, B=136) +Fout=873.70 (A=033, B=136) +Fout=873.80 (A=034, B=136) +Fout=873.90 (A=035, B=136) +Fout=874.00 (A=036, B=136) +Fout=874.10 (A=037, B=136) +Fout=874.20 (A=038, B=136) +Fout=874.30 (A=039, B=136) +Fout=874.40 (A=040, B=136) +Fout=874.50 (A=041, B=136) +Fout=874.60 (A=042, B=136) +Fout=874.70 (A=043, B=136) +Fout=874.80 (A=044, B=136) +Fout=874.90 (A=045, B=136) +Fout=875.00 (A=046, B=136) +Fout=875.10 (A=047, B=136) +Fout=875.20 (A=048, B=136) +Fout=875.30 (A=049, B=136) +Fout=875.40 (A=050, B=136) +Fout=875.50 (A=051, B=136) +Fout=875.60 (A=052, B=136) +Fout=875.70 (A=053, B=136) +Fout=875.80 (A=054, B=136) +Fout=875.90 (A=055, B=136) +Fout=876.00 (A=056, B=136) +Fout=876.10 (A=057, B=136) +Fout=876.20 (A=058, B=136) +Fout=876.30 (A=059, B=136) +Fout=876.40 (A=060, B=136) +Fout=876.50 (A=061, B=136) +Fout=876.60 (A=062, B=136) +Fout=876.80 (A=000, B=137) +Fout=876.90 (A=001, B=137) +Fout=877.00 (A=002, B=137) +Fout=877.10 (A=003, B=137) +Fout=877.20 (A=004, B=137) +Fout=877.30 (A=005, B=137) +Fout=877.40 (A=006, B=137) +Fout=877.50 (A=007, B=137) +Fout=877.60 (A=008, B=137) +Fout=877.70 (A=009, B=137) +Fout=877.80 (A=010, B=137) +Fout=877.90 (A=011, B=137) +Fout=878.00 (A=012, B=137) +Fout=878.10 (A=013, B=137) +Fout=878.20 (A=014, B=137) +Fout=878.30 (A=015, B=137) +Fout=878.40 (A=016, B=137) +Fout=878.50 (A=017, B=137) +Fout=878.60 (A=018, B=137) +Fout=878.70 (A=019, B=137) +Fout=878.80 (A=020, B=137) +Fout=878.90 (A=021, B=137) +Fout=879.00 (A=022, B=137) +Fout=879.10 (A=023, B=137) +Fout=879.20 (A=024, B=137) +Fout=879.30 (A=025, B=137) +Fout=879.40 (A=026, B=137) +Fout=879.50 (A=027, B=137) +Fout=879.60 (A=028, B=137) +Fout=879.70 (A=029, B=137) +Fout=879.80 (A=030, B=137) +Fout=879.90 (A=031, B=137) +Fout=880.00 (A=032, B=137) +Fout=880.10 (A=033, B=137) +Fout=880.20 (A=034, B=137) +Fout=880.30 (A=035, B=137) +Fout=880.40 (A=036, B=137) +Fout=880.50 (A=037, B=137) +Fout=880.60 (A=038, B=137) +Fout=880.70 (A=039, B=137) +Fout=880.80 (A=040, B=137) +Fout=880.90 (A=041, B=137) +Fout=881.00 (A=042, B=137) +Fout=881.10 (A=043, B=137) +Fout=881.20 (A=044, B=137) +Fout=881.30 (A=045, B=137) +Fout=881.40 (A=046, B=137) +Fout=881.50 (A=047, B=137) +Fout=881.60 (A=048, B=137) +Fout=881.70 (A=049, B=137) +Fout=881.80 (A=050, B=137) +Fout=881.90 (A=051, B=137) +Fout=882.00 (A=052, B=137) +Fout=882.10 (A=053, B=137) +Fout=882.20 (A=054, B=137) +Fout=882.30 (A=055, B=137) +Fout=882.40 (A=056, B=137) +Fout=882.50 (A=057, B=137) +Fout=882.60 (A=058, B=137) +Fout=882.70 (A=059, B=137) +Fout=882.80 (A=060, B=137) +Fout=882.90 (A=061, B=137) +Fout=883.00 (A=062, B=137) +Fout=883.20 (A=000, B=138) +Fout=883.30 (A=001, B=138) +Fout=883.40 (A=002, B=138) +Fout=883.50 (A=003, B=138) +Fout=883.60 (A=004, B=138) +Fout=883.70 (A=005, B=138) +Fout=883.80 (A=006, B=138) +Fout=883.90 (A=007, B=138) +Fout=884.00 (A=008, B=138) +Fout=884.10 (A=009, B=138) +Fout=884.20 (A=010, B=138) +Fout=884.30 (A=011, B=138) +Fout=884.40 (A=012, B=138) +Fout=884.50 (A=013, B=138) +Fout=884.60 (A=014, B=138) +Fout=884.70 (A=015, B=138) +Fout=884.80 (A=016, B=138) +Fout=884.90 (A=017, B=138) +Fout=885.00 (A=018, B=138) +Fout=885.10 (A=019, B=138) +Fout=885.20 (A=020, B=138) +Fout=885.30 (A=021, B=138) +Fout=885.40 (A=022, B=138) +Fout=885.50 (A=023, B=138) +Fout=885.60 (A=024, B=138) +Fout=885.70 (A=025, B=138) +Fout=885.80 (A=026, B=138) +Fout=885.90 (A=027, B=138) +Fout=886.00 (A=028, B=138) +Fout=886.10 (A=029, B=138) +Fout=886.20 (A=030, B=138) +Fout=886.30 (A=031, B=138) +Fout=886.40 (A=032, B=138) +Fout=886.50 (A=033, B=138) +Fout=886.60 (A=034, B=138) +Fout=886.70 (A=035, B=138) +Fout=886.80 (A=036, B=138) +Fout=886.90 (A=037, B=138) +Fout=887.00 (A=038, B=138) +Fout=887.10 (A=039, B=138) +Fout=887.20 (A=040, B=138) +Fout=887.30 (A=041, B=138) +Fout=887.40 (A=042, B=138) +Fout=887.50 (A=043, B=138) +Fout=887.60 (A=044, B=138) +Fout=887.70 (A=045, B=138) +Fout=887.80 (A=046, B=138) +Fout=887.90 (A=047, B=138) +Fout=888.00 (A=048, B=138) +Fout=888.10 (A=049, B=138) +Fout=888.20 (A=050, B=138) +Fout=888.30 (A=051, B=138) +Fout=888.40 (A=052, B=138) +Fout=888.50 (A=053, B=138) +Fout=888.60 (A=054, B=138) +Fout=888.70 (A=055, B=138) +Fout=888.80 (A=056, B=138) +Fout=888.90 (A=057, B=138) +Fout=889.00 (A=058, B=138) +Fout=889.10 (A=059, B=138) +Fout=889.20 (A=060, B=138) +Fout=889.30 (A=061, B=138) +Fout=889.40 (A=062, B=138) +Fout=889.60 (A=000, B=139) +Fout=889.70 (A=001, B=139) +Fout=889.80 (A=002, B=139) +Fout=889.90 (A=003, B=139) +Fout=890.00 (A=004, B=139) +Fout=890.10 (A=005, B=139) +Fout=890.20 (A=006, B=139) +Fout=890.30 (A=007, B=139) +Fout=890.40 (A=008, B=139) +Fout=890.50 (A=009, B=139) +Fout=890.60 (A=010, B=139) +Fout=890.70 (A=011, B=139) +Fout=890.80 (A=012, B=139) +Fout=890.90 (A=013, B=139) +Fout=891.00 (A=014, B=139) +Fout=891.10 (A=015, B=139) +Fout=891.20 (A=016, B=139) +Fout=891.30 (A=017, B=139) +Fout=891.40 (A=018, B=139) +Fout=891.50 (A=019, B=139) +Fout=891.60 (A=020, B=139) +Fout=891.70 (A=021, B=139) +Fout=891.80 (A=022, B=139) +Fout=891.90 (A=023, B=139) +Fout=892.00 (A=024, B=139) +Fout=892.10 (A=025, B=139) +Fout=892.20 (A=026, B=139) +Fout=892.30 (A=027, B=139) +Fout=892.40 (A=028, B=139) +Fout=892.50 (A=029, B=139) +Fout=892.60 (A=030, B=139) +Fout=892.70 (A=031, B=139) +Fout=892.80 (A=032, B=139) +Fout=892.90 (A=033, B=139) +Fout=893.00 (A=034, B=139) +Fout=893.10 (A=035, B=139) +Fout=893.20 (A=036, B=139) +Fout=893.30 (A=037, B=139) +Fout=893.40 (A=038, B=139) +Fout=893.50 (A=039, B=139) +Fout=893.60 (A=040, B=139) +Fout=893.70 (A=041, B=139) +Fout=893.80 (A=042, B=139) +Fout=893.90 (A=043, B=139) +Fout=894.00 (A=044, B=139) +Fout=894.10 (A=045, B=139) +Fout=894.20 (A=046, B=139) +Fout=894.30 (A=047, B=139) +Fout=894.40 (A=048, B=139) +Fout=894.50 (A=049, B=139) +Fout=894.60 (A=050, B=139) +Fout=894.70 (A=051, B=139) +Fout=894.80 (A=052, B=139) +Fout=894.90 (A=053, B=139) +Fout=895.00 (A=054, B=139) +Fout=895.10 (A=055, B=139) +Fout=895.20 (A=056, B=139) +Fout=895.30 (A=057, B=139) +Fout=895.40 (A=058, B=139) +Fout=895.50 (A=059, B=139) +Fout=895.60 (A=060, B=139) +Fout=895.70 (A=061, B=139) +Fout=895.80 (A=062, B=139) +Fout=896.00 (A=000, B=140) +Fout=896.10 (A=001, B=140) +Fout=896.20 (A=002, B=140) +Fout=896.30 (A=003, B=140) +Fout=896.40 (A=004, B=140) +Fout=896.50 (A=005, B=140) +Fout=896.60 (A=006, B=140) +Fout=896.70 (A=007, B=140) +Fout=896.80 (A=008, B=140) +Fout=896.90 (A=009, B=140) +Fout=897.00 (A=010, B=140) +Fout=897.10 (A=011, B=140) +Fout=897.20 (A=012, B=140) +Fout=897.30 (A=013, B=140) +Fout=897.40 (A=014, B=140) +Fout=897.50 (A=015, B=140) +Fout=897.60 (A=016, B=140) +Fout=897.70 (A=017, B=140) +Fout=897.80 (A=018, B=140) +Fout=897.90 (A=019, B=140) +Fout=898.00 (A=020, B=140) +Fout=898.10 (A=021, B=140) +Fout=898.20 (A=022, B=140) +Fout=898.30 (A=023, B=140) +Fout=898.40 (A=024, B=140) +Fout=898.50 (A=025, B=140) +Fout=898.60 (A=026, B=140) +Fout=898.70 (A=027, B=140) +Fout=898.80 (A=028, B=140) +Fout=898.90 (A=029, B=140) +Fout=899.00 (A=030, B=140) +Fout=899.10 (A=031, B=140) +Fout=899.20 (A=032, B=140) +Fout=899.30 (A=033, B=140) +Fout=899.40 (A=034, B=140) +Fout=899.50 (A=035, B=140) +Fout=899.60 (A=036, B=140) +Fout=899.70 (A=037, B=140) +Fout=899.80 (A=038, B=140) +Fout=899.90 (A=039, B=140) +Fout=900.00 (A=040, B=140) +Fout=900.10 (A=041, B=140) +Fout=900.20 (A=042, B=140) +Fout=900.30 (A=043, B=140) +Fout=900.40 (A=044, B=140) +Fout=900.50 (A=045, B=140) +Fout=900.60 (A=046, B=140) +Fout=900.70 (A=047, B=140) +Fout=900.80 (A=048, B=140) +Fout=900.90 (A=049, B=140) +Fout=901.00 (A=050, B=140) +Fout=901.10 (A=051, B=140) +Fout=901.20 (A=052, B=140) +Fout=901.30 (A=053, B=140) +Fout=901.40 (A=054, B=140) +Fout=901.50 (A=055, B=140) +Fout=901.60 (A=056, B=140) +Fout=901.70 (A=057, B=140) +Fout=901.80 (A=058, B=140) +Fout=901.90 (A=059, B=140) +Fout=902.00 (A=060, B=140) +Fout=902.10 (A=061, B=140) +Fout=902.20 (A=062, B=140) +Fout=902.40 (A=000, B=141) +Fout=902.50 (A=001, B=141) +Fout=902.60 (A=002, B=141) +Fout=902.70 (A=003, B=141) +Fout=902.80 (A=004, B=141) +Fout=902.90 (A=005, B=141) +Fout=903.00 (A=006, B=141) +Fout=903.10 (A=007, B=141) +Fout=903.20 (A=008, B=141) +Fout=903.30 (A=009, B=141) +Fout=903.40 (A=010, B=141) +Fout=903.50 (A=011, B=141) +Fout=903.60 (A=012, B=141) +Fout=903.70 (A=013, B=141) +Fout=903.80 (A=014, B=141) +Fout=903.90 (A=015, B=141) +Fout=904.00 (A=016, B=141) +Fout=904.10 (A=017, B=141) +Fout=904.20 (A=018, B=141) +Fout=904.30 (A=019, B=141) +Fout=904.40 (A=020, B=141) +Fout=904.50 (A=021, B=141) +Fout=904.60 (A=022, B=141) +Fout=904.70 (A=023, B=141) +Fout=904.80 (A=024, B=141) +Fout=904.90 (A=025, B=141) +Fout=905.00 (A=026, B=141) +Fout=905.10 (A=027, B=141) +Fout=905.20 (A=028, B=141) +Fout=905.30 (A=029, B=141) +Fout=905.40 (A=030, B=141) +Fout=905.50 (A=031, B=141) +Fout=905.60 (A=032, B=141) +Fout=905.70 (A=033, B=141) +Fout=905.80 (A=034, B=141) +Fout=905.90 (A=035, B=141) +Fout=906.00 (A=036, B=141) +Fout=906.10 (A=037, B=141) +Fout=906.20 (A=038, B=141) +Fout=906.30 (A=039, B=141) +Fout=906.40 (A=040, B=141) +Fout=906.50 (A=041, B=141) +Fout=906.60 (A=042, B=141) +Fout=906.70 (A=043, B=141) +Fout=906.80 (A=044, B=141) +Fout=906.90 (A=045, B=141) +Fout=907.00 (A=046, B=141) +Fout=907.10 (A=047, B=141) +Fout=907.20 (A=048, B=141) +Fout=907.30 (A=049, B=141) +Fout=907.40 (A=050, B=141) +Fout=907.50 (A=051, B=141) +Fout=907.60 (A=052, B=141) +Fout=907.70 (A=053, B=141) +Fout=907.80 (A=054, B=141) +Fout=907.90 (A=055, B=141) +Fout=908.00 (A=056, B=141) +Fout=908.10 (A=057, B=141) +Fout=908.20 (A=058, B=141) +Fout=908.30 (A=059, B=141) +Fout=908.40 (A=060, B=141) +Fout=908.50 (A=061, B=141) +Fout=908.60 (A=062, B=141) +Fout=908.80 (A=000, B=142) +Fout=908.90 (A=001, B=142) +Fout=909.00 (A=002, B=142) +Fout=909.10 (A=003, B=142) +Fout=909.20 (A=004, B=142) +Fout=909.30 (A=005, B=142) +Fout=909.40 (A=006, B=142) +Fout=909.50 (A=007, B=142) +Fout=909.60 (A=008, B=142) +Fout=909.70 (A=009, B=142) +Fout=909.80 (A=010, B=142) +Fout=909.90 (A=011, B=142) +Fout=910.00 (A=012, B=142) +Fout=910.10 (A=013, B=142) +Fout=910.20 (A=014, B=142) +Fout=910.30 (A=015, B=142) +Fout=910.40 (A=016, B=142) +Fout=910.50 (A=017, B=142) +Fout=910.60 (A=018, B=142) +Fout=910.70 (A=019, B=142) +Fout=910.80 (A=020, B=142) +Fout=910.90 (A=021, B=142) +Fout=911.00 (A=022, B=142) +Fout=911.10 (A=023, B=142) +Fout=911.20 (A=024, B=142) +Fout=911.30 (A=025, B=142) +Fout=911.40 (A=026, B=142) +Fout=911.50 (A=027, B=142) +Fout=911.60 (A=028, B=142) +Fout=911.70 (A=029, B=142) +Fout=911.80 (A=030, B=142) +Fout=911.90 (A=031, B=142) +Fout=912.00 (A=032, B=142) +Fout=912.10 (A=033, B=142) +Fout=912.20 (A=034, B=142) +Fout=912.30 (A=035, B=142) +Fout=912.40 (A=036, B=142) +Fout=912.50 (A=037, B=142) +Fout=912.60 (A=038, B=142) +Fout=912.70 (A=039, B=142) +Fout=912.80 (A=040, B=142) +Fout=912.90 (A=041, B=142) +Fout=913.00 (A=042, B=142) +Fout=913.10 (A=043, B=142) +Fout=913.20 (A=044, B=142) +Fout=913.30 (A=045, B=142) +Fout=913.40 (A=046, B=142) +Fout=913.50 (A=047, B=142) +Fout=913.60 (A=048, B=142) +Fout=913.70 (A=049, B=142) +Fout=913.80 (A=050, B=142) +Fout=913.90 (A=051, B=142) +Fout=914.00 (A=052, B=142) +Fout=914.10 (A=053, B=142) +Fout=914.20 (A=054, B=142) +Fout=914.30 (A=055, B=142) +Fout=914.40 (A=056, B=142) +Fout=914.50 (A=057, B=142) +Fout=914.60 (A=058, B=142) +Fout=914.70 (A=059, B=142) +Fout=914.80 (A=060, B=142) +Fout=914.90 (A=061, B=142) +Fout=915.00 (A=062, B=142) +Fout=915.20 (A=000, B=143) +Fout=915.30 (A=001, B=143) +Fout=915.40 (A=002, B=143) +Fout=915.50 (A=003, B=143) +Fout=915.60 (A=004, B=143) +Fout=915.70 (A=005, B=143) +Fout=915.80 (A=006, B=143) +Fout=915.90 (A=007, B=143) +Fout=916.00 (A=008, B=143) +Fout=916.10 (A=009, B=143) +Fout=916.20 (A=010, B=143) +Fout=916.30 (A=011, B=143) +Fout=916.40 (A=012, B=143) +Fout=916.50 (A=013, B=143) +Fout=916.60 (A=014, B=143) +Fout=916.70 (A=015, B=143) +Fout=916.80 (A=016, B=143) +Fout=916.90 (A=017, B=143) +Fout=917.00 (A=018, B=143) +Fout=917.10 (A=019, B=143) +Fout=917.20 (A=020, B=143) +Fout=917.30 (A=021, B=143) +Fout=917.40 (A=022, B=143) +Fout=917.50 (A=023, B=143) +Fout=917.60 (A=024, B=143) +Fout=917.70 (A=025, B=143) +Fout=917.80 (A=026, B=143) +Fout=917.90 (A=027, B=143) +Fout=918.00 (A=028, B=143) +Fout=918.10 (A=029, B=143) +Fout=918.20 (A=030, B=143) +Fout=918.30 (A=031, B=143) +Fout=918.40 (A=032, B=143) +Fout=918.50 (A=033, B=143) +Fout=918.60 (A=034, B=143) +Fout=918.70 (A=035, B=143) +Fout=918.80 (A=036, B=143) +Fout=918.90 (A=037, B=143) +Fout=919.00 (A=038, B=143) +Fout=919.10 (A=039, B=143) +Fout=919.20 (A=040, B=143) +Fout=919.30 (A=041, B=143) +Fout=919.40 (A=042, B=143) +Fout=919.50 (A=043, B=143) +Fout=919.60 (A=044, B=143) +Fout=919.70 (A=045, B=143) +Fout=919.80 (A=046, B=143) +Fout=919.90 (A=047, B=143) +Fout=920.00 (A=048, B=143) +Fout=920.10 (A=049, B=143) +Fout=920.20 (A=050, B=143) +Fout=920.30 (A=051, B=143) +Fout=920.40 (A=052, B=143) +Fout=920.50 (A=053, B=143) +Fout=920.60 (A=054, B=143) +Fout=920.70 (A=055, B=143) +Fout=920.80 (A=056, B=143) +Fout=920.90 (A=057, B=143) +Fout=921.00 (A=058, B=143) +Fout=921.10 (A=059, B=143) +Fout=921.20 (A=060, B=143) +Fout=921.30 (A=061, B=143) +Fout=921.40 (A=062, B=143) +Fout=921.60 (A=000, B=144) +Fout=921.70 (A=001, B=144) +Fout=921.80 (A=002, B=144) +Fout=921.90 (A=003, B=144) +Fout=922.00 (A=004, B=144) +Fout=922.10 (A=005, B=144) +Fout=922.20 (A=006, B=144) +Fout=922.30 (A=007, B=144) +Fout=922.40 (A=008, B=144) +Fout=922.50 (A=009, B=144) +Fout=922.60 (A=010, B=144) +Fout=922.70 (A=011, B=144) +Fout=922.80 (A=012, B=144) +Fout=922.90 (A=013, B=144) +Fout=923.00 (A=014, B=144) +Fout=923.10 (A=015, B=144) +Fout=923.20 (A=016, B=144) +Fout=923.30 (A=017, B=144) +Fout=923.40 (A=018, B=144) +Fout=923.50 (A=019, B=144) +Fout=923.60 (A=020, B=144) +Fout=923.70 (A=021, B=144) +Fout=923.80 (A=022, B=144) +Fout=923.90 (A=023, B=144) +Fout=924.00 (A=024, B=144) +Fout=924.10 (A=025, B=144) +Fout=924.20 (A=026, B=144) +Fout=924.30 (A=027, B=144) +Fout=924.40 (A=028, B=144) +Fout=924.50 (A=029, B=144) +Fout=924.60 (A=030, B=144) +Fout=924.70 (A=031, B=144) +Fout=924.80 (A=032, B=144) +Fout=924.90 (A=033, B=144) +Fout=925.00 (A=034, B=144) +Fout=925.10 (A=035, B=144) +Fout=925.20 (A=036, B=144) +Fout=925.30 (A=037, B=144) +Fout=925.40 (A=038, B=144) +Fout=925.50 (A=039, B=144) +Fout=925.60 (A=040, B=144) +Fout=925.70 (A=041, B=144) +Fout=925.80 (A=042, B=144) +Fout=925.90 (A=043, B=144) +Fout=926.00 (A=044, B=144) +Fout=926.10 (A=045, B=144) +Fout=926.20 (A=046, B=144) +Fout=926.30 (A=047, B=144) +Fout=926.40 (A=048, B=144) +Fout=926.50 (A=049, B=144) +Fout=926.60 (A=050, B=144) +Fout=926.70 (A=051, B=144) +Fout=926.80 (A=052, B=144) +Fout=926.90 (A=053, B=144) +Fout=927.00 (A=054, B=144) +Fout=927.10 (A=055, B=144) +Fout=927.20 (A=056, B=144) +Fout=927.30 (A=057, B=144) +Fout=927.40 (A=058, B=144) +Fout=927.50 (A=059, B=144) +Fout=927.60 (A=060, B=144) +Fout=927.70 (A=061, B=144) +Fout=927.80 (A=062, B=144) +Fout=928.00 (A=000, B=145) +Fout=928.10 (A=001, B=145) +Fout=928.20 (A=002, B=145) +Fout=928.30 (A=003, B=145) +Fout=928.40 (A=004, B=145) +Fout=928.50 (A=005, B=145) +Fout=928.60 (A=006, B=145) +Fout=928.70 (A=007, B=145) +Fout=928.80 (A=008, B=145) +Fout=928.90 (A=009, B=145) +Fout=929.00 (A=010, B=145) +Fout=929.10 (A=011, B=145) +Fout=929.20 (A=012, B=145) +Fout=929.30 (A=013, B=145) +Fout=929.40 (A=014, B=145) +Fout=929.50 (A=015, B=145) +Fout=929.60 (A=016, B=145) +Fout=929.70 (A=017, B=145) +Fout=929.80 (A=018, B=145) +Fout=929.90 (A=019, B=145) +Fout=930.00 (A=020, B=145) +Fout=930.10 (A=021, B=145) +Fout=930.20 (A=022, B=145) +Fout=930.30 (A=023, B=145) +Fout=930.40 (A=024, B=145) +Fout=930.50 (A=025, B=145) +Fout=930.60 (A=026, B=145) +Fout=930.70 (A=027, B=145) +Fout=930.80 (A=028, B=145) +Fout=930.90 (A=029, B=145) +Fout=931.00 (A=030, B=145) +Fout=931.10 (A=031, B=145) +Fout=931.20 (A=032, B=145) +Fout=931.30 (A=033, B=145) +Fout=931.40 (A=034, B=145) +Fout=931.50 (A=035, B=145) +Fout=931.60 (A=036, B=145) +Fout=931.70 (A=037, B=145) +Fout=931.80 (A=038, B=145) +Fout=931.90 (A=039, B=145) +Fout=932.00 (A=040, B=145) +Fout=932.10 (A=041, B=145) +Fout=932.20 (A=042, B=145) +Fout=932.30 (A=043, B=145) +Fout=932.40 (A=044, B=145) +Fout=932.50 (A=045, B=145) +Fout=932.60 (A=046, B=145) +Fout=932.70 (A=047, B=145) +Fout=932.80 (A=048, B=145) +Fout=932.90 (A=049, B=145) +Fout=933.00 (A=050, B=145) +Fout=933.10 (A=051, B=145) +Fout=933.20 (A=052, B=145) +Fout=933.30 (A=053, B=145) +Fout=933.40 (A=054, B=145) +Fout=933.50 (A=055, B=145) +Fout=933.60 (A=056, B=145) +Fout=933.70 (A=057, B=145) +Fout=933.80 (A=058, B=145) +Fout=933.90 (A=059, B=145) +Fout=934.00 (A=060, B=145) +Fout=934.10 (A=061, B=145) +Fout=934.20 (A=062, B=145) +Fout=934.40 (A=000, B=146) +Fout=934.50 (A=001, B=146) +Fout=934.60 (A=002, B=146) +Fout=934.70 (A=003, B=146) +Fout=934.80 (A=004, B=146) +Fout=934.90 (A=005, B=146) +Fout=935.00 (A=006, B=146) +Fout=935.10 (A=007, B=146) +Fout=935.20 (A=008, B=146) +Fout=935.30 (A=009, B=146) +Fout=935.40 (A=010, B=146) +Fout=935.50 (A=011, B=146) +Fout=935.60 (A=012, B=146) +Fout=935.70 (A=013, B=146) +Fout=935.80 (A=014, B=146) +Fout=935.90 (A=015, B=146) +Fout=936.00 (A=016, B=146) +Fout=936.10 (A=017, B=146) +Fout=936.20 (A=018, B=146) +Fout=936.30 (A=019, B=146) +Fout=936.40 (A=020, B=146) +Fout=936.50 (A=021, B=146) +Fout=936.60 (A=022, B=146) +Fout=936.70 (A=023, B=146) +Fout=936.80 (A=024, B=146) +Fout=936.90 (A=025, B=146) +Fout=937.00 (A=026, B=146) +Fout=937.10 (A=027, B=146) +Fout=937.20 (A=028, B=146) +Fout=937.30 (A=029, B=146) +Fout=937.40 (A=030, B=146) +Fout=937.50 (A=031, B=146) +Fout=937.60 (A=032, B=146) +Fout=937.70 (A=033, B=146) +Fout=937.80 (A=034, B=146) +Fout=937.90 (A=035, B=146) +Fout=938.00 (A=036, B=146) +Fout=938.10 (A=037, B=146) +Fout=938.20 (A=038, B=146) +Fout=938.30 (A=039, B=146) +Fout=938.40 (A=040, B=146) +Fout=938.50 (A=041, B=146) +Fout=938.60 (A=042, B=146) +Fout=938.70 (A=043, B=146) +Fout=938.80 (A=044, B=146) +Fout=938.90 (A=045, B=146) +Fout=939.00 (A=046, B=146) +Fout=939.10 (A=047, B=146) +Fout=939.20 (A=048, B=146) +Fout=939.30 (A=049, B=146) +Fout=939.40 (A=050, B=146) +Fout=939.50 (A=051, B=146) +Fout=939.60 (A=052, B=146) +Fout=939.70 (A=053, B=146) +Fout=939.80 (A=054, B=146) +Fout=939.90 (A=055, B=146) +Fout=940.00 (A=056, B=146) +Fout=940.10 (A=057, B=146) +Fout=940.20 (A=058, B=146) +Fout=940.30 (A=059, B=146) +Fout=940.40 (A=060, B=146) +Fout=940.50 (A=061, B=146) +Fout=940.60 (A=062, B=146) +Fout=940.80 (A=000, B=147) +Fout=940.90 (A=001, B=147) +Fout=941.00 (A=002, B=147) +Fout=941.10 (A=003, B=147) +Fout=941.20 (A=004, B=147) +Fout=941.30 (A=005, B=147) +Fout=941.40 (A=006, B=147) +Fout=941.50 (A=007, B=147) +Fout=941.60 (A=008, B=147) +Fout=941.70 (A=009, B=147) +Fout=941.80 (A=010, B=147) +Fout=941.90 (A=011, B=147) +Fout=942.00 (A=012, B=147) +Fout=942.10 (A=013, B=147) +Fout=942.20 (A=014, B=147) +Fout=942.30 (A=015, B=147) +Fout=942.40 (A=016, B=147) +Fout=942.50 (A=017, B=147) +Fout=942.60 (A=018, B=147) +Fout=942.70 (A=019, B=147) +Fout=942.80 (A=020, B=147) +Fout=942.90 (A=021, B=147) +Fout=943.00 (A=022, B=147) +Fout=943.10 (A=023, B=147) +Fout=943.20 (A=024, B=147) +Fout=943.30 (A=025, B=147) +Fout=943.40 (A=026, B=147) +Fout=943.50 (A=027, B=147) +Fout=943.60 (A=028, B=147) +Fout=943.70 (A=029, B=147) +Fout=943.80 (A=030, B=147) +Fout=943.90 (A=031, B=147) +Fout=944.00 (A=032, B=147) +Fout=944.10 (A=033, B=147) +Fout=944.20 (A=034, B=147) +Fout=944.30 (A=035, B=147) +Fout=944.40 (A=036, B=147) +Fout=944.50 (A=037, B=147) +Fout=944.60 (A=038, B=147) +Fout=944.70 (A=039, B=147) +Fout=944.80 (A=040, B=147) +Fout=944.90 (A=041, B=147) +Fout=945.00 (A=042, B=147) +Fout=945.10 (A=043, B=147) +Fout=945.20 (A=044, B=147) +Fout=945.30 (A=045, B=147) +Fout=945.40 (A=046, B=147) +Fout=945.50 (A=047, B=147) +Fout=945.60 (A=048, B=147) +Fout=945.70 (A=049, B=147) +Fout=945.80 (A=050, B=147) +Fout=945.90 (A=051, B=147) +Fout=946.00 (A=052, B=147) +Fout=946.10 (A=053, B=147) +Fout=946.20 (A=054, B=147) +Fout=946.30 (A=055, B=147) +Fout=946.40 (A=056, B=147) +Fout=946.50 (A=057, B=147) +Fout=946.60 (A=058, B=147) +Fout=946.70 (A=059, B=147) +Fout=946.80 (A=060, B=147) +Fout=946.90 (A=061, B=147) +Fout=947.00 (A=062, B=147) +Fout=947.20 (A=000, B=148) +Fout=947.30 (A=001, B=148) +Fout=947.40 (A=002, B=148) +Fout=947.50 (A=003, B=148) +Fout=947.60 (A=004, B=148) +Fout=947.70 (A=005, B=148) +Fout=947.80 (A=006, B=148) +Fout=947.90 (A=007, B=148) +Fout=948.00 (A=008, B=148) +Fout=948.10 (A=009, B=148) +Fout=948.20 (A=010, B=148) +Fout=948.30 (A=011, B=148) +Fout=948.40 (A=012, B=148) +Fout=948.50 (A=013, B=148) +Fout=948.60 (A=014, B=148) +Fout=948.70 (A=015, B=148) +Fout=948.80 (A=016, B=148) +Fout=948.90 (A=017, B=148) +Fout=949.00 (A=018, B=148) +Fout=949.10 (A=019, B=148) +Fout=949.20 (A=020, B=148) +Fout=949.30 (A=021, B=148) +Fout=949.40 (A=022, B=148) +Fout=949.50 (A=023, B=148) +Fout=949.60 (A=024, B=148) +Fout=949.70 (A=025, B=148) +Fout=949.80 (A=026, B=148) +Fout=949.90 (A=027, B=148) +Fout=950.00 (A=028, B=148) +Fout=950.10 (A=029, B=148) +Fout=950.20 (A=030, B=148) +Fout=950.30 (A=031, B=148) +Fout=950.40 (A=032, B=148) +Fout=950.50 (A=033, B=148) +Fout=950.60 (A=034, B=148) +Fout=950.70 (A=035, B=148) +Fout=950.80 (A=036, B=148) +Fout=950.90 (A=037, B=148) +Fout=951.00 (A=038, B=148) +Fout=951.10 (A=039, B=148) +Fout=951.20 (A=040, B=148) +Fout=951.30 (A=041, B=148) +Fout=951.40 (A=042, B=148) +Fout=951.50 (A=043, B=148) +Fout=951.60 (A=044, B=148) +Fout=951.70 (A=045, B=148) +Fout=951.80 (A=046, B=148) +Fout=951.90 (A=047, B=148) +Fout=952.00 (A=048, B=148) +Fout=952.10 (A=049, B=148) +Fout=952.20 (A=050, B=148) +Fout=952.30 (A=051, B=148) +Fout=952.40 (A=052, B=148) +Fout=952.50 (A=053, B=148) +Fout=952.60 (A=054, B=148) +Fout=952.70 (A=055, B=148) +Fout=952.80 (A=056, B=148) +Fout=952.90 (A=057, B=148) +Fout=953.00 (A=058, B=148) +Fout=953.10 (A=059, B=148) +Fout=953.20 (A=060, B=148) +Fout=953.30 (A=061, B=148) +Fout=953.40 (A=062, B=148) +Fout=953.60 (A=000, B=149) +Fout=953.70 (A=001, B=149) +Fout=953.80 (A=002, B=149) +Fout=953.90 (A=003, B=149) +Fout=954.00 (A=004, B=149) +Fout=954.10 (A=005, B=149) +Fout=954.20 (A=006, B=149) +Fout=954.30 (A=007, B=149) +Fout=954.40 (A=008, B=149) +Fout=954.50 (A=009, B=149) +Fout=954.60 (A=010, B=149) +Fout=954.70 (A=011, B=149) +Fout=954.80 (A=012, B=149) +Fout=954.90 (A=013, B=149) +Fout=955.00 (A=014, B=149) +Fout=955.10 (A=015, B=149) +Fout=955.20 (A=016, B=149) +Fout=955.30 (A=017, B=149) +Fout=955.40 (A=018, B=149) +Fout=955.50 (A=019, B=149) +Fout=955.60 (A=020, B=149) +Fout=955.70 (A=021, B=149) +Fout=955.80 (A=022, B=149) +Fout=955.90 (A=023, B=149) +Fout=956.00 (A=024, B=149) +Fout=956.10 (A=025, B=149) +Fout=956.20 (A=026, B=149) +Fout=956.30 (A=027, B=149) +Fout=956.40 (A=028, B=149) +Fout=956.50 (A=029, B=149) +Fout=956.60 (A=030, B=149) +Fout=956.70 (A=031, B=149) +Fout=956.80 (A=032, B=149) +Fout=956.90 (A=033, B=149) +Fout=957.00 (A=034, B=149) +Fout=957.10 (A=035, B=149) +Fout=957.20 (A=036, B=149) +Fout=957.30 (A=037, B=149) +Fout=957.40 (A=038, B=149) +Fout=957.50 (A=039, B=149) +Fout=957.60 (A=040, B=149) +Fout=957.70 (A=041, B=149) +Fout=957.80 (A=042, B=149) +Fout=957.90 (A=043, B=149) +Fout=958.00 (A=044, B=149) +Fout=958.10 (A=045, B=149) +Fout=958.20 (A=046, B=149) +Fout=958.30 (A=047, B=149) +Fout=958.40 (A=048, B=149) +Fout=958.50 (A=049, B=149) +Fout=958.60 (A=050, B=149) +Fout=958.70 (A=051, B=149) +Fout=958.80 (A=052, B=149) +Fout=958.90 (A=053, B=149) +Fout=959.00 (A=054, B=149) +Fout=959.10 (A=055, B=149) +Fout=959.20 (A=056, B=149) +Fout=959.30 (A=057, B=149) +Fout=959.40 (A=058, B=149) +Fout=959.50 (A=059, B=149) +Fout=959.60 (A=060, B=149) +Fout=959.70 (A=061, B=149) +Fout=959.80 (A=062, B=149) +Fout=960.00 (A=000, B=150) +Fout=960.10 (A=001, B=150) +Fout=960.20 (A=002, B=150) +Fout=960.30 (A=003, B=150) +Fout=960.40 (A=004, B=150) +Fout=960.50 (A=005, B=150) +Fout=960.60 (A=006, B=150) +Fout=960.70 (A=007, B=150) +Fout=960.80 (A=008, B=150) +Fout=960.90 (A=009, B=150) +Fout=961.00 (A=010, B=150) +Fout=961.10 (A=011, B=150) +Fout=961.20 (A=012, B=150) +Fout=961.30 (A=013, B=150) +Fout=961.40 (A=014, B=150) +Fout=961.50 (A=015, B=150) +Fout=961.60 (A=016, B=150) +Fout=961.70 (A=017, B=150) +Fout=961.80 (A=018, B=150) +Fout=961.90 (A=019, B=150) +Fout=962.00 (A=020, B=150) +Fout=962.10 (A=021, B=150) +Fout=962.20 (A=022, B=150) +Fout=962.30 (A=023, B=150) +Fout=962.40 (A=024, B=150) +Fout=962.50 (A=025, B=150) +Fout=962.60 (A=026, B=150) +Fout=962.70 (A=027, B=150) +Fout=962.80 (A=028, B=150) +Fout=962.90 (A=029, B=150) +Fout=963.00 (A=030, B=150) +Fout=963.10 (A=031, B=150) +Fout=963.20 (A=032, B=150) +Fout=963.30 (A=033, B=150) +Fout=963.40 (A=034, B=150) +Fout=963.50 (A=035, B=150) +Fout=963.60 (A=036, B=150) +Fout=963.70 (A=037, B=150) +Fout=963.80 (A=038, B=150) +Fout=963.90 (A=039, B=150) +Fout=964.00 (A=040, B=150) +Fout=964.10 (A=041, B=150) +Fout=964.20 (A=042, B=150) +Fout=964.30 (A=043, B=150) +Fout=964.40 (A=044, B=150) +Fout=964.50 (A=045, B=150) +Fout=964.60 (A=046, B=150) +Fout=964.70 (A=047, B=150) +Fout=964.80 (A=048, B=150) +Fout=964.90 (A=049, B=150) +Fout=965.00 (A=050, B=150) +Fout=965.10 (A=051, B=150) +Fout=965.20 (A=052, B=150) +Fout=965.30 (A=053, B=150) +Fout=965.40 (A=054, B=150) +Fout=965.50 (A=055, B=150) +Fout=965.60 (A=056, B=150) +Fout=965.70 (A=057, B=150) +Fout=965.80 (A=058, B=150) +Fout=965.90 (A=059, B=150) +Fout=966.00 (A=060, B=150) +Fout=966.10 (A=061, B=150) +Fout=966.20 (A=062, B=150) +====================================================================== +PLL Rx High Band: +Fout=1804.80 (A=000, B=141) +Fout=1805.00 (A=001, B=141) +Fout=1805.20 (A=002, B=141) +Fout=1805.40 (A=003, B=141) +Fout=1805.60 (A=004, B=141) +Fout=1805.80 (A=005, B=141) +Fout=1806.00 (A=006, B=141) +Fout=1806.20 (A=007, B=141) +Fout=1806.40 (A=008, B=141) +Fout=1806.60 (A=009, B=141) +Fout=1806.80 (A=010, B=141) +Fout=1807.00 (A=011, B=141) +Fout=1807.20 (A=012, B=141) +Fout=1807.40 (A=013, B=141) +Fout=1807.60 (A=014, B=141) +Fout=1807.80 (A=015, B=141) +Fout=1808.00 (A=016, B=141) +Fout=1808.20 (A=017, B=141) +Fout=1808.40 (A=018, B=141) +Fout=1808.60 (A=019, B=141) +Fout=1808.80 (A=020, B=141) +Fout=1809.00 (A=021, B=141) +Fout=1809.20 (A=022, B=141) +Fout=1809.40 (A=023, B=141) +Fout=1809.60 (A=024, B=141) +Fout=1809.80 (A=025, B=141) +Fout=1810.00 (A=026, B=141) +Fout=1810.20 (A=027, B=141) +Fout=1810.40 (A=028, B=141) +Fout=1810.60 (A=029, B=141) +Fout=1810.80 (A=030, B=141) +Fout=1811.00 (A=031, B=141) +Fout=1811.20 (A=032, B=141) +Fout=1811.40 (A=033, B=141) +Fout=1811.60 (A=034, B=141) +Fout=1811.80 (A=035, B=141) +Fout=1812.00 (A=036, B=141) +Fout=1812.20 (A=037, B=141) +Fout=1812.40 (A=038, B=141) +Fout=1812.60 (A=039, B=141) +Fout=1812.80 (A=040, B=141) +Fout=1813.00 (A=041, B=141) +Fout=1813.20 (A=042, B=141) +Fout=1813.40 (A=043, B=141) +Fout=1813.60 (A=044, B=141) +Fout=1813.80 (A=045, B=141) +Fout=1814.00 (A=046, B=141) +Fout=1814.20 (A=047, B=141) +Fout=1814.40 (A=048, B=141) +Fout=1814.60 (A=049, B=141) +Fout=1814.80 (A=050, B=141) +Fout=1815.00 (A=051, B=141) +Fout=1815.20 (A=052, B=141) +Fout=1815.40 (A=053, B=141) +Fout=1815.60 (A=054, B=141) +Fout=1815.80 (A=055, B=141) +Fout=1816.00 (A=056, B=141) +Fout=1816.20 (A=057, B=141) +Fout=1816.40 (A=058, B=141) +Fout=1816.60 (A=059, B=141) +Fout=1816.80 (A=060, B=141) +Fout=1817.00 (A=061, B=141) +Fout=1817.20 (A=062, B=141) +Fout=1817.60 (A=000, B=142) +Fout=1817.80 (A=001, B=142) +Fout=1818.00 (A=002, B=142) +Fout=1818.20 (A=003, B=142) +Fout=1818.40 (A=004, B=142) +Fout=1818.60 (A=005, B=142) +Fout=1818.80 (A=006, B=142) +Fout=1819.00 (A=007, B=142) +Fout=1819.20 (A=008, B=142) +Fout=1819.40 (A=009, B=142) +Fout=1819.60 (A=010, B=142) +Fout=1819.80 (A=011, B=142) +Fout=1820.00 (A=012, B=142) +Fout=1820.20 (A=013, B=142) +Fout=1820.40 (A=014, B=142) +Fout=1820.60 (A=015, B=142) +Fout=1820.80 (A=016, B=142) +Fout=1821.00 (A=017, B=142) +Fout=1821.20 (A=018, B=142) +Fout=1821.40 (A=019, B=142) +Fout=1821.60 (A=020, B=142) +Fout=1821.80 (A=021, B=142) +Fout=1822.00 (A=022, B=142) +Fout=1822.20 (A=023, B=142) +Fout=1822.40 (A=024, B=142) +Fout=1822.60 (A=025, B=142) +Fout=1822.80 (A=026, B=142) +Fout=1823.00 (A=027, B=142) +Fout=1823.20 (A=028, B=142) +Fout=1823.40 (A=029, B=142) +Fout=1823.60 (A=030, B=142) +Fout=1823.80 (A=031, B=142) +Fout=1824.00 (A=032, B=142) +Fout=1824.20 (A=033, B=142) +Fout=1824.40 (A=034, B=142) +Fout=1824.60 (A=035, B=142) +Fout=1824.80 (A=036, B=142) +Fout=1825.00 (A=037, B=142) +Fout=1825.20 (A=038, B=142) +Fout=1825.40 (A=039, B=142) +Fout=1825.60 (A=040, B=142) +Fout=1825.80 (A=041, B=142) +Fout=1826.00 (A=042, B=142) +Fout=1826.20 (A=043, B=142) +Fout=1826.40 (A=044, B=142) +Fout=1826.60 (A=045, B=142) +Fout=1826.80 (A=046, B=142) +Fout=1827.00 (A=047, B=142) +Fout=1827.20 (A=048, B=142) +Fout=1827.40 (A=049, B=142) +Fout=1827.60 (A=050, B=142) +Fout=1827.80 (A=051, B=142) +Fout=1828.00 (A=052, B=142) +Fout=1828.20 (A=053, B=142) +Fout=1828.40 (A=054, B=142) +Fout=1828.60 (A=055, B=142) +Fout=1828.80 (A=056, B=142) +Fout=1829.00 (A=057, B=142) +Fout=1829.20 (A=058, B=142) +Fout=1829.40 (A=059, B=142) +Fout=1829.60 (A=060, B=142) +Fout=1829.80 (A=061, B=142) +Fout=1830.00 (A=062, B=142) +Fout=1830.40 (A=000, B=143) +Fout=1830.60 (A=001, B=143) +Fout=1830.80 (A=002, B=143) +Fout=1831.00 (A=003, B=143) +Fout=1831.20 (A=004, B=143) +Fout=1831.40 (A=005, B=143) +Fout=1831.60 (A=006, B=143) +Fout=1831.80 (A=007, B=143) +Fout=1832.00 (A=008, B=143) +Fout=1832.20 (A=009, B=143) +Fout=1832.40 (A=010, B=143) +Fout=1832.60 (A=011, B=143) +Fout=1832.80 (A=012, B=143) +Fout=1833.00 (A=013, B=143) +Fout=1833.20 (A=014, B=143) +Fout=1833.40 (A=015, B=143) +Fout=1833.60 (A=016, B=143) +Fout=1833.80 (A=017, B=143) +Fout=1834.00 (A=018, B=143) +Fout=1834.20 (A=019, B=143) +Fout=1834.40 (A=020, B=143) +Fout=1834.60 (A=021, B=143) +Fout=1834.80 (A=022, B=143) +Fout=1835.00 (A=023, B=143) +Fout=1835.20 (A=024, B=143) +Fout=1835.40 (A=025, B=143) +Fout=1835.60 (A=026, B=143) +Fout=1835.80 (A=027, B=143) +Fout=1836.00 (A=028, B=143) +Fout=1836.20 (A=029, B=143) +Fout=1836.40 (A=030, B=143) +Fout=1836.60 (A=031, B=143) +Fout=1836.80 (A=032, B=143) +Fout=1837.00 (A=033, B=143) +Fout=1837.20 (A=034, B=143) +Fout=1837.40 (A=035, B=143) +Fout=1837.60 (A=036, B=143) +Fout=1837.80 (A=037, B=143) +Fout=1838.00 (A=038, B=143) +Fout=1838.20 (A=039, B=143) +Fout=1838.40 (A=040, B=143) +Fout=1838.60 (A=041, B=143) +Fout=1838.80 (A=042, B=143) +Fout=1839.00 (A=043, B=143) +Fout=1839.20 (A=044, B=143) +Fout=1839.40 (A=045, B=143) +Fout=1839.60 (A=046, B=143) +Fout=1839.80 (A=047, B=143) +Fout=1840.00 (A=048, B=143) +Fout=1840.20 (A=049, B=143) +Fout=1840.40 (A=050, B=143) +Fout=1840.60 (A=051, B=143) +Fout=1840.80 (A=052, B=143) +Fout=1841.00 (A=053, B=143) +Fout=1841.20 (A=054, B=143) +Fout=1841.40 (A=055, B=143) +Fout=1841.60 (A=056, B=143) +Fout=1841.80 (A=057, B=143) +Fout=1842.00 (A=058, B=143) +Fout=1842.20 (A=059, B=143) +Fout=1842.40 (A=060, B=143) +Fout=1842.60 (A=061, B=143) +Fout=1842.80 (A=062, B=143) +Fout=1843.20 (A=000, B=144) +Fout=1843.40 (A=001, B=144) +Fout=1843.60 (A=002, B=144) +Fout=1843.80 (A=003, B=144) +Fout=1844.00 (A=004, B=144) +Fout=1844.20 (A=005, B=144) +Fout=1844.40 (A=006, B=144) +Fout=1844.60 (A=007, B=144) +Fout=1844.80 (A=008, B=144) +Fout=1845.00 (A=009, B=144) +Fout=1845.20 (A=010, B=144) +Fout=1845.40 (A=011, B=144) +Fout=1845.60 (A=012, B=144) +Fout=1845.80 (A=013, B=144) +Fout=1846.00 (A=014, B=144) +Fout=1846.20 (A=015, B=144) +Fout=1846.40 (A=016, B=144) +Fout=1846.60 (A=017, B=144) +Fout=1846.80 (A=018, B=144) +Fout=1847.00 (A=019, B=144) +Fout=1847.20 (A=020, B=144) +Fout=1847.40 (A=021, B=144) +Fout=1847.60 (A=022, B=144) +Fout=1847.80 (A=023, B=144) +Fout=1848.00 (A=024, B=144) +Fout=1848.20 (A=025, B=144) +Fout=1848.40 (A=026, B=144) +Fout=1848.60 (A=027, B=144) +Fout=1848.80 (A=028, B=144) +Fout=1849.00 (A=029, B=144) +Fout=1849.20 (A=030, B=144) +Fout=1849.40 (A=031, B=144) +Fout=1849.60 (A=032, B=144) +Fout=1849.80 (A=033, B=144) +Fout=1850.00 (A=034, B=144) +Fout=1850.20 (A=035, B=144) +Fout=1850.40 (A=036, B=144) +Fout=1850.60 (A=037, B=144) +Fout=1850.80 (A=038, B=144) +Fout=1851.00 (A=039, B=144) +Fout=1851.20 (A=040, B=144) +Fout=1851.40 (A=041, B=144) +Fout=1851.60 (A=042, B=144) +Fout=1851.80 (A=043, B=144) +Fout=1852.00 (A=044, B=144) +Fout=1852.20 (A=045, B=144) +Fout=1852.40 (A=046, B=144) +Fout=1852.60 (A=047, B=144) +Fout=1852.80 (A=048, B=144) +Fout=1853.00 (A=049, B=144) +Fout=1853.20 (A=050, B=144) +Fout=1853.40 (A=051, B=144) +Fout=1853.60 (A=052, B=144) +Fout=1853.80 (A=053, B=144) +Fout=1854.00 (A=054, B=144) +Fout=1854.20 (A=055, B=144) +Fout=1854.40 (A=056, B=144) +Fout=1854.60 (A=057, B=144) +Fout=1854.80 (A=058, B=144) +Fout=1855.00 (A=059, B=144) +Fout=1855.20 (A=060, B=144) +Fout=1855.40 (A=061, B=144) +Fout=1855.60 (A=062, B=144) +Fout=1856.00 (A=000, B=145) +Fout=1856.20 (A=001, B=145) +Fout=1856.40 (A=002, B=145) +Fout=1856.60 (A=003, B=145) +Fout=1856.80 (A=004, B=145) +Fout=1857.00 (A=005, B=145) +Fout=1857.20 (A=006, B=145) +Fout=1857.40 (A=007, B=145) +Fout=1857.60 (A=008, B=145) +Fout=1857.80 (A=009, B=145) +Fout=1858.00 (A=010, B=145) +Fout=1858.20 (A=011, B=145) +Fout=1858.40 (A=012, B=145) +Fout=1858.60 (A=013, B=145) +Fout=1858.80 (A=014, B=145) +Fout=1859.00 (A=015, B=145) +Fout=1859.20 (A=016, B=145) +Fout=1859.40 (A=017, B=145) +Fout=1859.60 (A=018, B=145) +Fout=1859.80 (A=019, B=145) +Fout=1860.00 (A=020, B=145) +Fout=1860.20 (A=021, B=145) +Fout=1860.40 (A=022, B=145) +Fout=1860.60 (A=023, B=145) +Fout=1860.80 (A=024, B=145) +Fout=1861.00 (A=025, B=145) +Fout=1861.20 (A=026, B=145) +Fout=1861.40 (A=027, B=145) +Fout=1861.60 (A=028, B=145) +Fout=1861.80 (A=029, B=145) +Fout=1862.00 (A=030, B=145) +Fout=1862.20 (A=031, B=145) +Fout=1862.40 (A=032, B=145) +Fout=1862.60 (A=033, B=145) +Fout=1862.80 (A=034, B=145) +Fout=1863.00 (A=035, B=145) +Fout=1863.20 (A=036, B=145) +Fout=1863.40 (A=037, B=145) +Fout=1863.60 (A=038, B=145) +Fout=1863.80 (A=039, B=145) +Fout=1864.00 (A=040, B=145) +Fout=1864.20 (A=041, B=145) +Fout=1864.40 (A=042, B=145) +Fout=1864.60 (A=043, B=145) +Fout=1864.80 (A=044, B=145) +Fout=1865.00 (A=045, B=145) +Fout=1865.20 (A=046, B=145) +Fout=1865.40 (A=047, B=145) +Fout=1865.60 (A=048, B=145) +Fout=1865.80 (A=049, B=145) +Fout=1866.00 (A=050, B=145) +Fout=1866.20 (A=051, B=145) +Fout=1866.40 (A=052, B=145) +Fout=1866.60 (A=053, B=145) +Fout=1866.80 (A=054, B=145) +Fout=1867.00 (A=055, B=145) +Fout=1867.20 (A=056, B=145) +Fout=1867.40 (A=057, B=145) +Fout=1867.60 (A=058, B=145) +Fout=1867.80 (A=059, B=145) +Fout=1868.00 (A=060, B=145) +Fout=1868.20 (A=061, B=145) +Fout=1868.40 (A=062, B=145) +Fout=1868.80 (A=000, B=146) +Fout=1869.00 (A=001, B=146) +Fout=1869.20 (A=002, B=146) +Fout=1869.40 (A=003, B=146) +Fout=1869.60 (A=004, B=146) +Fout=1869.80 (A=005, B=146) +Fout=1870.00 (A=006, B=146) +Fout=1870.20 (A=007, B=146) +Fout=1870.40 (A=008, B=146) +Fout=1870.60 (A=009, B=146) +Fout=1870.80 (A=010, B=146) +Fout=1871.00 (A=011, B=146) +Fout=1871.20 (A=012, B=146) +Fout=1871.40 (A=013, B=146) +Fout=1871.60 (A=014, B=146) +Fout=1871.80 (A=015, B=146) +Fout=1872.00 (A=016, B=146) +Fout=1872.20 (A=017, B=146) +Fout=1872.40 (A=018, B=146) +Fout=1872.60 (A=019, B=146) +Fout=1872.80 (A=020, B=146) +Fout=1873.00 (A=021, B=146) +Fout=1873.20 (A=022, B=146) +Fout=1873.40 (A=023, B=146) +Fout=1873.60 (A=024, B=146) +Fout=1873.80 (A=025, B=146) +Fout=1874.00 (A=026, B=146) +Fout=1874.20 (A=027, B=146) +Fout=1874.40 (A=028, B=146) +Fout=1874.60 (A=029, B=146) +Fout=1874.80 (A=030, B=146) +Fout=1875.00 (A=031, B=146) +Fout=1875.20 (A=032, B=146) +Fout=1875.40 (A=033, B=146) +Fout=1875.60 (A=034, B=146) +Fout=1875.80 (A=035, B=146) +Fout=1876.00 (A=036, B=146) +Fout=1876.20 (A=037, B=146) +Fout=1876.40 (A=038, B=146) +Fout=1876.60 (A=039, B=146) +Fout=1876.80 (A=040, B=146) +Fout=1877.00 (A=041, B=146) +Fout=1877.20 (A=042, B=146) +Fout=1877.40 (A=043, B=146) +Fout=1877.60 (A=044, B=146) +Fout=1877.80 (A=045, B=146) +Fout=1878.00 (A=046, B=146) +Fout=1878.20 (A=047, B=146) +Fout=1878.40 (A=048, B=146) +Fout=1878.60 (A=049, B=146) +Fout=1878.80 (A=050, B=146) +Fout=1879.00 (A=051, B=146) +Fout=1879.20 (A=052, B=146) +Fout=1879.40 (A=053, B=146) +Fout=1879.60 (A=054, B=146) +Fout=1879.80 (A=055, B=146) +Fout=1880.00 (A=056, B=146) +Fout=1880.20 (A=057, B=146) +Fout=1880.40 (A=058, B=146) +Fout=1880.60 (A=059, B=146) +Fout=1880.80 (A=060, B=146) +Fout=1881.00 (A=061, B=146) +Fout=1881.20 (A=062, B=146) +Fout=1881.60 (A=000, B=147) +Fout=1881.80 (A=001, B=147) +Fout=1882.00 (A=002, B=147) +Fout=1882.20 (A=003, B=147) +Fout=1882.40 (A=004, B=147) +Fout=1882.60 (A=005, B=147) +Fout=1882.80 (A=006, B=147) +Fout=1883.00 (A=007, B=147) +Fout=1883.20 (A=008, B=147) +Fout=1883.40 (A=009, B=147) +Fout=1883.60 (A=010, B=147) +Fout=1883.80 (A=011, B=147) +Fout=1884.00 (A=012, B=147) +Fout=1884.20 (A=013, B=147) +Fout=1884.40 (A=014, B=147) +Fout=1884.60 (A=015, B=147) +Fout=1884.80 (A=016, B=147) +Fout=1885.00 (A=017, B=147) +Fout=1885.20 (A=018, B=147) +Fout=1885.40 (A=019, B=147) +Fout=1885.60 (A=020, B=147) +Fout=1885.80 (A=021, B=147) +Fout=1886.00 (A=022, B=147) +Fout=1886.20 (A=023, B=147) +Fout=1886.40 (A=024, B=147) +Fout=1886.60 (A=025, B=147) +Fout=1886.80 (A=026, B=147) +Fout=1887.00 (A=027, B=147) +Fout=1887.20 (A=028, B=147) +Fout=1887.40 (A=029, B=147) +Fout=1887.60 (A=030, B=147) +Fout=1887.80 (A=031, B=147) +Fout=1888.00 (A=032, B=147) +Fout=1888.20 (A=033, B=147) +Fout=1888.40 (A=034, B=147) +Fout=1888.60 (A=035, B=147) +Fout=1888.80 (A=036, B=147) +Fout=1889.00 (A=037, B=147) +Fout=1889.20 (A=038, B=147) +Fout=1889.40 (A=039, B=147) +Fout=1889.60 (A=040, B=147) +Fout=1889.80 (A=041, B=147) +Fout=1890.00 (A=042, B=147) +Fout=1890.20 (A=043, B=147) +Fout=1890.40 (A=044, B=147) +Fout=1890.60 (A=045, B=147) +Fout=1890.80 (A=046, B=147) +Fout=1891.00 (A=047, B=147) +Fout=1891.20 (A=048, B=147) +Fout=1891.40 (A=049, B=147) +Fout=1891.60 (A=050, B=147) +Fout=1891.80 (A=051, B=147) +Fout=1892.00 (A=052, B=147) +Fout=1892.20 (A=053, B=147) +Fout=1892.40 (A=054, B=147) +Fout=1892.60 (A=055, B=147) +Fout=1892.80 (A=056, B=147) +Fout=1893.00 (A=057, B=147) +Fout=1893.20 (A=058, B=147) +Fout=1893.40 (A=059, B=147) +Fout=1893.60 (A=060, B=147) +Fout=1893.80 (A=061, B=147) +Fout=1894.00 (A=062, B=147) +Fout=1894.40 (A=000, B=148) +Fout=1894.60 (A=001, B=148) +Fout=1894.80 (A=002, B=148) +Fout=1895.00 (A=003, B=148) +Fout=1895.20 (A=004, B=148) +Fout=1895.40 (A=005, B=148) +Fout=1895.60 (A=006, B=148) +Fout=1895.80 (A=007, B=148) +Fout=1896.00 (A=008, B=148) +Fout=1896.20 (A=009, B=148) +Fout=1896.40 (A=010, B=148) +Fout=1896.60 (A=011, B=148) +Fout=1896.80 (A=012, B=148) +Fout=1897.00 (A=013, B=148) +Fout=1897.20 (A=014, B=148) +Fout=1897.40 (A=015, B=148) +Fout=1897.60 (A=016, B=148) +Fout=1897.80 (A=017, B=148) +Fout=1898.00 (A=018, B=148) +Fout=1898.20 (A=019, B=148) +Fout=1898.40 (A=020, B=148) +Fout=1898.60 (A=021, B=148) +Fout=1898.80 (A=022, B=148) +Fout=1899.00 (A=023, B=148) +Fout=1899.20 (A=024, B=148) +Fout=1899.40 (A=025, B=148) +Fout=1899.60 (A=026, B=148) +Fout=1899.80 (A=027, B=148) +Fout=1900.00 (A=028, B=148) +Fout=1900.20 (A=029, B=148) +Fout=1900.40 (A=030, B=148) +Fout=1900.60 (A=031, B=148) +Fout=1900.80 (A=032, B=148) +Fout=1901.00 (A=033, B=148) +Fout=1901.20 (A=034, B=148) +Fout=1901.40 (A=035, B=148) +Fout=1901.60 (A=036, B=148) +Fout=1901.80 (A=037, B=148) +Fout=1902.00 (A=038, B=148) +Fout=1902.20 (A=039, B=148) +Fout=1902.40 (A=040, B=148) +Fout=1902.60 (A=041, B=148) +Fout=1902.80 (A=042, B=148) +Fout=1903.00 (A=043, B=148) +Fout=1903.20 (A=044, B=148) +Fout=1903.40 (A=045, B=148) +Fout=1903.60 (A=046, B=148) +Fout=1903.80 (A=047, B=148) +Fout=1904.00 (A=048, B=148) +Fout=1904.20 (A=049, B=148) +Fout=1904.40 (A=050, B=148) +Fout=1904.60 (A=051, B=148) +Fout=1904.80 (A=052, B=148) +Fout=1905.00 (A=053, B=148) +Fout=1905.20 (A=054, B=148) +Fout=1905.40 (A=055, B=148) +Fout=1905.60 (A=056, B=148) +Fout=1905.80 (A=057, B=148) +Fout=1906.00 (A=058, B=148) +Fout=1906.20 (A=059, B=148) +Fout=1906.40 (A=060, B=148) +Fout=1906.60 (A=061, B=148) +Fout=1906.80 (A=062, B=148) +Fout=1907.20 (A=000, B=149) +Fout=1907.40 (A=001, B=149) +Fout=1907.60 (A=002, B=149) +Fout=1907.80 (A=003, B=149) +Fout=1908.00 (A=004, B=149) +Fout=1908.20 (A=005, B=149) +Fout=1908.40 (A=006, B=149) +Fout=1908.60 (A=007, B=149) +Fout=1908.80 (A=008, B=149) +Fout=1909.00 (A=009, B=149) +Fout=1909.20 (A=010, B=149) +Fout=1909.40 (A=011, B=149) +Fout=1909.60 (A=012, B=149) +Fout=1909.80 (A=013, B=149) +Fout=1910.00 (A=014, B=149) +Fout=1910.20 (A=015, B=149) +Fout=1910.40 (A=016, B=149) +Fout=1910.60 (A=017, B=149) +Fout=1910.80 (A=018, B=149) +Fout=1911.00 (A=019, B=149) +Fout=1911.20 (A=020, B=149) +Fout=1911.40 (A=021, B=149) +Fout=1911.60 (A=022, B=149) +Fout=1911.80 (A=023, B=149) +Fout=1912.00 (A=024, B=149) +Fout=1912.20 (A=025, B=149) +Fout=1912.40 (A=026, B=149) +Fout=1912.60 (A=027, B=149) +Fout=1912.80 (A=028, B=149) +Fout=1913.00 (A=029, B=149) +Fout=1913.20 (A=030, B=149) +Fout=1913.40 (A=031, B=149) +Fout=1913.60 (A=032, B=149) +Fout=1913.80 (A=033, B=149) +Fout=1914.00 (A=034, B=149) +Fout=1914.20 (A=035, B=149) +Fout=1914.40 (A=036, B=149) +Fout=1914.60 (A=037, B=149) +Fout=1914.80 (A=038, B=149) +Fout=1915.00 (A=039, B=149) +Fout=1915.20 (A=040, B=149) +Fout=1915.40 (A=041, B=149) +Fout=1915.60 (A=042, B=149) +Fout=1915.80 (A=043, B=149) +Fout=1916.00 (A=044, B=149) +Fout=1916.20 (A=045, B=149) +Fout=1916.40 (A=046, B=149) +Fout=1916.60 (A=047, B=149) +Fout=1916.80 (A=048, B=149) +Fout=1917.00 (A=049, B=149) +Fout=1917.20 (A=050, B=149) +Fout=1917.40 (A=051, B=149) +Fout=1917.60 (A=052, B=149) +Fout=1917.80 (A=053, B=149) +Fout=1918.00 (A=054, B=149) +Fout=1918.20 (A=055, B=149) +Fout=1918.40 (A=056, B=149) +Fout=1918.60 (A=057, B=149) +Fout=1918.80 (A=058, B=149) +Fout=1919.00 (A=059, B=149) +Fout=1919.20 (A=060, B=149) +Fout=1919.40 (A=061, B=149) +Fout=1919.60 (A=062, B=149) +Fout=1920.00 (A=000, B=150) +Fout=1920.20 (A=001, B=150) +Fout=1920.40 (A=002, B=150) +Fout=1920.60 (A=003, B=150) +Fout=1920.80 (A=004, B=150) +Fout=1921.00 (A=005, B=150) +Fout=1921.20 (A=006, B=150) +Fout=1921.40 (A=007, B=150) +Fout=1921.60 (A=008, B=150) +Fout=1921.80 (A=009, B=150) +Fout=1922.00 (A=010, B=150) +Fout=1922.20 (A=011, B=150) +Fout=1922.40 (A=012, B=150) +Fout=1922.60 (A=013, B=150) +Fout=1922.80 (A=014, B=150) +Fout=1923.00 (A=015, B=150) +Fout=1923.20 (A=016, B=150) +Fout=1923.40 (A=017, B=150) +Fout=1923.60 (A=018, B=150) +Fout=1923.80 (A=019, B=150) +Fout=1924.00 (A=020, B=150) +Fout=1924.20 (A=021, B=150) +Fout=1924.40 (A=022, B=150) +Fout=1924.60 (A=023, B=150) +Fout=1924.80 (A=024, B=150) +Fout=1925.00 (A=025, B=150) +Fout=1925.20 (A=026, B=150) +Fout=1925.40 (A=027, B=150) +Fout=1925.60 (A=028, B=150) +Fout=1925.80 (A=029, B=150) +Fout=1926.00 (A=030, B=150) +Fout=1926.20 (A=031, B=150) +Fout=1926.40 (A=032, B=150) +Fout=1926.60 (A=033, B=150) +Fout=1926.80 (A=034, B=150) +Fout=1927.00 (A=035, B=150) +Fout=1927.20 (A=036, B=150) +Fout=1927.40 (A=037, B=150) +Fout=1927.60 (A=038, B=150) +Fout=1927.80 (A=039, B=150) +Fout=1928.00 (A=040, B=150) +Fout=1928.20 (A=041, B=150) +Fout=1928.40 (A=042, B=150) +Fout=1928.60 (A=043, B=150) +Fout=1928.80 (A=044, B=150) +Fout=1929.00 (A=045, B=150) +Fout=1929.20 (A=046, B=150) +Fout=1929.40 (A=047, B=150) +Fout=1929.60 (A=048, B=150) +Fout=1929.80 (A=049, B=150) +Fout=1930.00 (A=050, B=150) +Fout=1930.20 (A=051, B=150) +Fout=1930.40 (A=052, B=150) +Fout=1930.60 (A=053, B=150) +Fout=1930.80 (A=054, B=150) +Fout=1931.00 (A=055, B=150) +Fout=1931.20 (A=056, B=150) +Fout=1931.40 (A=057, B=150) +Fout=1931.60 (A=058, B=150) +Fout=1931.80 (A=059, B=150) +Fout=1932.00 (A=060, B=150) +Fout=1932.20 (A=061, B=150) +Fout=1932.40 (A=062, B=150) +Fout=1932.80 (A=000, B=151) +Fout=1933.00 (A=001, B=151) +Fout=1933.20 (A=002, B=151) +Fout=1933.40 (A=003, B=151) +Fout=1933.60 (A=004, B=151) +Fout=1933.80 (A=005, B=151) +Fout=1934.00 (A=006, B=151) +Fout=1934.20 (A=007, B=151) +Fout=1934.40 (A=008, B=151) +Fout=1934.60 (A=009, B=151) +Fout=1934.80 (A=010, B=151) +Fout=1935.00 (A=011, B=151) +Fout=1935.20 (A=012, B=151) +Fout=1935.40 (A=013, B=151) +Fout=1935.60 (A=014, B=151) +Fout=1935.80 (A=015, B=151) +Fout=1936.00 (A=016, B=151) +Fout=1936.20 (A=017, B=151) +Fout=1936.40 (A=018, B=151) +Fout=1936.60 (A=019, B=151) +Fout=1936.80 (A=020, B=151) +Fout=1937.00 (A=021, B=151) +Fout=1937.20 (A=022, B=151) +Fout=1937.40 (A=023, B=151) +Fout=1937.60 (A=024, B=151) +Fout=1937.80 (A=025, B=151) +Fout=1938.00 (A=026, B=151) +Fout=1938.20 (A=027, B=151) +Fout=1938.40 (A=028, B=151) +Fout=1938.60 (A=029, B=151) +Fout=1938.80 (A=030, B=151) +Fout=1939.00 (A=031, B=151) +Fout=1939.20 (A=032, B=151) +Fout=1939.40 (A=033, B=151) +Fout=1939.60 (A=034, B=151) +Fout=1939.80 (A=035, B=151) +Fout=1940.00 (A=036, B=151) +Fout=1940.20 (A=037, B=151) +Fout=1940.40 (A=038, B=151) +Fout=1940.60 (A=039, B=151) +Fout=1940.80 (A=040, B=151) +Fout=1941.00 (A=041, B=151) +Fout=1941.20 (A=042, B=151) +Fout=1941.40 (A=043, B=151) +Fout=1941.60 (A=044, B=151) +Fout=1941.80 (A=045, B=151) +Fout=1942.00 (A=046, B=151) +Fout=1942.20 (A=047, B=151) +Fout=1942.40 (A=048, B=151) +Fout=1942.60 (A=049, B=151) +Fout=1942.80 (A=050, B=151) +Fout=1943.00 (A=051, B=151) +Fout=1943.20 (A=052, B=151) +Fout=1943.40 (A=053, B=151) +Fout=1943.60 (A=054, B=151) +Fout=1943.80 (A=055, B=151) +Fout=1944.00 (A=056, B=151) +Fout=1944.20 (A=057, B=151) +Fout=1944.40 (A=058, B=151) +Fout=1944.60 (A=059, B=151) +Fout=1944.80 (A=060, B=151) +Fout=1945.00 (A=061, B=151) +Fout=1945.20 (A=062, B=151) +Fout=1945.60 (A=000, B=152) +Fout=1945.80 (A=001, B=152) +Fout=1946.00 (A=002, B=152) +Fout=1946.20 (A=003, B=152) +Fout=1946.40 (A=004, B=152) +Fout=1946.60 (A=005, B=152) +Fout=1946.80 (A=006, B=152) +Fout=1947.00 (A=007, B=152) +Fout=1947.20 (A=008, B=152) +Fout=1947.40 (A=009, B=152) +Fout=1947.60 (A=010, B=152) +Fout=1947.80 (A=011, B=152) +Fout=1948.00 (A=012, B=152) +Fout=1948.20 (A=013, B=152) +Fout=1948.40 (A=014, B=152) +Fout=1948.60 (A=015, B=152) +Fout=1948.80 (A=016, B=152) +Fout=1949.00 (A=017, B=152) +Fout=1949.20 (A=018, B=152) +Fout=1949.40 (A=019, B=152) +Fout=1949.60 (A=020, B=152) +Fout=1949.80 (A=021, B=152) +Fout=1950.00 (A=022, B=152) +Fout=1950.20 (A=023, B=152) +Fout=1950.40 (A=024, B=152) +Fout=1950.60 (A=025, B=152) +Fout=1950.80 (A=026, B=152) +Fout=1951.00 (A=027, B=152) +Fout=1951.20 (A=028, B=152) +Fout=1951.40 (A=029, B=152) +Fout=1951.60 (A=030, B=152) +Fout=1951.80 (A=031, B=152) +Fout=1952.00 (A=032, B=152) +Fout=1952.20 (A=033, B=152) +Fout=1952.40 (A=034, B=152) +Fout=1952.60 (A=035, B=152) +Fout=1952.80 (A=036, B=152) +Fout=1953.00 (A=037, B=152) +Fout=1953.20 (A=038, B=152) +Fout=1953.40 (A=039, B=152) +Fout=1953.60 (A=040, B=152) +Fout=1953.80 (A=041, B=152) +Fout=1954.00 (A=042, B=152) +Fout=1954.20 (A=043, B=152) +Fout=1954.40 (A=044, B=152) +Fout=1954.60 (A=045, B=152) +Fout=1954.80 (A=046, B=152) +Fout=1955.00 (A=047, B=152) +Fout=1955.20 (A=048, B=152) +Fout=1955.40 (A=049, B=152) +Fout=1955.60 (A=050, B=152) +Fout=1955.80 (A=051, B=152) +Fout=1956.00 (A=052, B=152) +Fout=1956.20 (A=053, B=152) +Fout=1956.40 (A=054, B=152) +Fout=1956.60 (A=055, B=152) +Fout=1956.80 (A=056, B=152) +Fout=1957.00 (A=057, B=152) +Fout=1957.20 (A=058, B=152) +Fout=1957.40 (A=059, B=152) +Fout=1957.60 (A=060, B=152) +Fout=1957.80 (A=061, B=152) +Fout=1958.00 (A=062, B=152) +Fout=1958.40 (A=000, B=153) +Fout=1958.60 (A=001, B=153) +Fout=1958.80 (A=002, B=153) +Fout=1959.00 (A=003, B=153) +Fout=1959.20 (A=004, B=153) +Fout=1959.40 (A=005, B=153) +Fout=1959.60 (A=006, B=153) +Fout=1959.80 (A=007, B=153) +Fout=1960.00 (A=008, B=153) +Fout=1960.20 (A=009, B=153) +Fout=1960.40 (A=010, B=153) +Fout=1960.60 (A=011, B=153) +Fout=1960.80 (A=012, B=153) +Fout=1961.00 (A=013, B=153) +Fout=1961.20 (A=014, B=153) +Fout=1961.40 (A=015, B=153) +Fout=1961.60 (A=016, B=153) +Fout=1961.80 (A=017, B=153) +Fout=1962.00 (A=018, B=153) +Fout=1962.20 (A=019, B=153) +Fout=1962.40 (A=020, B=153) +Fout=1962.60 (A=021, B=153) +Fout=1962.80 (A=022, B=153) +Fout=1963.00 (A=023, B=153) +Fout=1963.20 (A=024, B=153) +Fout=1963.40 (A=025, B=153) +Fout=1963.60 (A=026, B=153) +Fout=1963.80 (A=027, B=153) +Fout=1964.00 (A=028, B=153) +Fout=1964.20 (A=029, B=153) +Fout=1964.40 (A=030, B=153) +Fout=1964.60 (A=031, B=153) +Fout=1964.80 (A=032, B=153) +Fout=1965.00 (A=033, B=153) +Fout=1965.20 (A=034, B=153) +Fout=1965.40 (A=035, B=153) +Fout=1965.60 (A=036, B=153) +Fout=1965.80 (A=037, B=153) +Fout=1966.00 (A=038, B=153) +Fout=1966.20 (A=039, B=153) +Fout=1966.40 (A=040, B=153) +Fout=1966.60 (A=041, B=153) +Fout=1966.80 (A=042, B=153) +Fout=1967.00 (A=043, B=153) +Fout=1967.20 (A=044, B=153) +Fout=1967.40 (A=045, B=153) +Fout=1967.60 (A=046, B=153) +Fout=1967.80 (A=047, B=153) +Fout=1968.00 (A=048, B=153) +Fout=1968.20 (A=049, B=153) +Fout=1968.40 (A=050, B=153) +Fout=1968.60 (A=051, B=153) +Fout=1968.80 (A=052, B=153) +Fout=1969.00 (A=053, B=153) +Fout=1969.20 (A=054, B=153) +Fout=1969.40 (A=055, B=153) +Fout=1969.60 (A=056, B=153) +Fout=1969.80 (A=057, B=153) +Fout=1970.00 (A=058, B=153) +Fout=1970.20 (A=059, B=153) +Fout=1970.40 (A=060, B=153) +Fout=1970.60 (A=061, B=153) +Fout=1970.80 (A=062, B=153) +Fout=1971.20 (A=000, B=154) +Fout=1971.40 (A=001, B=154) +Fout=1971.60 (A=002, B=154) +Fout=1971.80 (A=003, B=154) +Fout=1972.00 (A=004, B=154) +Fout=1972.20 (A=005, B=154) +Fout=1972.40 (A=006, B=154) +Fout=1972.60 (A=007, B=154) +Fout=1972.80 (A=008, B=154) +Fout=1973.00 (A=009, B=154) +Fout=1973.20 (A=010, B=154) +Fout=1973.40 (A=011, B=154) +Fout=1973.60 (A=012, B=154) +Fout=1973.80 (A=013, B=154) +Fout=1974.00 (A=014, B=154) +Fout=1974.20 (A=015, B=154) +Fout=1974.40 (A=016, B=154) +Fout=1974.60 (A=017, B=154) +Fout=1974.80 (A=018, B=154) +Fout=1975.00 (A=019, B=154) +Fout=1975.20 (A=020, B=154) +Fout=1975.40 (A=021, B=154) +Fout=1975.60 (A=022, B=154) +Fout=1975.80 (A=023, B=154) +Fout=1976.00 (A=024, B=154) +Fout=1976.20 (A=025, B=154) +Fout=1976.40 (A=026, B=154) +Fout=1976.60 (A=027, B=154) +Fout=1976.80 (A=028, B=154) +Fout=1977.00 (A=029, B=154) +Fout=1977.20 (A=030, B=154) +Fout=1977.40 (A=031, B=154) +Fout=1977.60 (A=032, B=154) +Fout=1977.80 (A=033, B=154) +Fout=1978.00 (A=034, B=154) +Fout=1978.20 (A=035, B=154) +Fout=1978.40 (A=036, B=154) +Fout=1978.60 (A=037, B=154) +Fout=1978.80 (A=038, B=154) +Fout=1979.00 (A=039, B=154) +Fout=1979.20 (A=040, B=154) +Fout=1979.40 (A=041, B=154) +Fout=1979.60 (A=042, B=154) +Fout=1979.80 (A=043, B=154) +Fout=1980.00 (A=044, B=154) +Fout=1980.20 (A=045, B=154) +Fout=1980.40 (A=046, B=154) +Fout=1980.60 (A=047, B=154) +Fout=1980.80 (A=048, B=154) +Fout=1981.00 (A=049, B=154) +Fout=1981.20 (A=050, B=154) +Fout=1981.40 (A=051, B=154) +Fout=1981.60 (A=052, B=154) +Fout=1981.80 (A=053, B=154) +Fout=1982.00 (A=054, B=154) +Fout=1982.20 (A=055, B=154) +Fout=1982.40 (A=056, B=154) +Fout=1982.60 (A=057, B=154) +Fout=1982.80 (A=058, B=154) +Fout=1983.00 (A=059, B=154) +Fout=1983.20 (A=060, B=154) +Fout=1983.40 (A=061, B=154) +Fout=1983.60 (A=062, B=154) +Fout=1984.00 (A=000, B=155) +Fout=1984.20 (A=001, B=155) +Fout=1984.40 (A=002, B=155) +Fout=1984.60 (A=003, B=155) +Fout=1984.80 (A=004, B=155) +Fout=1985.00 (A=005, B=155) +Fout=1985.20 (A=006, B=155) +Fout=1985.40 (A=007, B=155) +Fout=1985.60 (A=008, B=155) +Fout=1985.80 (A=009, B=155) +Fout=1986.00 (A=010, B=155) +Fout=1986.20 (A=011, B=155) +Fout=1986.40 (A=012, B=155) +Fout=1986.60 (A=013, B=155) +Fout=1986.80 (A=014, B=155) +Fout=1987.00 (A=015, B=155) +Fout=1987.20 (A=016, B=155) +Fout=1987.40 (A=017, B=155) +Fout=1987.60 (A=018, B=155) +Fout=1987.80 (A=019, B=155) +Fout=1988.00 (A=020, B=155) +Fout=1988.20 (A=021, B=155) +Fout=1988.40 (A=022, B=155) +Fout=1988.60 (A=023, B=155) +Fout=1988.80 (A=024, B=155) +Fout=1989.00 (A=025, B=155) +Fout=1989.20 (A=026, B=155) +Fout=1989.40 (A=027, B=155) +Fout=1989.60 (A=028, B=155) +Fout=1989.80 (A=029, B=155) +Fout=1990.00 (A=030, B=155) +Fout=1990.20 (A=031, B=155) +Fout=1990.40 (A=032, B=155) +Fout=1990.60 (A=033, B=155) +Fout=1990.80 (A=034, B=155) +Fout=1991.00 (A=035, B=155) +Fout=1991.20 (A=036, B=155) +Fout=1991.40 (A=037, B=155) +Fout=1991.60 (A=038, B=155) +Fout=1991.80 (A=039, B=155) +Fout=1992.00 (A=040, B=155) +Fout=1992.20 (A=041, B=155) +Fout=1992.40 (A=042, B=155) +Fout=1992.60 (A=043, B=155) +Fout=1992.80 (A=044, B=155) +Fout=1993.00 (A=045, B=155) +Fout=1993.20 (A=046, B=155) +Fout=1993.40 (A=047, B=155) +Fout=1993.60 (A=048, B=155) +Fout=1993.80 (A=049, B=155) +Fout=1994.00 (A=050, B=155) +Fout=1994.20 (A=051, B=155) +Fout=1994.40 (A=052, B=155) +Fout=1994.60 (A=053, B=155) +Fout=1994.80 (A=054, B=155) +Fout=1995.00 (A=055, B=155) +Fout=1995.20 (A=056, B=155) +Fout=1995.40 (A=057, B=155) +Fout=1995.60 (A=058, B=155) +Fout=1995.80 (A=059, B=155) +Fout=1996.00 (A=060, B=155) +Fout=1996.20 (A=061, B=155) +Fout=1996.40 (A=062, B=155) +====================================================================== +PLL Tx GSM850_1 +Fout=819.20 (A=000, B=128) +Fout=819.30 (A=001, B=128) +Fout=819.40 (A=002, B=128) +Fout=819.50 (A=003, B=128) +Fout=819.60 (A=004, B=128) +Fout=819.70 (A=005, B=128) +Fout=819.80 (A=006, B=128) +Fout=819.90 (A=007, B=128) +Fout=820.00 (A=008, B=128) +Fout=820.10 (A=009, B=128) +Fout=820.20 (A=010, B=128) +Fout=820.30 (A=011, B=128) +Fout=820.40 (A=012, B=128) +Fout=820.50 (A=013, B=128) +Fout=820.60 (A=014, B=128) +Fout=820.70 (A=015, B=128) +Fout=820.80 (A=016, B=128) +Fout=820.90 (A=017, B=128) +Fout=821.00 (A=018, B=128) +Fout=821.10 (A=019, B=128) +Fout=821.20 (A=020, B=128) +Fout=821.30 (A=021, B=128) +Fout=821.40 (A=022, B=128) +Fout=821.50 (A=023, B=128) +Fout=821.60 (A=024, B=128) +Fout=821.70 (A=025, B=128) +Fout=821.80 (A=026, B=128) +Fout=821.90 (A=027, B=128) +Fout=822.00 (A=028, B=128) +Fout=822.10 (A=029, B=128) +Fout=822.20 (A=030, B=128) +Fout=822.30 (A=031, B=128) +Fout=822.40 (A=032, B=128) +Fout=822.50 (A=033, B=128) +Fout=822.60 (A=034, B=128) +Fout=822.70 (A=035, B=128) +Fout=822.80 (A=036, B=128) +Fout=822.90 (A=037, B=128) +Fout=823.00 (A=038, B=128) +Fout=823.10 (A=039, B=128) +Fout=823.20 (A=040, B=128) +Fout=823.30 (A=041, B=128) +Fout=823.40 (A=042, B=128) +Fout=823.50 (A=043, B=128) +Fout=823.60 (A=044, B=128) +Fout=823.70 (A=045, B=128) +Fout=823.80 (A=046, B=128) +Fout=823.90 (A=047, B=128) +Fout=824.00 (A=048, B=128) +Fout=824.10 (A=049, B=128) +Fout=824.20 (A=050, B=128) +Fout=824.30 (A=051, B=128) +Fout=824.40 (A=052, B=128) +Fout=824.50 (A=053, B=128) +Fout=824.60 (A=054, B=128) +Fout=824.70 (A=055, B=128) +Fout=824.80 (A=056, B=128) +Fout=824.90 (A=057, B=128) +Fout=825.00 (A=058, B=128) +Fout=825.10 (A=059, B=128) +Fout=825.20 (A=060, B=128) +Fout=825.30 (A=061, B=128) +Fout=825.40 (A=062, B=128) +Fout=825.60 (A=000, B=129) +Fout=825.70 (A=001, B=129) +Fout=825.80 (A=002, B=129) +Fout=825.90 (A=003, B=129) +Fout=826.00 (A=004, B=129) +Fout=826.10 (A=005, B=129) +Fout=826.20 (A=006, B=129) +Fout=826.30 (A=007, B=129) +Fout=826.40 (A=008, B=129) +Fout=826.50 (A=009, B=129) +Fout=826.60 (A=010, B=129) +Fout=826.70 (A=011, B=129) +Fout=826.80 (A=012, B=129) +Fout=826.90 (A=013, B=129) +Fout=827.00 (A=014, B=129) +Fout=827.10 (A=015, B=129) +Fout=827.20 (A=016, B=129) +Fout=827.30 (A=017, B=129) +Fout=827.40 (A=018, B=129) +Fout=827.50 (A=019, B=129) +Fout=827.60 (A=020, B=129) +Fout=827.70 (A=021, B=129) +Fout=827.80 (A=022, B=129) +Fout=827.90 (A=023, B=129) +Fout=828.00 (A=024, B=129) +Fout=828.10 (A=025, B=129) +Fout=828.20 (A=026, B=129) +Fout=828.30 (A=027, B=129) +Fout=828.40 (A=028, B=129) +Fout=828.50 (A=029, B=129) +Fout=828.60 (A=030, B=129) +Fout=828.70 (A=031, B=129) +Fout=828.80 (A=032, B=129) +Fout=828.90 (A=033, B=129) +Fout=829.00 (A=034, B=129) +Fout=829.10 (A=035, B=129) +Fout=829.20 (A=036, B=129) +Fout=829.30 (A=037, B=129) +Fout=829.40 (A=038, B=129) +Fout=829.50 (A=039, B=129) +Fout=829.60 (A=040, B=129) +Fout=829.70 (A=041, B=129) +Fout=829.80 (A=042, B=129) +Fout=829.90 (A=043, B=129) +Fout=830.00 (A=044, B=129) +Fout=830.10 (A=045, B=129) +Fout=830.20 (A=046, B=129) +Fout=830.30 (A=047, B=129) +Fout=830.40 (A=048, B=129) +Fout=830.50 (A=049, B=129) +Fout=830.60 (A=050, B=129) +Fout=830.70 (A=051, B=129) +Fout=830.80 (A=052, B=129) +Fout=830.90 (A=053, B=129) +Fout=831.00 (A=054, B=129) +Fout=831.10 (A=055, B=129) +Fout=831.20 (A=056, B=129) +Fout=831.30 (A=057, B=129) +Fout=831.40 (A=058, B=129) +Fout=831.50 (A=059, B=129) +Fout=831.60 (A=060, B=129) +Fout=831.70 (A=061, B=129) +Fout=831.80 (A=062, B=129) +Fout=832.00 (A=000, B=130) +Fout=832.10 (A=001, B=130) +Fout=832.20 (A=002, B=130) +Fout=832.30 (A=003, B=130) +Fout=832.40 (A=004, B=130) +Fout=832.50 (A=005, B=130) +Fout=832.60 (A=006, B=130) +Fout=832.70 (A=007, B=130) +Fout=832.80 (A=008, B=130) +Fout=832.90 (A=009, B=130) +Fout=833.00 (A=010, B=130) +Fout=833.10 (A=011, B=130) +Fout=833.20 (A=012, B=130) +Fout=833.30 (A=013, B=130) +Fout=833.40 (A=014, B=130) +Fout=833.50 (A=015, B=130) +Fout=833.60 (A=016, B=130) +Fout=833.70 (A=017, B=130) +Fout=833.80 (A=018, B=130) +Fout=833.90 (A=019, B=130) +Fout=834.00 (A=020, B=130) +Fout=834.10 (A=021, B=130) +Fout=834.20 (A=022, B=130) +Fout=834.30 (A=023, B=130) +Fout=834.40 (A=024, B=130) +Fout=834.50 (A=025, B=130) +Fout=834.60 (A=026, B=130) +Fout=834.70 (A=027, B=130) +Fout=834.80 (A=028, B=130) +Fout=834.90 (A=029, B=130) +Fout=835.00 (A=030, B=130) +Fout=835.10 (A=031, B=130) +Fout=835.20 (A=032, B=130) +Fout=835.30 (A=033, B=130) +Fout=835.40 (A=034, B=130) +Fout=835.50 (A=035, B=130) +Fout=835.60 (A=036, B=130) +Fout=835.70 (A=037, B=130) +Fout=835.80 (A=038, B=130) +Fout=835.90 (A=039, B=130) +Fout=836.00 (A=040, B=130) +Fout=836.10 (A=041, B=130) +Fout=836.20 (A=042, B=130) +Fout=836.30 (A=043, B=130) +Fout=836.40 (A=044, B=130) +Fout=836.50 (A=045, B=130) +Fout=836.60 (A=046, B=130) +Fout=836.70 (A=047, B=130) +Fout=836.80 (A=048, B=130) +Fout=836.90 (A=049, B=130) +Fout=837.00 (A=050, B=130) +Fout=837.10 (A=051, B=130) +Fout=837.20 (A=052, B=130) +Fout=837.30 (A=053, B=130) +Fout=837.40 (A=054, B=130) +Fout=837.50 (A=055, B=130) +Fout=837.60 (A=056, B=130) +Fout=837.70 (A=057, B=130) +Fout=837.80 (A=058, B=130) +Fout=837.90 (A=059, B=130) +Fout=838.00 (A=060, B=130) +Fout=838.10 (A=061, B=130) +Fout=838.20 (A=062, B=130) +====================================================================== +PLL Tx GSM850_2 +Fout=832.00 (A=000, B=065) +Fout=832.20 (A=001, B=065) +Fout=832.40 (A=002, B=065) +Fout=832.60 (A=003, B=065) +Fout=832.80 (A=004, B=065) +Fout=833.00 (A=005, B=065) +Fout=833.20 (A=006, B=065) +Fout=833.40 (A=007, B=065) +Fout=833.60 (A=008, B=065) +Fout=833.80 (A=009, B=065) +Fout=834.00 (A=010, B=065) +Fout=834.20 (A=011, B=065) +Fout=834.40 (A=012, B=065) +Fout=834.60 (A=013, B=065) +Fout=834.80 (A=014, B=065) +Fout=835.00 (A=015, B=065) +Fout=835.20 (A=016, B=065) +Fout=835.40 (A=017, B=065) +Fout=835.60 (A=018, B=065) +Fout=835.80 (A=019, B=065) +Fout=836.00 (A=020, B=065) +Fout=836.20 (A=021, B=065) +Fout=836.40 (A=022, B=065) +Fout=836.60 (A=023, B=065) +Fout=836.80 (A=024, B=065) +Fout=837.00 (A=025, B=065) +Fout=837.20 (A=026, B=065) +Fout=837.40 (A=027, B=065) +Fout=837.60 (A=028, B=065) +Fout=837.80 (A=029, B=065) +Fout=838.00 (A=030, B=065) +Fout=838.20 (A=031, B=065) +Fout=838.40 (A=032, B=065) +Fout=838.60 (A=033, B=065) +Fout=838.80 (A=034, B=065) +Fout=839.00 (A=035, B=065) +Fout=839.20 (A=036, B=065) +Fout=839.40 (A=037, B=065) +Fout=839.60 (A=038, B=065) +Fout=839.80 (A=039, B=065) +Fout=840.00 (A=040, B=065) +Fout=840.20 (A=041, B=065) +Fout=840.40 (A=042, B=065) +Fout=840.60 (A=043, B=065) +Fout=840.80 (A=044, B=065) +Fout=841.00 (A=045, B=065) +Fout=841.20 (A=046, B=065) +Fout=841.40 (A=047, B=065) +Fout=841.60 (A=048, B=065) +Fout=841.80 (A=049, B=065) +Fout=842.00 (A=050, B=065) +Fout=842.20 (A=051, B=065) +Fout=842.40 (A=052, B=065) +Fout=842.60 (A=053, B=065) +Fout=842.80 (A=054, B=065) +Fout=843.00 (A=055, B=065) +Fout=843.20 (A=056, B=065) +Fout=843.40 (A=057, B=065) +Fout=843.60 (A=058, B=065) +Fout=843.80 (A=059, B=065) +Fout=844.00 (A=060, B=065) +Fout=844.20 (A=061, B=065) +Fout=844.40 (A=062, B=065) +Fout=844.60 (A=063, B=065) +Fout=844.80 (A=000, B=066) +Fout=845.00 (A=001, B=066) +Fout=845.20 (A=002, B=066) +Fout=845.40 (A=003, B=066) +Fout=845.60 (A=004, B=066) +Fout=845.80 (A=005, B=066) +Fout=846.00 (A=006, B=066) +Fout=846.20 (A=007, B=066) +Fout=846.40 (A=008, B=066) +Fout=846.60 (A=009, B=066) +Fout=846.80 (A=010, B=066) +Fout=847.00 (A=011, B=066) +Fout=847.20 (A=012, B=066) +Fout=847.40 (A=013, B=066) +Fout=847.60 (A=014, B=066) +Fout=847.80 (A=015, B=066) +Fout=848.00 (A=016, B=066) +Fout=848.20 (A=017, B=066) +Fout=848.40 (A=018, B=066) +Fout=848.60 (A=019, B=066) +Fout=848.80 (A=020, B=066) +Fout=849.00 (A=021, B=066) +Fout=849.20 (A=022, B=066) +Fout=849.40 (A=023, B=066) +Fout=849.60 (A=024, B=066) +Fout=849.80 (A=025, B=066) +Fout=850.00 (A=026, B=066) +Fout=850.20 (A=027, B=066) +Fout=850.40 (A=028, B=066) +Fout=850.60 (A=029, B=066) +Fout=850.80 (A=030, B=066) +Fout=851.00 (A=031, B=066) +Fout=851.20 (A=032, B=066) +Fout=851.40 (A=033, B=066) +Fout=851.60 (A=034, B=066) +Fout=851.80 (A=035, B=066) +Fout=852.00 (A=036, B=066) +Fout=852.20 (A=037, B=066) +Fout=852.40 (A=038, B=066) +Fout=852.60 (A=039, B=066) +Fout=852.80 (A=040, B=066) +Fout=853.00 (A=041, B=066) +Fout=853.20 (A=042, B=066) +Fout=853.40 (A=043, B=066) +Fout=853.60 (A=044, B=066) +Fout=853.80 (A=045, B=066) +Fout=854.00 (A=046, B=066) +Fout=854.20 (A=047, B=066) +Fout=854.40 (A=048, B=066) +Fout=854.60 (A=049, B=066) +Fout=854.80 (A=050, B=066) +Fout=855.00 (A=051, B=066) +Fout=855.20 (A=052, B=066) +Fout=855.40 (A=053, B=066) +Fout=855.60 (A=054, B=066) +Fout=855.80 (A=055, B=066) +Fout=856.00 (A=056, B=066) +Fout=856.20 (A=057, B=066) +Fout=856.40 (A=058, B=066) +Fout=856.60 (A=059, B=066) +Fout=856.80 (A=060, B=066) +Fout=857.00 (A=061, B=066) +Fout=857.20 (A=062, B=066) +Fout=857.40 (A=063, B=066) +====================================================================== +PLL Tx GSM900 +Fout=870.40 (A=000, B=068) +Fout=870.60 (A=001, B=068) +Fout=870.80 (A=002, B=068) +Fout=871.00 (A=003, B=068) +Fout=871.20 (A=004, B=068) +Fout=871.40 (A=005, B=068) +Fout=871.60 (A=006, B=068) +Fout=871.80 (A=007, B=068) +Fout=872.00 (A=008, B=068) +Fout=872.20 (A=009, B=068) +Fout=872.40 (A=010, B=068) +Fout=872.60 (A=011, B=068) +Fout=872.80 (A=012, B=068) +Fout=873.00 (A=013, B=068) +Fout=873.20 (A=014, B=068) +Fout=873.40 (A=015, B=068) +Fout=873.60 (A=016, B=068) +Fout=873.80 (A=017, B=068) +Fout=874.00 (A=018, B=068) +Fout=874.20 (A=019, B=068) +Fout=874.40 (A=020, B=068) +Fout=874.60 (A=021, B=068) +Fout=874.80 (A=022, B=068) +Fout=875.00 (A=023, B=068) +Fout=875.20 (A=024, B=068) +Fout=875.40 (A=025, B=068) +Fout=875.60 (A=026, B=068) +Fout=875.80 (A=027, B=068) +Fout=876.00 (A=028, B=068) +Fout=876.20 (A=029, B=068) +Fout=876.40 (A=030, B=068) +Fout=876.60 (A=031, B=068) +Fout=876.80 (A=032, B=068) +Fout=877.00 (A=033, B=068) +Fout=877.20 (A=034, B=068) +Fout=877.40 (A=035, B=068) +Fout=877.60 (A=036, B=068) +Fout=877.80 (A=037, B=068) +Fout=878.00 (A=038, B=068) +Fout=878.20 (A=039, B=068) +Fout=878.40 (A=040, B=068) +Fout=878.60 (A=041, B=068) +Fout=878.80 (A=042, B=068) +Fout=879.00 (A=043, B=068) +Fout=879.20 (A=044, B=068) +Fout=879.40 (A=045, B=068) +Fout=879.60 (A=046, B=068) +Fout=879.80 (A=047, B=068) +Fout=880.00 (A=048, B=068) +Fout=880.20 (A=049, B=068) +Fout=880.40 (A=050, B=068) +Fout=880.60 (A=051, B=068) +Fout=880.80 (A=052, B=068) +Fout=881.00 (A=053, B=068) +Fout=881.20 (A=054, B=068) +Fout=881.40 (A=055, B=068) +Fout=881.60 (A=056, B=068) +Fout=881.80 (A=057, B=068) +Fout=882.00 (A=058, B=068) +Fout=882.20 (A=059, B=068) +Fout=882.40 (A=060, B=068) +Fout=882.60 (A=061, B=068) +Fout=882.80 (A=062, B=068) +Fout=883.00 (A=063, B=068) +Fout=883.20 (A=000, B=069) +Fout=883.40 (A=001, B=069) +Fout=883.60 (A=002, B=069) +Fout=883.80 (A=003, B=069) +Fout=884.00 (A=004, B=069) +Fout=884.20 (A=005, B=069) +Fout=884.40 (A=006, B=069) +Fout=884.60 (A=007, B=069) +Fout=884.80 (A=008, B=069) +Fout=885.00 (A=009, B=069) +Fout=885.20 (A=010, B=069) +Fout=885.40 (A=011, B=069) +Fout=885.60 (A=012, B=069) +Fout=885.80 (A=013, B=069) +Fout=886.00 (A=014, B=069) +Fout=886.20 (A=015, B=069) +Fout=886.40 (A=016, B=069) +Fout=886.60 (A=017, B=069) +Fout=886.80 (A=018, B=069) +Fout=887.00 (A=019, B=069) +Fout=887.20 (A=020, B=069) +Fout=887.40 (A=021, B=069) +Fout=887.60 (A=022, B=069) +Fout=887.80 (A=023, B=069) +Fout=888.00 (A=024, B=069) +Fout=888.20 (A=025, B=069) +Fout=888.40 (A=026, B=069) +Fout=888.60 (A=027, B=069) +Fout=888.80 (A=028, B=069) +Fout=889.00 (A=029, B=069) +Fout=889.20 (A=030, B=069) +Fout=889.40 (A=031, B=069) +Fout=889.60 (A=032, B=069) +Fout=889.80 (A=033, B=069) +Fout=890.00 (A=034, B=069) +Fout=890.20 (A=035, B=069) +Fout=890.40 (A=036, B=069) +Fout=890.60 (A=037, B=069) +Fout=890.80 (A=038, B=069) +Fout=891.00 (A=039, B=069) +Fout=891.20 (A=040, B=069) +Fout=891.40 (A=041, B=069) +Fout=891.60 (A=042, B=069) +Fout=891.80 (A=043, B=069) +Fout=892.00 (A=044, B=069) +Fout=892.20 (A=045, B=069) +Fout=892.40 (A=046, B=069) +Fout=892.60 (A=047, B=069) +Fout=892.80 (A=048, B=069) +Fout=893.00 (A=049, B=069) +Fout=893.20 (A=050, B=069) +Fout=893.40 (A=051, B=069) +Fout=893.60 (A=052, B=069) +Fout=893.80 (A=053, B=069) +Fout=894.00 (A=054, B=069) +Fout=894.20 (A=055, B=069) +Fout=894.40 (A=056, B=069) +Fout=894.60 (A=057, B=069) +Fout=894.80 (A=058, B=069) +Fout=895.00 (A=059, B=069) +Fout=895.20 (A=060, B=069) +Fout=895.40 (A=061, B=069) +Fout=895.60 (A=062, B=069) +Fout=895.80 (A=063, B=069) +Fout=896.00 (A=000, B=070) +Fout=896.20 (A=001, B=070) +Fout=896.40 (A=002, B=070) +Fout=896.60 (A=003, B=070) +Fout=896.80 (A=004, B=070) +Fout=897.00 (A=005, B=070) +Fout=897.20 (A=006, B=070) +Fout=897.40 (A=007, B=070) +Fout=897.60 (A=008, B=070) +Fout=897.80 (A=009, B=070) +Fout=898.00 (A=010, B=070) +Fout=898.20 (A=011, B=070) +Fout=898.40 (A=012, B=070) +Fout=898.60 (A=013, B=070) +Fout=898.80 (A=014, B=070) +Fout=899.00 (A=015, B=070) +Fout=899.20 (A=016, B=070) +Fout=899.40 (A=017, B=070) +Fout=899.60 (A=018, B=070) +Fout=899.80 (A=019, B=070) +Fout=900.00 (A=020, B=070) +Fout=900.20 (A=021, B=070) +Fout=900.40 (A=022, B=070) +Fout=900.60 (A=023, B=070) +Fout=900.80 (A=024, B=070) +Fout=901.00 (A=025, B=070) +Fout=901.20 (A=026, B=070) +Fout=901.40 (A=027, B=070) +Fout=901.60 (A=028, B=070) +Fout=901.80 (A=029, B=070) +Fout=902.00 (A=030, B=070) +Fout=902.20 (A=031, B=070) +Fout=902.40 (A=032, B=070) +Fout=902.60 (A=033, B=070) +Fout=902.80 (A=034, B=070) +Fout=903.00 (A=035, B=070) +Fout=903.20 (A=036, B=070) +Fout=903.40 (A=037, B=070) +Fout=903.60 (A=038, B=070) +Fout=903.80 (A=039, B=070) +Fout=904.00 (A=040, B=070) +Fout=904.20 (A=041, B=070) +Fout=904.40 (A=042, B=070) +Fout=904.60 (A=043, B=070) +Fout=904.80 (A=044, B=070) +Fout=905.00 (A=045, B=070) +Fout=905.20 (A=046, B=070) +Fout=905.40 (A=047, B=070) +Fout=905.60 (A=048, B=070) +Fout=905.80 (A=049, B=070) +Fout=906.00 (A=050, B=070) +Fout=906.20 (A=051, B=070) +Fout=906.40 (A=052, B=070) +Fout=906.60 (A=053, B=070) +Fout=906.80 (A=054, B=070) +Fout=907.00 (A=055, B=070) +Fout=907.20 (A=056, B=070) +Fout=907.40 (A=057, B=070) +Fout=907.60 (A=058, B=070) +Fout=907.80 (A=059, B=070) +Fout=908.00 (A=060, B=070) +Fout=908.20 (A=061, B=070) +Fout=908.40 (A=062, B=070) +Fout=908.60 (A=063, B=070) +Fout=908.80 (A=000, B=071) +Fout=909.00 (A=001, B=071) +Fout=909.20 (A=002, B=071) +Fout=909.40 (A=003, B=071) +Fout=909.60 (A=004, B=071) +Fout=909.80 (A=005, B=071) +Fout=910.00 (A=006, B=071) +Fout=910.20 (A=007, B=071) +Fout=910.40 (A=008, B=071) +Fout=910.60 (A=009, B=071) +Fout=910.80 (A=010, B=071) +Fout=911.00 (A=011, B=071) +Fout=911.20 (A=012, B=071) +Fout=911.40 (A=013, B=071) +Fout=911.60 (A=014, B=071) +Fout=911.80 (A=015, B=071) +Fout=912.00 (A=016, B=071) +Fout=912.20 (A=017, B=071) +Fout=912.40 (A=018, B=071) +Fout=912.60 (A=019, B=071) +Fout=912.80 (A=020, B=071) +Fout=913.00 (A=021, B=071) +Fout=913.20 (A=022, B=071) +Fout=913.40 (A=023, B=071) +Fout=913.60 (A=024, B=071) +Fout=913.80 (A=025, B=071) +Fout=914.00 (A=026, B=071) +Fout=914.20 (A=027, B=071) +Fout=914.40 (A=028, B=071) +Fout=914.60 (A=029, B=071) +Fout=914.80 (A=030, B=071) +Fout=915.00 (A=031, B=071) +Fout=915.20 (A=032, B=071) +Fout=915.40 (A=033, B=071) +Fout=915.60 (A=034, B=071) +Fout=915.80 (A=035, B=071) +Fout=916.00 (A=036, B=071) +Fout=916.20 (A=037, B=071) +Fout=916.40 (A=038, B=071) +Fout=916.60 (A=039, B=071) +Fout=916.80 (A=040, B=071) +Fout=917.00 (A=041, B=071) +Fout=917.20 (A=042, B=071) +Fout=917.40 (A=043, B=071) +Fout=917.60 (A=044, B=071) +Fout=917.80 (A=045, B=071) +Fout=918.00 (A=046, B=071) +Fout=918.20 (A=047, B=071) +Fout=918.40 (A=048, B=071) +Fout=918.60 (A=049, B=071) +Fout=918.80 (A=050, B=071) +Fout=919.00 (A=051, B=071) +Fout=919.20 (A=052, B=071) +Fout=919.40 (A=053, B=071) +Fout=919.60 (A=054, B=071) +Fout=919.80 (A=055, B=071) +Fout=920.00 (A=056, B=071) +Fout=920.20 (A=057, B=071) +Fout=920.40 (A=058, B=071) +Fout=920.60 (A=059, B=071) +Fout=920.80 (A=060, B=071) +Fout=921.00 (A=061, B=071) +Fout=921.20 (A=062, B=071) +Fout=921.40 (A=063, B=071) +====================================================================== +PLL Tx GSM1800/1900 +Fout=1702.40 (A=000, B=133) +Fout=1702.60 (A=001, B=133) +Fout=1702.80 (A=002, B=133) +Fout=1703.00 (A=003, B=133) +Fout=1703.20 (A=004, B=133) +Fout=1703.40 (A=005, B=133) +Fout=1703.60 (A=006, B=133) +Fout=1703.80 (A=007, B=133) +Fout=1704.00 (A=008, B=133) +Fout=1704.20 (A=009, B=133) +Fout=1704.40 (A=010, B=133) +Fout=1704.60 (A=011, B=133) +Fout=1704.80 (A=012, B=133) +Fout=1705.00 (A=013, B=133) +Fout=1705.20 (A=014, B=133) +Fout=1705.40 (A=015, B=133) +Fout=1705.60 (A=016, B=133) +Fout=1705.80 (A=017, B=133) +Fout=1706.00 (A=018, B=133) +Fout=1706.20 (A=019, B=133) +Fout=1706.40 (A=020, B=133) +Fout=1706.60 (A=021, B=133) +Fout=1706.80 (A=022, B=133) +Fout=1707.00 (A=023, B=133) +Fout=1707.20 (A=024, B=133) +Fout=1707.40 (A=025, B=133) +Fout=1707.60 (A=026, B=133) +Fout=1707.80 (A=027, B=133) +Fout=1708.00 (A=028, B=133) +Fout=1708.20 (A=029, B=133) +Fout=1708.40 (A=030, B=133) +Fout=1708.60 (A=031, B=133) +Fout=1708.80 (A=032, B=133) +Fout=1709.00 (A=033, B=133) +Fout=1709.20 (A=034, B=133) +Fout=1709.40 (A=035, B=133) +Fout=1709.60 (A=036, B=133) +Fout=1709.80 (A=037, B=133) +Fout=1710.00 (A=038, B=133) +Fout=1710.20 (A=039, B=133) +Fout=1710.40 (A=040, B=133) +Fout=1710.60 (A=041, B=133) +Fout=1710.80 (A=042, B=133) +Fout=1711.00 (A=043, B=133) +Fout=1711.20 (A=044, B=133) +Fout=1711.40 (A=045, B=133) +Fout=1711.60 (A=046, B=133) +Fout=1711.80 (A=047, B=133) +Fout=1712.00 (A=048, B=133) +Fout=1712.20 (A=049, B=133) +Fout=1712.40 (A=050, B=133) +Fout=1712.60 (A=051, B=133) +Fout=1712.80 (A=052, B=133) +Fout=1713.00 (A=053, B=133) +Fout=1713.20 (A=054, B=133) +Fout=1713.40 (A=055, B=133) +Fout=1713.60 (A=056, B=133) +Fout=1713.80 (A=057, B=133) +Fout=1714.00 (A=058, B=133) +Fout=1714.20 (A=059, B=133) +Fout=1714.40 (A=060, B=133) +Fout=1714.60 (A=061, B=133) +Fout=1714.80 (A=062, B=133) +Fout=1715.00 (A=063, B=133) +Fout=1715.20 (A=000, B=134) +Fout=1715.40 (A=001, B=134) +Fout=1715.60 (A=002, B=134) +Fout=1715.80 (A=003, B=134) +Fout=1716.00 (A=004, B=134) +Fout=1716.20 (A=005, B=134) +Fout=1716.40 (A=006, B=134) +Fout=1716.60 (A=007, B=134) +Fout=1716.80 (A=008, B=134) +Fout=1717.00 (A=009, B=134) +Fout=1717.20 (A=010, B=134) +Fout=1717.40 (A=011, B=134) +Fout=1717.60 (A=012, B=134) +Fout=1717.80 (A=013, B=134) +Fout=1718.00 (A=014, B=134) +Fout=1718.20 (A=015, B=134) +Fout=1718.40 (A=016, B=134) +Fout=1718.60 (A=017, B=134) +Fout=1718.80 (A=018, B=134) +Fout=1719.00 (A=019, B=134) +Fout=1719.20 (A=020, B=134) +Fout=1719.40 (A=021, B=134) +Fout=1719.60 (A=022, B=134) +Fout=1719.80 (A=023, B=134) +Fout=1720.00 (A=024, B=134) +Fout=1720.20 (A=025, B=134) +Fout=1720.40 (A=026, B=134) +Fout=1720.60 (A=027, B=134) +Fout=1720.80 (A=028, B=134) +Fout=1721.00 (A=029, B=134) +Fout=1721.20 (A=030, B=134) +Fout=1721.40 (A=031, B=134) +Fout=1721.60 (A=032, B=134) +Fout=1721.80 (A=033, B=134) +Fout=1722.00 (A=034, B=134) +Fout=1722.20 (A=035, B=134) +Fout=1722.40 (A=036, B=134) +Fout=1722.60 (A=037, B=134) +Fout=1722.80 (A=038, B=134) +Fout=1723.00 (A=039, B=134) +Fout=1723.20 (A=040, B=134) +Fout=1723.40 (A=041, B=134) +Fout=1723.60 (A=042, B=134) +Fout=1723.80 (A=043, B=134) +Fout=1724.00 (A=044, B=134) +Fout=1724.20 (A=045, B=134) +Fout=1724.40 (A=046, B=134) +Fout=1724.60 (A=047, B=134) +Fout=1724.80 (A=048, B=134) +Fout=1725.00 (A=049, B=134) +Fout=1725.20 (A=050, B=134) +Fout=1725.40 (A=051, B=134) +Fout=1725.60 (A=052, B=134) +Fout=1725.80 (A=053, B=134) +Fout=1726.00 (A=054, B=134) +Fout=1726.20 (A=055, B=134) +Fout=1726.40 (A=056, B=134) +Fout=1726.60 (A=057, B=134) +Fout=1726.80 (A=058, B=134) +Fout=1727.00 (A=059, B=134) +Fout=1727.20 (A=060, B=134) +Fout=1727.40 (A=061, B=134) +Fout=1727.60 (A=062, B=134) +Fout=1727.80 (A=063, B=134) +Fout=1728.00 (A=000, B=135) +Fout=1728.20 (A=001, B=135) +Fout=1728.40 (A=002, B=135) +Fout=1728.60 (A=003, B=135) +Fout=1728.80 (A=004, B=135) +Fout=1729.00 (A=005, B=135) +Fout=1729.20 (A=006, B=135) +Fout=1729.40 (A=007, B=135) +Fout=1729.60 (A=008, B=135) +Fout=1729.80 (A=009, B=135) +Fout=1730.00 (A=010, B=135) +Fout=1730.20 (A=011, B=135) +Fout=1730.40 (A=012, B=135) +Fout=1730.60 (A=013, B=135) +Fout=1730.80 (A=014, B=135) +Fout=1731.00 (A=015, B=135) +Fout=1731.20 (A=016, B=135) +Fout=1731.40 (A=017, B=135) +Fout=1731.60 (A=018, B=135) +Fout=1731.80 (A=019, B=135) +Fout=1732.00 (A=020, B=135) +Fout=1732.20 (A=021, B=135) +Fout=1732.40 (A=022, B=135) +Fout=1732.60 (A=023, B=135) +Fout=1732.80 (A=024, B=135) +Fout=1733.00 (A=025, B=135) +Fout=1733.20 (A=026, B=135) +Fout=1733.40 (A=027, B=135) +Fout=1733.60 (A=028, B=135) +Fout=1733.80 (A=029, B=135) +Fout=1734.00 (A=030, B=135) +Fout=1734.20 (A=031, B=135) +Fout=1734.40 (A=032, B=135) +Fout=1734.60 (A=033, B=135) +Fout=1734.80 (A=034, B=135) +Fout=1735.00 (A=035, B=135) +Fout=1735.20 (A=036, B=135) +Fout=1735.40 (A=037, B=135) +Fout=1735.60 (A=038, B=135) +Fout=1735.80 (A=039, B=135) +Fout=1736.00 (A=040, B=135) +Fout=1736.20 (A=041, B=135) +Fout=1736.40 (A=042, B=135) +Fout=1736.60 (A=043, B=135) +Fout=1736.80 (A=044, B=135) +Fout=1737.00 (A=045, B=135) +Fout=1737.20 (A=046, B=135) +Fout=1737.40 (A=047, B=135) +Fout=1737.60 (A=048, B=135) +Fout=1737.80 (A=049, B=135) +Fout=1738.00 (A=050, B=135) +Fout=1738.20 (A=051, B=135) +Fout=1738.40 (A=052, B=135) +Fout=1738.60 (A=053, B=135) +Fout=1738.80 (A=054, B=135) +Fout=1739.00 (A=055, B=135) +Fout=1739.20 (A=056, B=135) +Fout=1739.40 (A=057, B=135) +Fout=1739.60 (A=058, B=135) +Fout=1739.80 (A=059, B=135) +Fout=1740.00 (A=060, B=135) +Fout=1740.20 (A=061, B=135) +Fout=1740.40 (A=062, B=135) +Fout=1740.60 (A=063, B=135) +Fout=1740.80 (A=000, B=136) +Fout=1741.00 (A=001, B=136) +Fout=1741.20 (A=002, B=136) +Fout=1741.40 (A=003, B=136) +Fout=1741.60 (A=004, B=136) +Fout=1741.80 (A=005, B=136) +Fout=1742.00 (A=006, B=136) +Fout=1742.20 (A=007, B=136) +Fout=1742.40 (A=008, B=136) +Fout=1742.60 (A=009, B=136) +Fout=1742.80 (A=010, B=136) +Fout=1743.00 (A=011, B=136) +Fout=1743.20 (A=012, B=136) +Fout=1743.40 (A=013, B=136) +Fout=1743.60 (A=014, B=136) +Fout=1743.80 (A=015, B=136) +Fout=1744.00 (A=016, B=136) +Fout=1744.20 (A=017, B=136) +Fout=1744.40 (A=018, B=136) +Fout=1744.60 (A=019, B=136) +Fout=1744.80 (A=020, B=136) +Fout=1745.00 (A=021, B=136) +Fout=1745.20 (A=022, B=136) +Fout=1745.40 (A=023, B=136) +Fout=1745.60 (A=024, B=136) +Fout=1745.80 (A=025, B=136) +Fout=1746.00 (A=026, B=136) +Fout=1746.20 (A=027, B=136) +Fout=1746.40 (A=028, B=136) +Fout=1746.60 (A=029, B=136) +Fout=1746.80 (A=030, B=136) +Fout=1747.00 (A=031, B=136) +Fout=1747.20 (A=032, B=136) +Fout=1747.40 (A=033, B=136) +Fout=1747.60 (A=034, B=136) +Fout=1747.80 (A=035, B=136) +Fout=1748.00 (A=036, B=136) +Fout=1748.20 (A=037, B=136) +Fout=1748.40 (A=038, B=136) +Fout=1748.60 (A=039, B=136) +Fout=1748.80 (A=040, B=136) +Fout=1749.00 (A=041, B=136) +Fout=1749.20 (A=042, B=136) +Fout=1749.40 (A=043, B=136) +Fout=1749.60 (A=044, B=136) +Fout=1749.80 (A=045, B=136) +Fout=1750.00 (A=046, B=136) +Fout=1750.20 (A=047, B=136) +Fout=1750.40 (A=048, B=136) +Fout=1750.60 (A=049, B=136) +Fout=1750.80 (A=050, B=136) +Fout=1751.00 (A=051, B=136) +Fout=1751.20 (A=052, B=136) +Fout=1751.40 (A=053, B=136) +Fout=1751.60 (A=054, B=136) +Fout=1751.80 (A=055, B=136) +Fout=1752.00 (A=056, B=136) +Fout=1752.20 (A=057, B=136) +Fout=1752.40 (A=058, B=136) +Fout=1752.60 (A=059, B=136) +Fout=1752.80 (A=060, B=136) +Fout=1753.00 (A=061, B=136) +Fout=1753.20 (A=062, B=136) +Fout=1753.40 (A=063, B=136) +Fout=1753.60 (A=000, B=137) +Fout=1753.80 (A=001, B=137) +Fout=1754.00 (A=002, B=137) +Fout=1754.20 (A=003, B=137) +Fout=1754.40 (A=004, B=137) +Fout=1754.60 (A=005, B=137) +Fout=1754.80 (A=006, B=137) +Fout=1755.00 (A=007, B=137) +Fout=1755.20 (A=008, B=137) +Fout=1755.40 (A=009, B=137) +Fout=1755.60 (A=010, B=137) +Fout=1755.80 (A=011, B=137) +Fout=1756.00 (A=012, B=137) +Fout=1756.20 (A=013, B=137) +Fout=1756.40 (A=014, B=137) +Fout=1756.60 (A=015, B=137) +Fout=1756.80 (A=016, B=137) +Fout=1757.00 (A=017, B=137) +Fout=1757.20 (A=018, B=137) +Fout=1757.40 (A=019, B=137) +Fout=1757.60 (A=020, B=137) +Fout=1757.80 (A=021, B=137) +Fout=1758.00 (A=022, B=137) +Fout=1758.20 (A=023, B=137) +Fout=1758.40 (A=024, B=137) +Fout=1758.60 (A=025, B=137) +Fout=1758.80 (A=026, B=137) +Fout=1759.00 (A=027, B=137) +Fout=1759.20 (A=028, B=137) +Fout=1759.40 (A=029, B=137) +Fout=1759.60 (A=030, B=137) +Fout=1759.80 (A=031, B=137) +Fout=1760.00 (A=032, B=137) +Fout=1760.20 (A=033, B=137) +Fout=1760.40 (A=034, B=137) +Fout=1760.60 (A=035, B=137) +Fout=1760.80 (A=036, B=137) +Fout=1761.00 (A=037, B=137) +Fout=1761.20 (A=038, B=137) +Fout=1761.40 (A=039, B=137) +Fout=1761.60 (A=040, B=137) +Fout=1761.80 (A=041, B=137) +Fout=1762.00 (A=042, B=137) +Fout=1762.20 (A=043, B=137) +Fout=1762.40 (A=044, B=137) +Fout=1762.60 (A=045, B=137) +Fout=1762.80 (A=046, B=137) +Fout=1763.00 (A=047, B=137) +Fout=1763.20 (A=048, B=137) +Fout=1763.40 (A=049, B=137) +Fout=1763.60 (A=050, B=137) +Fout=1763.80 (A=051, B=137) +Fout=1764.00 (A=052, B=137) +Fout=1764.20 (A=053, B=137) +Fout=1764.40 (A=054, B=137) +Fout=1764.60 (A=055, B=137) +Fout=1764.80 (A=056, B=137) +Fout=1765.00 (A=057, B=137) +Fout=1765.20 (A=058, B=137) +Fout=1765.40 (A=059, B=137) +Fout=1765.60 (A=060, B=137) +Fout=1765.80 (A=061, B=137) +Fout=1766.00 (A=062, B=137) +Fout=1766.20 (A=063, B=137) +Fout=1766.40 (A=000, B=138) +Fout=1766.60 (A=001, B=138) +Fout=1766.80 (A=002, B=138) +Fout=1767.00 (A=003, B=138) +Fout=1767.20 (A=004, B=138) +Fout=1767.40 (A=005, B=138) +Fout=1767.60 (A=006, B=138) +Fout=1767.80 (A=007, B=138) +Fout=1768.00 (A=008, B=138) +Fout=1768.20 (A=009, B=138) +Fout=1768.40 (A=010, B=138) +Fout=1768.60 (A=011, B=138) +Fout=1768.80 (A=012, B=138) +Fout=1769.00 (A=013, B=138) +Fout=1769.20 (A=014, B=138) +Fout=1769.40 (A=015, B=138) +Fout=1769.60 (A=016, B=138) +Fout=1769.80 (A=017, B=138) +Fout=1770.00 (A=018, B=138) +Fout=1770.20 (A=019, B=138) +Fout=1770.40 (A=020, B=138) +Fout=1770.60 (A=021, B=138) +Fout=1770.80 (A=022, B=138) +Fout=1771.00 (A=023, B=138) +Fout=1771.20 (A=024, B=138) +Fout=1771.40 (A=025, B=138) +Fout=1771.60 (A=026, B=138) +Fout=1771.80 (A=027, B=138) +Fout=1772.00 (A=028, B=138) +Fout=1772.20 (A=029, B=138) +Fout=1772.40 (A=030, B=138) +Fout=1772.60 (A=031, B=138) +Fout=1772.80 (A=032, B=138) +Fout=1773.00 (A=033, B=138) +Fout=1773.20 (A=034, B=138) +Fout=1773.40 (A=035, B=138) +Fout=1773.60 (A=036, B=138) +Fout=1773.80 (A=037, B=138) +Fout=1774.00 (A=038, B=138) +Fout=1774.20 (A=039, B=138) +Fout=1774.40 (A=040, B=138) +Fout=1774.60 (A=041, B=138) +Fout=1774.80 (A=042, B=138) +Fout=1775.00 (A=043, B=138) +Fout=1775.20 (A=044, B=138) +Fout=1775.40 (A=045, B=138) +Fout=1775.60 (A=046, B=138) +Fout=1775.80 (A=047, B=138) +Fout=1776.00 (A=048, B=138) +Fout=1776.20 (A=049, B=138) +Fout=1776.40 (A=050, B=138) +Fout=1776.60 (A=051, B=138) +Fout=1776.80 (A=052, B=138) +Fout=1777.00 (A=053, B=138) +Fout=1777.20 (A=054, B=138) +Fout=1777.40 (A=055, B=138) +Fout=1777.60 (A=056, B=138) +Fout=1777.80 (A=057, B=138) +Fout=1778.00 (A=058, B=138) +Fout=1778.20 (A=059, B=138) +Fout=1778.40 (A=060, B=138) +Fout=1778.60 (A=061, B=138) +Fout=1778.80 (A=062, B=138) +Fout=1779.00 (A=063, B=138) +Fout=1779.20 (A=000, B=139) +Fout=1779.40 (A=001, B=139) +Fout=1779.60 (A=002, B=139) +Fout=1779.80 (A=003, B=139) +Fout=1780.00 (A=004, B=139) +Fout=1780.20 (A=005, B=139) +Fout=1780.40 (A=006, B=139) +Fout=1780.60 (A=007, B=139) +Fout=1780.80 (A=008, B=139) +Fout=1781.00 (A=009, B=139) +Fout=1781.20 (A=010, B=139) +Fout=1781.40 (A=011, B=139) +Fout=1781.60 (A=012, B=139) +Fout=1781.80 (A=013, B=139) +Fout=1782.00 (A=014, B=139) +Fout=1782.20 (A=015, B=139) +Fout=1782.40 (A=016, B=139) +Fout=1782.60 (A=017, B=139) +Fout=1782.80 (A=018, B=139) +Fout=1783.00 (A=019, B=139) +Fout=1783.20 (A=020, B=139) +Fout=1783.40 (A=021, B=139) +Fout=1783.60 (A=022, B=139) +Fout=1783.80 (A=023, B=139) +Fout=1784.00 (A=024, B=139) +Fout=1784.20 (A=025, B=139) +Fout=1784.40 (A=026, B=139) +Fout=1784.60 (A=027, B=139) +Fout=1784.80 (A=028, B=139) +Fout=1785.00 (A=029, B=139) +Fout=1785.20 (A=030, B=139) +Fout=1785.40 (A=031, B=139) +Fout=1785.60 (A=032, B=139) +Fout=1785.80 (A=033, B=139) +Fout=1786.00 (A=034, B=139) +Fout=1786.20 (A=035, B=139) +Fout=1786.40 (A=036, B=139) +Fout=1786.60 (A=037, B=139) +Fout=1786.80 (A=038, B=139) +Fout=1787.00 (A=039, B=139) +Fout=1787.20 (A=040, B=139) +Fout=1787.40 (A=041, B=139) +Fout=1787.60 (A=042, B=139) +Fout=1787.80 (A=043, B=139) +Fout=1788.00 (A=044, B=139) +Fout=1788.20 (A=045, B=139) +Fout=1788.40 (A=046, B=139) +Fout=1788.60 (A=047, B=139) +Fout=1788.80 (A=048, B=139) +Fout=1789.00 (A=049, B=139) +Fout=1789.20 (A=050, B=139) +Fout=1789.40 (A=051, B=139) +Fout=1789.60 (A=052, B=139) +Fout=1789.80 (A=053, B=139) +Fout=1790.00 (A=054, B=139) +Fout=1790.20 (A=055, B=139) +Fout=1790.40 (A=056, B=139) +Fout=1790.60 (A=057, B=139) +Fout=1790.80 (A=058, B=139) +Fout=1791.00 (A=059, B=139) +Fout=1791.20 (A=060, B=139) +Fout=1791.40 (A=061, B=139) +Fout=1791.60 (A=062, B=139) +Fout=1791.80 (A=063, B=139) +Fout=1792.00 (A=000, B=140) +Fout=1792.20 (A=001, B=140) +Fout=1792.40 (A=002, B=140) +Fout=1792.60 (A=003, B=140) +Fout=1792.80 (A=004, B=140) +Fout=1793.00 (A=005, B=140) +Fout=1793.20 (A=006, B=140) +Fout=1793.40 (A=007, B=140) +Fout=1793.60 (A=008, B=140) +Fout=1793.80 (A=009, B=140) +Fout=1794.00 (A=010, B=140) +Fout=1794.20 (A=011, B=140) +Fout=1794.40 (A=012, B=140) +Fout=1794.60 (A=013, B=140) +Fout=1794.80 (A=014, B=140) +Fout=1795.00 (A=015, B=140) +Fout=1795.20 (A=016, B=140) +Fout=1795.40 (A=017, B=140) +Fout=1795.60 (A=018, B=140) +Fout=1795.80 (A=019, B=140) +Fout=1796.00 (A=020, B=140) +Fout=1796.20 (A=021, B=140) +Fout=1796.40 (A=022, B=140) +Fout=1796.60 (A=023, B=140) +Fout=1796.80 (A=024, B=140) +Fout=1797.00 (A=025, B=140) +Fout=1797.20 (A=026, B=140) +Fout=1797.40 (A=027, B=140) +Fout=1797.60 (A=028, B=140) +Fout=1797.80 (A=029, B=140) +Fout=1798.00 (A=030, B=140) +Fout=1798.20 (A=031, B=140) +Fout=1798.40 (A=032, B=140) +Fout=1798.60 (A=033, B=140) +Fout=1798.80 (A=034, B=140) +Fout=1799.00 (A=035, B=140) +Fout=1799.20 (A=036, B=140) +Fout=1799.40 (A=037, B=140) +Fout=1799.60 (A=038, B=140) +Fout=1799.80 (A=039, B=140) +Fout=1800.00 (A=040, B=140) +Fout=1800.20 (A=041, B=140) +Fout=1800.40 (A=042, B=140) +Fout=1800.60 (A=043, B=140) +Fout=1800.80 (A=044, B=140) +Fout=1801.00 (A=045, B=140) +Fout=1801.20 (A=046, B=140) +Fout=1801.40 (A=047, B=140) +Fout=1801.60 (A=048, B=140) +Fout=1801.80 (A=049, B=140) +Fout=1802.00 (A=050, B=140) +Fout=1802.20 (A=051, B=140) +Fout=1802.40 (A=052, B=140) +Fout=1802.60 (A=053, B=140) +Fout=1802.80 (A=054, B=140) +Fout=1803.00 (A=055, B=140) +Fout=1803.20 (A=056, B=140) +Fout=1803.40 (A=057, B=140) +Fout=1803.60 (A=058, B=140) +Fout=1803.80 (A=059, B=140) +Fout=1804.00 (A=060, B=140) +Fout=1804.20 (A=061, B=140) +Fout=1804.40 (A=062, B=140) +Fout=1804.60 (A=063, B=140) +Fout=1804.80 (A=000, B=141) +Fout=1805.00 (A=001, B=141) +Fout=1805.20 (A=002, B=141) +Fout=1805.40 (A=003, B=141) +Fout=1805.60 (A=004, B=141) +Fout=1805.80 (A=005, B=141) +Fout=1806.00 (A=006, B=141) +Fout=1806.20 (A=007, B=141) +Fout=1806.40 (A=008, B=141) +Fout=1806.60 (A=009, B=141) +Fout=1806.80 (A=010, B=141) +Fout=1807.00 (A=011, B=141) +Fout=1807.20 (A=012, B=141) +Fout=1807.40 (A=013, B=141) +Fout=1807.60 (A=014, B=141) +Fout=1807.80 (A=015, B=141) +Fout=1808.00 (A=016, B=141) +Fout=1808.20 (A=017, B=141) +Fout=1808.40 (A=018, B=141) +Fout=1808.60 (A=019, B=141) +Fout=1808.80 (A=020, B=141) +Fout=1809.00 (A=021, B=141) +Fout=1809.20 (A=022, B=141) +Fout=1809.40 (A=023, B=141) +Fout=1809.60 (A=024, B=141) +Fout=1809.80 (A=025, B=141) +Fout=1810.00 (A=026, B=141) +Fout=1810.20 (A=027, B=141) +Fout=1810.40 (A=028, B=141) +Fout=1810.60 (A=029, B=141) +Fout=1810.80 (A=030, B=141) +Fout=1811.00 (A=031, B=141) +Fout=1811.20 (A=032, B=141) +Fout=1811.40 (A=033, B=141) +Fout=1811.60 (A=034, B=141) +Fout=1811.80 (A=035, B=141) +Fout=1812.00 (A=036, B=141) +Fout=1812.20 (A=037, B=141) +Fout=1812.40 (A=038, B=141) +Fout=1812.60 (A=039, B=141) +Fout=1812.80 (A=040, B=141) +Fout=1813.00 (A=041, B=141) +Fout=1813.20 (A=042, B=141) +Fout=1813.40 (A=043, B=141) +Fout=1813.60 (A=044, B=141) +Fout=1813.80 (A=045, B=141) +Fout=1814.00 (A=046, B=141) +Fout=1814.20 (A=047, B=141) +Fout=1814.40 (A=048, B=141) +Fout=1814.60 (A=049, B=141) +Fout=1814.80 (A=050, B=141) +Fout=1815.00 (A=051, B=141) +Fout=1815.20 (A=052, B=141) +Fout=1815.40 (A=053, B=141) +Fout=1815.60 (A=054, B=141) +Fout=1815.80 (A=055, B=141) +Fout=1816.00 (A=056, B=141) +Fout=1816.20 (A=057, B=141) +Fout=1816.40 (A=058, B=141) +Fout=1816.60 (A=059, B=141) +Fout=1816.80 (A=060, B=141) +Fout=1817.00 (A=061, B=141) +Fout=1817.20 (A=062, B=141) +Fout=1817.40 (A=063, B=141) +Fout=1817.60 (A=000, B=142) +Fout=1817.80 (A=001, B=142) +Fout=1818.00 (A=002, B=142) +Fout=1818.20 (A=003, B=142) +Fout=1818.40 (A=004, B=142) +Fout=1818.60 (A=005, B=142) +Fout=1818.80 (A=006, B=142) +Fout=1819.00 (A=007, B=142) +Fout=1819.20 (A=008, B=142) +Fout=1819.40 (A=009, B=142) +Fout=1819.60 (A=010, B=142) +Fout=1819.80 (A=011, B=142) +Fout=1820.00 (A=012, B=142) +Fout=1820.20 (A=013, B=142) +Fout=1820.40 (A=014, B=142) +Fout=1820.60 (A=015, B=142) +Fout=1820.80 (A=016, B=142) +Fout=1821.00 (A=017, B=142) +Fout=1821.20 (A=018, B=142) +Fout=1821.40 (A=019, B=142) +Fout=1821.60 (A=020, B=142) +Fout=1821.80 (A=021, B=142) +Fout=1822.00 (A=022, B=142) +Fout=1822.20 (A=023, B=142) +Fout=1822.40 (A=024, B=142) +Fout=1822.60 (A=025, B=142) +Fout=1822.80 (A=026, B=142) +Fout=1823.00 (A=027, B=142) +Fout=1823.20 (A=028, B=142) +Fout=1823.40 (A=029, B=142) +Fout=1823.60 (A=030, B=142) +Fout=1823.80 (A=031, B=142) +Fout=1824.00 (A=032, B=142) +Fout=1824.20 (A=033, B=142) +Fout=1824.40 (A=034, B=142) +Fout=1824.60 (A=035, B=142) +Fout=1824.80 (A=036, B=142) +Fout=1825.00 (A=037, B=142) +Fout=1825.20 (A=038, B=142) +Fout=1825.40 (A=039, B=142) +Fout=1825.60 (A=040, B=142) +Fout=1825.80 (A=041, B=142) +Fout=1826.00 (A=042, B=142) +Fout=1826.20 (A=043, B=142) +Fout=1826.40 (A=044, B=142) +Fout=1826.60 (A=045, B=142) +Fout=1826.80 (A=046, B=142) +Fout=1827.00 (A=047, B=142) +Fout=1827.20 (A=048, B=142) +Fout=1827.40 (A=049, B=142) +Fout=1827.60 (A=050, B=142) +Fout=1827.80 (A=051, B=142) +Fout=1828.00 (A=052, B=142) +Fout=1828.20 (A=053, B=142) +Fout=1828.40 (A=054, B=142) +Fout=1828.60 (A=055, B=142) +Fout=1828.80 (A=056, B=142) +Fout=1829.00 (A=057, B=142) +Fout=1829.20 (A=058, B=142) +Fout=1829.40 (A=059, B=142) +Fout=1829.60 (A=060, B=142) +Fout=1829.80 (A=061, B=142) +Fout=1830.00 (A=062, B=142) +Fout=1830.20 (A=063, B=142) +Fout=1830.40 (A=000, B=143) +Fout=1830.60 (A=001, B=143) +Fout=1830.80 (A=002, B=143) +Fout=1831.00 (A=003, B=143) +Fout=1831.20 (A=004, B=143) +Fout=1831.40 (A=005, B=143) +Fout=1831.60 (A=006, B=143) +Fout=1831.80 (A=007, B=143) +Fout=1832.00 (A=008, B=143) +Fout=1832.20 (A=009, B=143) +Fout=1832.40 (A=010, B=143) +Fout=1832.60 (A=011, B=143) +Fout=1832.80 (A=012, B=143) +Fout=1833.00 (A=013, B=143) +Fout=1833.20 (A=014, B=143) +Fout=1833.40 (A=015, B=143) +Fout=1833.60 (A=016, B=143) +Fout=1833.80 (A=017, B=143) +Fout=1834.00 (A=018, B=143) +Fout=1834.20 (A=019, B=143) +Fout=1834.40 (A=020, B=143) +Fout=1834.60 (A=021, B=143) +Fout=1834.80 (A=022, B=143) +Fout=1835.00 (A=023, B=143) +Fout=1835.20 (A=024, B=143) +Fout=1835.40 (A=025, B=143) +Fout=1835.60 (A=026, B=143) +Fout=1835.80 (A=027, B=143) +Fout=1836.00 (A=028, B=143) +Fout=1836.20 (A=029, B=143) +Fout=1836.40 (A=030, B=143) +Fout=1836.60 (A=031, B=143) +Fout=1836.80 (A=032, B=143) +Fout=1837.00 (A=033, B=143) +Fout=1837.20 (A=034, B=143) +Fout=1837.40 (A=035, B=143) +Fout=1837.60 (A=036, B=143) +Fout=1837.80 (A=037, B=143) +Fout=1838.00 (A=038, B=143) +Fout=1838.20 (A=039, B=143) +Fout=1838.40 (A=040, B=143) +Fout=1838.60 (A=041, B=143) +Fout=1838.80 (A=042, B=143) +Fout=1839.00 (A=043, B=143) +Fout=1839.20 (A=044, B=143) +Fout=1839.40 (A=045, B=143) +Fout=1839.60 (A=046, B=143) +Fout=1839.80 (A=047, B=143) +Fout=1840.00 (A=048, B=143) +Fout=1840.20 (A=049, B=143) +Fout=1840.40 (A=050, B=143) +Fout=1840.60 (A=051, B=143) +Fout=1840.80 (A=052, B=143) +Fout=1841.00 (A=053, B=143) +Fout=1841.20 (A=054, B=143) +Fout=1841.40 (A=055, B=143) +Fout=1841.60 (A=056, B=143) +Fout=1841.80 (A=057, B=143) +Fout=1842.00 (A=058, B=143) +Fout=1842.20 (A=059, B=143) +Fout=1842.40 (A=060, B=143) +Fout=1842.60 (A=061, B=143) +Fout=1842.80 (A=062, B=143) +Fout=1843.00 (A=063, B=143) +Fout=1843.20 (A=000, B=144) +Fout=1843.40 (A=001, B=144) +Fout=1843.60 (A=002, B=144) +Fout=1843.80 (A=003, B=144) +Fout=1844.00 (A=004, B=144) +Fout=1844.20 (A=005, B=144) +Fout=1844.40 (A=006, B=144) +Fout=1844.60 (A=007, B=144) +Fout=1844.80 (A=008, B=144) +Fout=1845.00 (A=009, B=144) +Fout=1845.20 (A=010, B=144) +Fout=1845.40 (A=011, B=144) +Fout=1845.60 (A=012, B=144) +Fout=1845.80 (A=013, B=144) +Fout=1846.00 (A=014, B=144) +Fout=1846.20 (A=015, B=144) +Fout=1846.40 (A=016, B=144) +Fout=1846.60 (A=017, B=144) +Fout=1846.80 (A=018, B=144) +Fout=1847.00 (A=019, B=144) +Fout=1847.20 (A=020, B=144) +Fout=1847.40 (A=021, B=144) +Fout=1847.60 (A=022, B=144) +Fout=1847.80 (A=023, B=144) +Fout=1848.00 (A=024, B=144) +Fout=1848.20 (A=025, B=144) +Fout=1848.40 (A=026, B=144) +Fout=1848.60 (A=027, B=144) +Fout=1848.80 (A=028, B=144) +Fout=1849.00 (A=029, B=144) +Fout=1849.20 (A=030, B=144) +Fout=1849.40 (A=031, B=144) +Fout=1849.60 (A=032, B=144) +Fout=1849.80 (A=033, B=144) +Fout=1850.00 (A=034, B=144) +Fout=1850.20 (A=035, B=144) +Fout=1850.40 (A=036, B=144) +Fout=1850.60 (A=037, B=144) +Fout=1850.80 (A=038, B=144) +Fout=1851.00 (A=039, B=144) +Fout=1851.20 (A=040, B=144) +Fout=1851.40 (A=041, B=144) +Fout=1851.60 (A=042, B=144) +Fout=1851.80 (A=043, B=144) +Fout=1852.00 (A=044, B=144) +Fout=1852.20 (A=045, B=144) +Fout=1852.40 (A=046, B=144) +Fout=1852.60 (A=047, B=144) +Fout=1852.80 (A=048, B=144) +Fout=1853.00 (A=049, B=144) +Fout=1853.20 (A=050, B=144) +Fout=1853.40 (A=051, B=144) +Fout=1853.60 (A=052, B=144) +Fout=1853.80 (A=053, B=144) +Fout=1854.00 (A=054, B=144) +Fout=1854.20 (A=055, B=144) +Fout=1854.40 (A=056, B=144) +Fout=1854.60 (A=057, B=144) +Fout=1854.80 (A=058, B=144) +Fout=1855.00 (A=059, B=144) +Fout=1855.20 (A=060, B=144) +Fout=1855.40 (A=061, B=144) +Fout=1855.60 (A=062, B=144) +Fout=1855.80 (A=063, B=144) +Fout=1856.00 (A=000, B=145) +Fout=1856.20 (A=001, B=145) +Fout=1856.40 (A=002, B=145) +Fout=1856.60 (A=003, B=145) +Fout=1856.80 (A=004, B=145) +Fout=1857.00 (A=005, B=145) +Fout=1857.20 (A=006, B=145) +Fout=1857.40 (A=007, B=145) +Fout=1857.60 (A=008, B=145) +Fout=1857.80 (A=009, B=145) +Fout=1858.00 (A=010, B=145) +Fout=1858.20 (A=011, B=145) +Fout=1858.40 (A=012, B=145) +Fout=1858.60 (A=013, B=145) +Fout=1858.80 (A=014, B=145) +Fout=1859.00 (A=015, B=145) +Fout=1859.20 (A=016, B=145) +Fout=1859.40 (A=017, B=145) +Fout=1859.60 (A=018, B=145) +Fout=1859.80 (A=019, B=145) +Fout=1860.00 (A=020, B=145) +Fout=1860.20 (A=021, B=145) +Fout=1860.40 (A=022, B=145) +Fout=1860.60 (A=023, B=145) +Fout=1860.80 (A=024, B=145) +Fout=1861.00 (A=025, B=145) +Fout=1861.20 (A=026, B=145) +Fout=1861.40 (A=027, B=145) +Fout=1861.60 (A=028, B=145) +Fout=1861.80 (A=029, B=145) +Fout=1862.00 (A=030, B=145) +Fout=1862.20 (A=031, B=145) +Fout=1862.40 (A=032, B=145) +Fout=1862.60 (A=033, B=145) +Fout=1862.80 (A=034, B=145) +Fout=1863.00 (A=035, B=145) +Fout=1863.20 (A=036, B=145) +Fout=1863.40 (A=037, B=145) +Fout=1863.60 (A=038, B=145) +Fout=1863.80 (A=039, B=145) +Fout=1864.00 (A=040, B=145) +Fout=1864.20 (A=041, B=145) +Fout=1864.40 (A=042, B=145) +Fout=1864.60 (A=043, B=145) +Fout=1864.80 (A=044, B=145) +Fout=1865.00 (A=045, B=145) +Fout=1865.20 (A=046, B=145) +Fout=1865.40 (A=047, B=145) +Fout=1865.60 (A=048, B=145) +Fout=1865.80 (A=049, B=145) +Fout=1866.00 (A=050, B=145) +Fout=1866.20 (A=051, B=145) +Fout=1866.40 (A=052, B=145) +Fout=1866.60 (A=053, B=145) +Fout=1866.80 (A=054, B=145) +Fout=1867.00 (A=055, B=145) +Fout=1867.20 (A=056, B=145) +Fout=1867.40 (A=057, B=145) +Fout=1867.60 (A=058, B=145) +Fout=1867.80 (A=059, B=145) +Fout=1868.00 (A=060, B=145) +Fout=1868.20 (A=061, B=145) +Fout=1868.40 (A=062, B=145) +Fout=1868.60 (A=063, B=145) +Fout=1868.80 (A=000, B=146) +Fout=1869.00 (A=001, B=146) +Fout=1869.20 (A=002, B=146) +Fout=1869.40 (A=003, B=146) +Fout=1869.60 (A=004, B=146) +Fout=1869.80 (A=005, B=146) +Fout=1870.00 (A=006, B=146) +Fout=1870.20 (A=007, B=146) +Fout=1870.40 (A=008, B=146) +Fout=1870.60 (A=009, B=146) +Fout=1870.80 (A=010, B=146) +Fout=1871.00 (A=011, B=146) +Fout=1871.20 (A=012, B=146) +Fout=1871.40 (A=013, B=146) +Fout=1871.60 (A=014, B=146) +Fout=1871.80 (A=015, B=146) +Fout=1872.00 (A=016, B=146) +Fout=1872.20 (A=017, B=146) +Fout=1872.40 (A=018, B=146) +Fout=1872.60 (A=019, B=146) +Fout=1872.80 (A=020, B=146) +Fout=1873.00 (A=021, B=146) +Fout=1873.20 (A=022, B=146) +Fout=1873.40 (A=023, B=146) +Fout=1873.60 (A=024, B=146) +Fout=1873.80 (A=025, B=146) +Fout=1874.00 (A=026, B=146) +Fout=1874.20 (A=027, B=146) +Fout=1874.40 (A=028, B=146) +Fout=1874.60 (A=029, B=146) +Fout=1874.80 (A=030, B=146) +Fout=1875.00 (A=031, B=146) +Fout=1875.20 (A=032, B=146) +Fout=1875.40 (A=033, B=146) +Fout=1875.60 (A=034, B=146) +Fout=1875.80 (A=035, B=146) +Fout=1876.00 (A=036, B=146) +Fout=1876.20 (A=037, B=146) +Fout=1876.40 (A=038, B=146) +Fout=1876.60 (A=039, B=146) +Fout=1876.80 (A=040, B=146) +Fout=1877.00 (A=041, B=146) +Fout=1877.20 (A=042, B=146) +Fout=1877.40 (A=043, B=146) +Fout=1877.60 (A=044, B=146) +Fout=1877.80 (A=045, B=146) +Fout=1878.00 (A=046, B=146) +Fout=1878.20 (A=047, B=146) +Fout=1878.40 (A=048, B=146) +Fout=1878.60 (A=049, B=146) +Fout=1878.80 (A=050, B=146) +Fout=1879.00 (A=051, B=146) +Fout=1879.20 (A=052, B=146) +Fout=1879.40 (A=053, B=146) +Fout=1879.60 (A=054, B=146) +Fout=1879.80 (A=055, B=146) +Fout=1880.00 (A=056, B=146) +Fout=1880.20 (A=057, B=146) +Fout=1880.40 (A=058, B=146) +Fout=1880.60 (A=059, B=146) +Fout=1880.80 (A=060, B=146) +Fout=1881.00 (A=061, B=146) +Fout=1881.20 (A=062, B=146) +Fout=1881.40 (A=063, B=146) +Fout=1881.60 (A=000, B=147) +Fout=1881.80 (A=001, B=147) +Fout=1882.00 (A=002, B=147) +Fout=1882.20 (A=003, B=147) +Fout=1882.40 (A=004, B=147) +Fout=1882.60 (A=005, B=147) +Fout=1882.80 (A=006, B=147) +Fout=1883.00 (A=007, B=147) +Fout=1883.20 (A=008, B=147) +Fout=1883.40 (A=009, B=147) +Fout=1883.60 (A=010, B=147) +Fout=1883.80 (A=011, B=147) +Fout=1884.00 (A=012, B=147) +Fout=1884.20 (A=013, B=147) +Fout=1884.40 (A=014, B=147) +Fout=1884.60 (A=015, B=147) +Fout=1884.80 (A=016, B=147) +Fout=1885.00 (A=017, B=147) +Fout=1885.20 (A=018, B=147) +Fout=1885.40 (A=019, B=147) +Fout=1885.60 (A=020, B=147) +Fout=1885.80 (A=021, B=147) +Fout=1886.00 (A=022, B=147) +Fout=1886.20 (A=023, B=147) +Fout=1886.40 (A=024, B=147) +Fout=1886.60 (A=025, B=147) +Fout=1886.80 (A=026, B=147) +Fout=1887.00 (A=027, B=147) +Fout=1887.20 (A=028, B=147) +Fout=1887.40 (A=029, B=147) +Fout=1887.60 (A=030, B=147) +Fout=1887.80 (A=031, B=147) +Fout=1888.00 (A=032, B=147) +Fout=1888.20 (A=033, B=147) +Fout=1888.40 (A=034, B=147) +Fout=1888.60 (A=035, B=147) +Fout=1888.80 (A=036, B=147) +Fout=1889.00 (A=037, B=147) +Fout=1889.20 (A=038, B=147) +Fout=1889.40 (A=039, B=147) +Fout=1889.60 (A=040, B=147) +Fout=1889.80 (A=041, B=147) +Fout=1890.00 (A=042, B=147) +Fout=1890.20 (A=043, B=147) +Fout=1890.40 (A=044, B=147) +Fout=1890.60 (A=045, B=147) +Fout=1890.80 (A=046, B=147) +Fout=1891.00 (A=047, B=147) +Fout=1891.20 (A=048, B=147) +Fout=1891.40 (A=049, B=147) +Fout=1891.60 (A=050, B=147) +Fout=1891.80 (A=051, B=147) +Fout=1892.00 (A=052, B=147) +Fout=1892.20 (A=053, B=147) +Fout=1892.40 (A=054, B=147) +Fout=1892.60 (A=055, B=147) +Fout=1892.80 (A=056, B=147) +Fout=1893.00 (A=057, B=147) +Fout=1893.20 (A=058, B=147) +Fout=1893.40 (A=059, B=147) +Fout=1893.60 (A=060, B=147) +Fout=1893.80 (A=061, B=147) +Fout=1894.00 (A=062, B=147) +Fout=1894.20 (A=063, B=147) +Fout=1894.40 (A=000, B=148) +Fout=1894.60 (A=001, B=148) +Fout=1894.80 (A=002, B=148) +Fout=1895.00 (A=003, B=148) +Fout=1895.20 (A=004, B=148) +Fout=1895.40 (A=005, B=148) +Fout=1895.60 (A=006, B=148) +Fout=1895.80 (A=007, B=148) +Fout=1896.00 (A=008, B=148) +Fout=1896.20 (A=009, B=148) +Fout=1896.40 (A=010, B=148) +Fout=1896.60 (A=011, B=148) +Fout=1896.80 (A=012, B=148) +Fout=1897.00 (A=013, B=148) +Fout=1897.20 (A=014, B=148) +Fout=1897.40 (A=015, B=148) +Fout=1897.60 (A=016, B=148) +Fout=1897.80 (A=017, B=148) +Fout=1898.00 (A=018, B=148) +Fout=1898.20 (A=019, B=148) +Fout=1898.40 (A=020, B=148) +Fout=1898.60 (A=021, B=148) +Fout=1898.80 (A=022, B=148) +Fout=1899.00 (A=023, B=148) +Fout=1899.20 (A=024, B=148) +Fout=1899.40 (A=025, B=148) +Fout=1899.60 (A=026, B=148) +Fout=1899.80 (A=027, B=148) +Fout=1900.00 (A=028, B=148) +Fout=1900.20 (A=029, B=148) +Fout=1900.40 (A=030, B=148) +Fout=1900.60 (A=031, B=148) +Fout=1900.80 (A=032, B=148) +Fout=1901.00 (A=033, B=148) +Fout=1901.20 (A=034, B=148) +Fout=1901.40 (A=035, B=148) +Fout=1901.60 (A=036, B=148) +Fout=1901.80 (A=037, B=148) +Fout=1902.00 (A=038, B=148) +Fout=1902.20 (A=039, B=148) +Fout=1902.40 (A=040, B=148) +Fout=1902.60 (A=041, B=148) +Fout=1902.80 (A=042, B=148) +Fout=1903.00 (A=043, B=148) +Fout=1903.20 (A=044, B=148) +Fout=1903.40 (A=045, B=148) +Fout=1903.60 (A=046, B=148) +Fout=1903.80 (A=047, B=148) +Fout=1904.00 (A=048, B=148) +Fout=1904.20 (A=049, B=148) +Fout=1904.40 (A=050, B=148) +Fout=1904.60 (A=051, B=148) +Fout=1904.80 (A=052, B=148) +Fout=1905.00 (A=053, B=148) +Fout=1905.20 (A=054, B=148) +Fout=1905.40 (A=055, B=148) +Fout=1905.60 (A=056, B=148) +Fout=1905.80 (A=057, B=148) +Fout=1906.00 (A=058, B=148) +Fout=1906.20 (A=059, B=148) +Fout=1906.40 (A=060, B=148) +Fout=1906.60 (A=061, B=148) +Fout=1906.80 (A=062, B=148) +Fout=1907.00 (A=063, B=148) +Fout=1907.20 (A=000, B=149) +Fout=1907.40 (A=001, B=149) +Fout=1907.60 (A=002, B=149) +Fout=1907.80 (A=003, B=149) +Fout=1908.00 (A=004, B=149) +Fout=1908.20 (A=005, B=149) +Fout=1908.40 (A=006, B=149) +Fout=1908.60 (A=007, B=149) +Fout=1908.80 (A=008, B=149) +Fout=1909.00 (A=009, B=149) +Fout=1909.20 (A=010, B=149) +Fout=1909.40 (A=011, B=149) +Fout=1909.60 (A=012, B=149) +Fout=1909.80 (A=013, B=149) +Fout=1910.00 (A=014, B=149) +Fout=1910.20 (A=015, B=149) +Fout=1910.40 (A=016, B=149) +Fout=1910.60 (A=017, B=149) +Fout=1910.80 (A=018, B=149) +Fout=1911.00 (A=019, B=149) +Fout=1911.20 (A=020, B=149) +Fout=1911.40 (A=021, B=149) +Fout=1911.60 (A=022, B=149) +Fout=1911.80 (A=023, B=149) +Fout=1912.00 (A=024, B=149) +Fout=1912.20 (A=025, B=149) +Fout=1912.40 (A=026, B=149) +Fout=1912.60 (A=027, B=149) +Fout=1912.80 (A=028, B=149) +Fout=1913.00 (A=029, B=149) +Fout=1913.20 (A=030, B=149) +Fout=1913.40 (A=031, B=149) +Fout=1913.60 (A=032, B=149) +Fout=1913.80 (A=033, B=149) +Fout=1914.00 (A=034, B=149) +Fout=1914.20 (A=035, B=149) +Fout=1914.40 (A=036, B=149) +Fout=1914.60 (A=037, B=149) +Fout=1914.80 (A=038, B=149) +Fout=1915.00 (A=039, B=149) +Fout=1915.20 (A=040, B=149) +Fout=1915.40 (A=041, B=149) +Fout=1915.60 (A=042, B=149) +Fout=1915.80 (A=043, B=149) +Fout=1916.00 (A=044, B=149) +Fout=1916.20 (A=045, B=149) +Fout=1916.40 (A=046, B=149) +Fout=1916.60 (A=047, B=149) +Fout=1916.80 (A=048, B=149) +Fout=1917.00 (A=049, B=149) +Fout=1917.20 (A=050, B=149) +Fout=1917.40 (A=051, B=149) +Fout=1917.60 (A=052, B=149) +Fout=1917.80 (A=053, B=149) +Fout=1918.00 (A=054, B=149) +Fout=1918.20 (A=055, B=149) +Fout=1918.40 (A=056, B=149) +Fout=1918.60 (A=057, B=149) +Fout=1918.80 (A=058, B=149) +Fout=1919.00 (A=059, B=149) +Fout=1919.20 (A=060, B=149) +Fout=1919.40 (A=061, B=149) +Fout=1919.60 (A=062, B=149) +Fout=1919.80 (A=063, B=149) diff --git a/src/host/rita_pll/rita_pll_notes.txt b/src/host/rita_pll/rita_pll_notes.txt new file mode 100644 index 00000000..8557d3ae --- /dev/null +++ b/src/host/rita_pll/rita_pll_notes.txt @@ -0,0 +1,8 @@ + +Regular Operation as per DS GSM SPEC + +GSM900 Tx: 870.4 ... 921.4 MHz 880.0 ... 914.8 +GSM900 Rx: 864.4 ... 966.2 MHz 925.0 ... 959.8 + +GSM1800 Tx: 1702.4 ... 1919.8 MHz 1710.2 ... 1784.8 +GSM1800 Rx: 1804.8 ... 1996.4 MHz 1805.2 ... 1879.8 |