@@ -39,6 +39,7 @@
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
#include <osmocom/gsm/protocol/ipaccess.h>
+#include <osmocom/gsm/abis_nm.h>
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/logging.h>
@@ -53,11 +54,14 @@
#define SYSMOBTS_RF_LOCK_PATH "/var/lock/bts_rf_lock"
+#define TEMP_TIMER_SECS ((6 * 3600) + 1)
+
#include "utils.h"
#include "eeprom.h"
#include "l1_if.h"
#include "hw_misc.h"
#include "btsconfig.h"
+#include <misc/sysmobts_misc.h>
/* FIXME: read from real hardware */
const uint8_t abis_mac[6] = { 0,1,2,3,4,5 };
@@ -295,6 +299,74 @@ static int write_pid_file(char *procname)
return 0;
}
+static int reduce_max_power;
+static int status_change_power_red;
+static int last_power_transmitter = -1;
+enum {
+ SBTS2050_DISABLE_CHANGE_POWER = 0,
+ SBTS2050_ENABLE_CHANGE_POWER,
+};
+
+#define oml_tlv_parse(dec, buf, len) \
+ tlv_parse(dec, &abis_nm_att_tlvdef, buf, len, 0, 0)
+
+/* size of the struct plus 1 Bytes of tag and 2 Bytes for the length */
+#define TLV_ADD_INFO_LEN (sizeof(struct sbts2050_config_info) + 3)
+
+static void update_transmiter_power(struct gsm_bts_trx *trx, int reduce_power)
+{
+ struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
+ int power_transmitter = trx->nominal_power - trx->max_power_red;
+
+ power_transmitter -= reduce_power;
+ if (power_transmitter < 0)
+ power_transmitter = 0;
+
+ if (last_power_transmitter != power_transmitter) {
+ if (fl1h->hLayer1) {
+ l1if_set_txpower(fl1h, power_transmitter);
+ last_power_transmitter = power_transmitter;
+ }
+ }
+}
+
+static struct osmo_timer_list power_timer;
+static void change_transmitter_power_cb(void *data)
+{
+ struct gsm_bts *bts = data;
+ struct gsm_bts_trx *trx = bts->c0;
+
+ if (status_change_power_red == SBTS2050_ENABLE_CHANGE_POWER) {
+ update_transmiter_power(trx, reduce_max_power);
+ status_change_power_red = SBTS2050_DISABLE_CHANGE_POWER;
+ osmo_timer_schedule(&power_timer, TEMP_TIMER_SECS, 0);
+ } else if (status_change_power_red == SBTS2050_DISABLE_CHANGE_POWER)
+ update_transmiter_power(trx, 0);
+}
+
+static int take_max_power_red(struct msgb *msg)
+{
+ struct sbts2050_config_info *config_info;
+ struct tlv_parsed tlv_out;
+ int rc;
+
+ rc = oml_tlv_parse(&tlv_out, msg->tail - TLV_ADD_INFO_LEN,
+ TLV_ADD_INFO_LEN);
+
+ if (rc < 0)
+ return -1;
+
+ config_info =
+ (struct sbts2050_config_info *) TLVP_VAL(&tlv_out, NM_ATT_ADD_INFO);
+
+ reduce_max_power = config_info->reduce_max_power;
+
+ status_change_power_red = SBTS2050_ENABLE_CHANGE_POWER;
+ change_transmitter_power_cb(bts);
+
+ return 0;
+}
+
/*
* In succesfully case, this function set again the pointers of the l2h and l3h
* of the OML message that we have received. In other case, we don't set the
@@ -404,6 +476,11 @@ static int read_sock(struct osmo_fd *fd, unsigned int what)
goto err;
}
+ if (take_max_power_red(msg) < 0) {
+ LOGP(DL1C, LOGL_ERROR, "Add_info Malformed message\n");
+ goto err;
+ }
+
mo = &bts->mo;
msg->trx = mo->bts->c0;
@@ -452,6 +529,9 @@ static int oml_sock_unix_init(struct osmo_fd *accept, struct osmo_fd *read)
read->fd = -1;
accept->data = read;
+ power_timer.cb = change_transmitter_power_cb;
+ power_timer.data = bts;
+
rc = osmo_sock_unix_init_ofd(accept, SOCK_SEQPACKET, 0, SOCKET_PATH,
OSMO_SOCK_F_BIND | OSMO_SOCK_F_NONBLOCK);
return rc;