@@ -51,6 +51,16 @@ AC_CHECK_HEADER([openbsc/gsm_data_shared.h],[],
[])
CPPFLAGS=$oldCPPFLAGS
+# Check for the sbts2050_header.h that was added after the 3.6 release
+AC_CHECK_HEADER([sysmocom/femtobts/sbts2050_header.h],
+ [sysmo_uc_header="yes"],[])
+
+if test "$sysmo_uc_header" = "yes" ; then
+ AC_DEFINE(BUILD_SBTS2050, 1, [Define if we want to build SBTS2050])
+fi
+AM_CONDITIONAL(BUILD_SBTS2050, test "x$sysmo_uc_header" = "xyes")
+AM_CONFIG_HEADER(btsconfig.h)
+
AC_OUTPUT(
src/Makefile
src/common/Makefile
@@ -35,6 +35,7 @@
#include <osmocom/core/application.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/serial.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
@@ -53,6 +54,58 @@ void *tall_mgr_ctx;
/* every 1 hours means 365*24 = 8760 EEprom writes per year (max) */
#define HOURS_TIMER_SECS (1 * 3600)
+#ifdef BUILD_SBTS2050
+static struct osmo_timer_list temp_uc_timer;
+static void check_uctemp_timer_cb(void *data)
+{
+ int temp_pa = 0, temp_board = 0;
+ struct uc *ucontrol0 = data;
+
+ sbts2050_uc_check_temp(ucontrol0, &temp_pa, &temp_board);
+
+ osmo_timer_schedule(&temp_uc_timer, TEMP_TIMER_SECS, 0);
+}
+#endif
+
+static void initialize_sbts2050(void)
+{
+#ifdef BUILD_SBTS2050
+ static struct uc ucontrol0 = {
+ .id = 0,
+ .path = "/dev/ttyS0"
+ };
+ int val;
+
+ if (sysmobts_par_get_int(SYSMOBTS_PAR_MODEL_NR, &val) < 0) {
+ LOGP(DFIND, LOGL_ERROR,
+ "Failed to get Model number\n");
+ return;
+ }
+
+ if (val == 2050) {
+ if (sysmobts_par_get_int(SYSMOBTS_PAR_TRX_NR, &val) < 0) {
+ LOGP(DFIND, LOGL_ERROR,
+ "Failed to get the TRX number\n");
+ return;
+ }
+
+ if (val != 0)
+ return;
+ }
+
+ ucontrol0.fd = osmo_serial_init(ucontrol0.path, 115200);
+ if (ucontrol0.fd < 0) {
+ LOGP(DFIND, LOGL_ERROR,
+ "Failed to open the serial interface\n");
+ return;
+ }
+
+ temp_uc_timer.cb = check_uctemp_timer_cb;
+ temp_uc_timer.data = &ucontrol0;
+ check_uctemp_timer_cb(&ucontrol0);
+#endif
+}
+
static struct osmo_timer_list temp_timer;
static void check_temp_timer_cb(void *unused)
{
@@ -309,6 +362,9 @@ int main(int argc, char **argv)
hours_timer.cb = hours_timer_cb;
hours_timer_cb(NULL);
+ /* start uc temperature check timer */
+ initialize_sbts2050();
+
/* handle broadcast messages for ipaccess-find */
fd.cb = ipaccess_bcast;
rc = osmo_sock_init_ofd(&fd, AF_INET, SOCK_DGRAM, IPPROTO_UDP,
@@ -32,14 +32,186 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
#include <osmocom/core/application.h>
#include <osmocom/vty/telnet_interface.h>
#include <osmocom/vty/logging.h>
+#include "btsconfig.h"
#include "sysmobts_misc.h"
#include "sysmobts_par.h"
#include "sysmobts_mgr.h"
+#ifdef BUILD_SBTS2050
+#include <sysmocom/femtobts/sbts2050_header.h>
+#endif
+
+#define SERIAL_ALLOC_SIZE 300
+#define SIZE_HEADER_RSP 5
+#define SIZE_HEADER_CMD 4
+
+
+#ifdef BUILD_SBTS2050
+/**********************************************************************
+ * Functions read/write from serial interface
+ *********************************************************************/
+static int hand_serial_read(int fd, struct msgb *msg, int numbytes)
+{
+ int rc, bread = 0;
+
+ if (numbytes > msgb_tailroom(msg))
+ return -ENOSPC;
+
+ while (bread < numbytes) {
+ rc = read(fd, msg->tail, numbytes - bread);
+ if (rc < 0)
+ return -1;
+ if (rc == 0)
+ break;
+
+ bread += rc;
+ msgb_put(msg, rc);
+ }
+
+ return bread;
+}
+
+static int hand_serial_write(int fd, struct msgb *msg)
+{
+ int rc, bwritten = 0;
+
+ while (msg->len > 0) {
+ rc = write(fd, msg->data, msg->len);
+ if (rc <= 0)
+ return -1;
+
+ msgb_pull(msg, rc);
+ bwritten += rc;
+ }
+
+ return bwritten;
+}
+
+/**********************************************************************
+ * Functions request information to Microcontroller
+ *********************************************************************/
+static void add_parity(cmdpkt_t *command)
+{
+ int n;
+ uint8_t parity = 0x00;
+ for (n = 0; n < SIZE_HEADER_CMD+command->u8Len; n++)
+ parity ^= ((uint8_t *)command)[n];
+
+ command->cmd.raw[command->u8Len] = parity;
+}
+
+static struct msgb *sbts2050_ucinfo_get(struct uc *ucontrol, struct ucinfo info)
+{
+ int num, rc;
+ cmdpkt_t *command;
+ rsppkt_t *response;
+ struct msgb *msg;
+ fd_set fdread;
+ struct timeval tout = {
+ .tv_sec = 10,
+ };
+
+ switch (info.id) {
+ case SBTS2050_TEMP_RQT:
+ num = sizeof(command->cmd.tempGet);
+ break;
+ default:
+ return NULL;
+ }
+ num = num + SIZE_HEADER_CMD+1;
+
+ msg = msgb_alloc(SERIAL_ALLOC_SIZE, "Message Microcontroller");
+ if (msg == NULL) {
+ LOGP(DTEMP, LOGL_ERROR, "Error creating msg\n");
+ return NULL;
+ }
+ command = (cmdpkt_t *) msgb_put(msg, num);
+
+ command->u16Magic = 0xCAFE;
+ switch (info.id) {
+ case SBTS2050_TEMP_RQT:
+ command->u8Id = info.id;
+ command->u8Len = sizeof(command->cmd.tempGet);
+ break;
+ default:
+ goto err;
+ }
+
+ add_parity(command);
+
+ if (hand_serial_write(ucontrol->fd, msg) < 0)
+ goto err;
+
+ msgb_reset(msg);
+
+ FD_ZERO(&fdread);
+ FD_SET(ucontrol->fd, &fdread);
+
+ num = SIZE_HEADER_RSP;
+ while (1) {
+ rc = select(ucontrol->fd+1, &fdread, NULL, NULL, &tout);
+ if (rc > 0) {
+ if (hand_serial_read(ucontrol->fd, msg, num) < 0)
+ goto err;
+
+ response = (rsppkt_t *)msg->data;
+
+ if (response->u8Id != info.id || msg->len <= 0 ||
+ response->i8Error != RQT_SUCCESS)
+ goto err;
+
+ if (msg->len == SIZE_HEADER_RSP + response->u8Len + 1)
+ break;
+
+ num = response->u8Len + 1;
+ } else
+ goto err;
+ }
+
+ return msg;
+
+err:
+ msgb_free(msg);
+ return NULL;
+}
+#endif
+
+/**********************************************************************
+ * Uc temperature handling
+ *********************************************************************/
+void sbts2050_uc_check_temp(struct uc *ucontrol, int *temp_pa, int *temp_board)
+{
+#ifdef BUILD_SBTS2050
+ rsppkt_t *response;
+ struct msgb *msg;
+ struct ucinfo info = {
+ .id = SBTS2050_TEMP_RQT,
+ };
+
+ msg = sbts2050_ucinfo_get(ucontrol, info);
+
+ if (msg == NULL) {
+ LOGP(DTEMP, LOGL_ERROR, "Error reading temperature\n");
+ return;
+ }
+
+ response = (rsppkt_t *)msg->data;
+
+ *temp_board = response->rsp.tempGet.i8BrdTemp;
+ *temp_pa = response->rsp.tempGet.i8PaTemp;
+
+ LOGP(DTEMP, LOGL_DEBUG, "Temperature Board: %+3d C\n"
+ "Tempeture PA: %+3d C\n",
+ response->rsp.tempGet.i8BrdTemp,
+ response->rsp.tempGet.i8PaTemp);
+ msgb_free(msg);
+#endif
+}
/*********************************************************************
* Temperature handling
@@ -13,11 +13,26 @@ enum sysmobts_temp_type {
_NUM_TEMP_TYPES
};
+struct uc {
+ int id;
+ int fd;
+ const char *path;
+};
+
+struct ucinfo {
+ uint16_t id;
+ int master;
+ int slave;
+ int pa;
+};
+
int sysmobts_temp_get(enum sysmobts_temp_sensor sensor,
enum sysmobts_temp_type type);
void sysmobts_check_temp(int no_eeprom_write);
+void sbts2050_uc_check_temp(struct uc *ucontrol, int *temp_pa, int *temp_board);
+
int sysmobts_update_hours(int no_epprom_write);
enum sysmobts_firmware_type {