osmocom-analog/src/amps/sysinfo.c

197 lines
5.6 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include "../libsample/sample.h"
#include "amps.h"
#include "frame.h"
#include "main.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 dtx, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis)
{
int i;
memset(si, 0, sizeof(*si));
/* how oftern to repeat the overhead train */
if (!tacs)
si->overhead_repeat = 17;
else
si->overhead_repeat = 14;
/* all words */
si->dcc = dcc;
/* VC assignment */
si->vmac = vmac;
/* filler */
si->filler.cmac = cmac;
si->filler.sdcc1 = 0;
si->filler.sdcc2 = 0;
si->filler.wfom = (bis) ? 0 : 1; /* must be set to ignore B/I bit */
/* Word 1 */
si->word1.sid1 = sid1;
si->word1.ep = 0; /* 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 = dtx; /* DTX seems not to work with my White Dynatac 8000 */
si->word2.n_1 = 20;
si->word2.rcf = (bis) ? 0 : 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;
/* Access 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 = bis; /* must be clear to ignore B/I bit */
si->acc_type.pci_home = 0; /* if set, bscap must also be set */
si->acc_type.pci_roam = 0; /* if set, bscap must also 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 > (int)(sizeof(si->type) / sizeof(si->type[0]))) {
fprintf(stderr, "si type array overflow, please fix!\n");
abort();
}
}
uint64_t get_sysinfo(amps_si *si, int debug)
{
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;
if (!tacs)
return amps_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc, debug);
else
return tacs_encode_word1_system(si->dcc, si->word1.sid1, si->word1.ep, si->word1.auth, si->word1.pci, nawc, debug);
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, debug);
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, debug);
case SYSINFO_REG_INCR:
return amps_encode_registration_increment(si->dcc, si->reg_incr.regincr, end, debug);
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, debug);
case SYSINFO_NEW_ACC:
return amps_encode_new_access_channel_set(si->dcc, si->new_acc.newacc, end, debug);
case SYSINFO_OVERLOAD:
return amps_encode_overload_control(si->dcc, si->overload.olc, end, debug);
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, debug);
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, debug);
}
fprintf(stderr, "get_sysinfo unknown type, please fix!\n");
abort();
}