diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2016-05-01 19:51:56 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2016-06-17 17:03:29 +0200 |
commit | d2c4ca4fa91d9496f5b7a5f2dc1c6b66bb52ced8 (patch) | |
tree | dd9c2d4cbe270a3fdcbacb08f566578d3386211f /src/amps/sysinfo.c | |
parent | 7d5d3da8d35ee5e34eb9b3b4fbd821b9f4b28fb5 (diff) |
Implementation of Advanced Mobile Phone Service (AMPS)
Diffstat (limited to 'src/amps/sysinfo.c')
-rw-r--r-- | src/amps/sysinfo.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/amps/sysinfo.c b/src/amps/sysinfo.c new file mode 100644 index 0000000..204de08 --- /dev/null +++ b/src/amps/sysinfo.c @@ -0,0 +1,185 @@ +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include "../common/timer.h" +#include "amps.h" +#include "frame.h" + +static struct sysinfo_reg_incr default_reg_incr = { + 450, +}; + +static struct sysinfo_loc_area default_loc_area = { + 0, + 0, + 0, + 0, +}; + +static struct sysinfo_new_acc default_new_acc = { + 0, +}; + +static struct sysinfo_overload default_overload = { + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, +}; + +static struct sysinfo_acc_type default_acc_type = { + 1, + 0, + 0, + 0, + 0, +}; + +static struct sysinfo_acc_attempt default_acc_attempt = { + 10, + 10, + 10, + 10, +}; + +void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr) +{ + int i; + + memset(si, 0, sizeof(*si)); + + /* all words */ + si->dcc = dcc; + /* VC assginment */ + si->vmac = vmac; + + /* filler */ + si->filler.cmac = cmac; + si->filler.sdcc1 = 0; + si->filler.sdcc2 = 0; + si->filler.wfom = 1; /* must be set to ignore B/I bit */ + + /* Word 1 */ + si->word1.sid1 = sid1; + si->word1.ep = 1; /* shall be 0 */ + si->word1.auth = 0; + si->word1.pci = 0; + + /* Word 2 */ + si->word2.s = 1; + si->word2.e = 1; + si->word2.regh = regh; + si->word2.regr = regr; + si->word2.dtx = 0; + si->word2.n_1 = 20; + si->word2.rcf = 1; /* must be set to ignore B/I bit */ + si->word2.cpa = 1; /* must be set for combined CC+PC */ + si->word2.cmax_1 = 20; + + /* registration increment */ + si->reg_incr.regincr = regincr; + + /* location area */ + si->loc_area.pureg = pureg; + si->loc_area.pdreg = pdreg; + if (locaid >= 0) { + si->loc_area.lreg = 1; + si->loc_area.locaid = locaid; + } + + /* new access channel set */ + si->new_acc.newacc = 0; + + /* overload control */ + for (i = 0; i < 16; i++) + si->overload.olc[i] = 1; + + /* Acces Tyoe */ + /* 'bis' must be 0, so the phone does not wait for busy bit. + * We cannot respond with B/I fast enough due to processing delay. + * So we don't set the B/I bit to busy on reception of message. + * The access type message (including this 'bis') must also be included. + */ + si->acc_type.bis = 0; /* must be clear to ignore B/I bit */ + si->acc_type.pci_home = 0; /* if set, bscap must allso be set */ + si->acc_type.pci_roam = 0; /* if set, bscap must allso be set */ + si->acc_type.bspc = 0; + si->acc_type.bscap = 0; + + /* access attempt parameters */ + si->acc_attempt.maxbusy_pgr = 10; + si->acc_attempt.maxsztr_pgr = 10; + si->acc_attempt.maxbusy_other = 10; + si->acc_attempt.maxsztr_other = 10; + + /* registration ID */ + si->reg_id.regid = 1000; +} + +void prepare_sysinfo(amps_si *si) +{ + int i = 0; + + si->type[i++] = SYSINFO_WORD1; + si->type[i++] = SYSINFO_WORD2; + si->type[i++] = SYSINFO_REG_ID; + /* include only messages that differ from default */ + if (!!memcmp(&si->reg_incr, &default_reg_incr, sizeof(si->reg_incr))) + si->type[i++] = SYSINFO_REG_INCR; + if (!!memcmp(&si->loc_area, &default_loc_area, sizeof(si->loc_area))) + si->type[i++] = SYSINFO_LOC_AREA; + if (!!memcmp(&si->new_acc, &default_new_acc, sizeof(si->new_acc))) + si->type[i++] = SYSINFO_NEW_ACC; + if (!!memcmp(&si->overload, &default_overload, sizeof(si->overload))) + si->type[i++] = SYSINFO_OVERLOAD; + if (!!memcmp(&si->acc_type, &default_acc_type, sizeof(si->acc_type))) + si->type[i++] = SYSINFO_ACC_TYPE; + if (!!memcmp(&si->acc_attempt, &default_acc_attempt, sizeof(si->acc_attempt))) + si->type[i++] = SYSINFO_ACC_ATTEMPT; + si->num = i; /* train is running */ + si->count = 0; /* first message in train */ + if (i > sizeof(si->type) / sizeof(si->type[0])) { + fprintf(stderr, "si type array overflow, pleas fix!\n"); + abort(); + } +} + +uint64_t get_sysinfo(amps_si *si) +{ + int count, nawc, end = 0; + time_t ti = time(NULL); + + count = si->count; + + if (++si->count == si->num) { + end = 1; + si->num = 0; /* train is over */ + } + + switch (si->type[count]) { + case SYSINFO_WORD1: + nawc = si->num - 1; + return amps_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc); + case SYSINFO_WORD2: + return amps_encode_word2_system(si->dcc, si->word2.s, si->word2.e, si->word2.regh, si->word2.regr, si->word2.dtx, si->word2.n_1, si->word2.rcf, si->word2.cpa, si->word2.cmax_1, end); + case SYSINFO_REG_ID: + /* use time stamp to generate regid */ + si->reg_id.regid = ti & 0xfffff; + return amps_encode_registration_id(si->dcc, si->reg_id.regid, end); + case SYSINFO_REG_INCR: + return amps_encode_registration_increment(si->dcc, si->reg_incr.regincr, end); + case SYSINFO_LOC_AREA: + return amps_encode_location_area(si->dcc, si->loc_area.pureg, si->loc_area.pdreg, si->loc_area.lreg, si->loc_area.locaid, end); + case SYSINFO_NEW_ACC: + return amps_encode_new_access_channel_set(si->dcc, si->new_acc.newacc, end); + case SYSINFO_OVERLOAD: + return amps_encode_overload_control(si->dcc, si->overload.olc, end); + case SYSINFO_ACC_TYPE: + return amps_encode_access_type(si->dcc, si->acc_type.bis, si->acc_type.pci_home, si->acc_type.pci_roam, si->acc_type.bspc, si->acc_type.bscap, end); + case SYSINFO_ACC_ATTEMPT: + return amps_encode_access_attempt(si->dcc, si->acc_attempt.maxbusy_pgr, si->acc_attempt.maxsztr_pgr, si->acc_attempt.maxbusy_other, si->acc_attempt.maxsztr_other, end); + } + + fprintf(stderr, "get_sysinfo unknown type, please fix!\n"); + abort(); +} + |