Phone

/* $Id$ */
/* Copyright (c) 2011-2020 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS Desktop Phone */
/* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <System.h>
#include "Phone.h"
/* Engineering */
/* private */
/* types */
typedef enum _EngineeringLocationPagingParameters
{
ELPP_BS_PA_MFRMS = 0,
ELPP_T3212,
ELPP_MCC,
ELPP_MNC,
ELPP_TMSI
} EngineeringLocationPagingParameter;
typedef enum _EngineeringNeighborCellInformation
{
ENCI_ARFCN = 0,
ENCI_C1,
ENCI_C2,
ENCI_RXLEV,
ENCI_BSIC,
ENCI_CELL_ID,
ENCI_LAC,
ENCI_FRAME_OFFSET,
ENCI_TIME_ALIGNMENT,
ENCI_CBA,
ENCI_CBQ,
ENCI_CELL_TYPE_IND,
ENCI_RAC,
ENCI_CELL_RESEL_OFFSET,
ENCI_TEMP_OFFSET,
ENCI_RXLEV_ACC_MIN
} EngineeringNeighborCellInformation;
typedef enum _EngineeringServingCellInformation
{
ESCI_ARFCN = 0,
ESCI_C1,
ESCI_C2,
ESCI_RXLEV,
ESCI_BSIC,
ESCI_CELL_ID,
ESCI_DSC,
ESCI_TXLEV,
ESCI_TN,
ESCI_RLT,
ESCI_TAV,
ESCI_RXLEV_F,
ESCI_RXLEV_S,
ESCI_RXQUAL_F,
ESCI_RXQUAL_S,
ESCI_LAC,
ESCI_CBA,
ESCI_CBQ,
ESCI_CELL_TYPE_IND,
ESCI_VOCODER
} EngineeringServingCellInformation;
typedef struct _PhonePlugin
{
PhonePluginHelper * helper;
guint source;
EngineeringNeighborCellInformation enci;
size_t enci_cnt;
/* widgets */
GtkWidget * window;
GtkToolItem * tb_play;
GtkToolItem * tb_fullscreen;
GtkListStore * sc_store;
GtkWidget * sc_view;
GtkListStore * nc_store;
GtkWidget * nc_view;
} Engineering;
/* constants */
/* serving cell */
enum {
SC_COL_FREQUENCY, SC_COL_C1, SC_COL_C2, SC_COL_RX_LEVEL,
SC_COL_STATION_ID, SC_COL_CELL_ID, SC_COL_TX_LEVEL,
SC_COL_TIMESLOT_NUMBER, SC_COL_LAC, SC_COL_TMSI
};
#define SC_COL_LAST SC_COL_TMSI
#define SC_COL_COUNT (SC_COL_LAST + 1)
static struct
{
int col;
char const * title;
} _engineering_sc_columns[SC_COL_COUNT + 1] =
{
{ SC_COL_FREQUENCY, "Frequency" },
{ SC_COL_C1, "C1" },
{ SC_COL_C2, "C2" },
{ SC_COL_RX_LEVEL, "RX level" },
{ SC_COL_STATION_ID, "Station ID" },
{ SC_COL_CELL_ID, "Cell ID" },
{ SC_COL_LAC, "Area code" },
{ SC_COL_TX_LEVEL, "TX level" },
{ SC_COL_TIMESLOT_NUMBER, "Timeslot" },
{ SC_COL_TMSI, "TMSI" },
{ 0, NULL }
};
/* neighbor cells */
enum { NC_COL_FREQUENCY, NC_COL_C1, NC_COL_C2, NC_COL_RXLEV, NC_COL_BSIC,
NC_COL_CELL_ID, NC_COL_LAC, NC_COL_FRAME_OFFSET, NC_COL_CBA, NC_COL_CBQ,
NC_COL_CELL_TYPE_IND, NC_COL_RAC };
#define NC_COL_LAST NC_COL_RAC
#define NC_COL_COUNT (NC_COL_LAST + 1)
static struct
{
int col;
char const * title;
} _engineering_nc_columns[NC_COL_COUNT + 1] =
{
{ NC_COL_FREQUENCY, "Frequency" },
{ NC_COL_C1, "C1" },
{ NC_COL_C2, "C2" },
{ NC_COL_RXLEV, "RX level" },
{ NC_COL_BSIC, "Station ID" },
{ NC_COL_CELL_ID, "Cell ID" },
{ NC_COL_LAC, "Area code" },
{ NC_COL_FRAME_OFFSET, "Frame offset" },
{ NC_COL_CBA, "Cell Bar Access" },
{ NC_COL_CBQ, "Cell Bar Qualify" },
{ NC_COL_CELL_TYPE_IND, "Cell type" },
{ NC_COL_RAC, "Routing area code" },
{ 0, NULL }
};
/* prototypes */
static Engineering * _engineering_init(PhonePluginHelper * helper);
static void _engineering_destroy(Engineering * engineering);
static double _engineering_get_frequency(unsigned int arfcn);
/* callbacks */
static gboolean _on_engineering_closex(gpointer data);
static void _on_engineering_play_toggled(gpointer data);
static void _on_engineering_fullscreen_toggled(gpointer data);
static gboolean _on_engineering_timeout(gpointer data);
static int _on_engineering_trigger_em(Engineering * engineering,
char const * result);
/* public */
/* variables */
PhonePluginDefinition plugin =
{
"Engineering",
"network-wireless",
NULL,
_engineering_init,
_engineering_destroy,
NULL,
NULL
};
/* private */
/* functions */
/* engineering_init */
static Engineering * _engineering_init(PhonePluginHelper * helper)
{
Engineering * engineering;
GtkWidget * vbox;
GtkWidget * toolbar;
GtkWidget * paned;
GtkWidget * frame;
GtkWidget * scrolled;
size_t i;
GtkCellRenderer * renderer;
GtkTreeViewColumn * column;
if((engineering = object_new(sizeof(*engineering))) == NULL)
return NULL;
engineering->helper = helper;
engineering->source = 0;
engineering->enci = 0;
engineering->enci_cnt = 0;
/* widgets */
/* window */
engineering->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(engineering->window), 200, 300);
#if GTK_CHECK_VERSION(2, 6, 0)
gtk_window_set_icon_name(GTK_WINDOW(engineering->window),
"stock_compile");
#endif
gtk_window_set_title(GTK_WINDOW(engineering->window),
"Engineering mode");
g_signal_connect_swapped(engineering->window, "delete-event",
G_CALLBACK(_on_engineering_closex), engineering);
#if GTK_CHECK_VERSION(3, 0, 0)
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
#else
vbox = gtk_vbox_new(FALSE, 0);
#endif
/* toolbar */
toolbar = gtk_toolbar_new();
engineering->tb_play = gtk_toggle_tool_button_new_from_stock(
GTK_STOCK_MEDIA_PLAY);
g_signal_connect_swapped(G_OBJECT(engineering->tb_play), "toggled",
G_CALLBACK(_on_engineering_play_toggled), engineering);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), engineering->tb_play, -1);
engineering->tb_fullscreen = gtk_toggle_tool_button_new_from_stock(
GTK_STOCK_FULLSCREEN);
g_signal_connect_swapped(engineering->tb_fullscreen, "toggled",
G_CALLBACK(_on_engineering_fullscreen_toggled),
engineering);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), engineering->tb_fullscreen,
-1);
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, TRUE, 0);
/* serving cell view */
#if GTK_CHECK_VERSION(3, 0, 0)
paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
#else
paned = gtk_vpaned_new();
#endif
frame = gtk_frame_new("Serving cell");
engineering->sc_store = gtk_list_store_new(SC_COL_COUNT,
G_TYPE_STRING, /* SC_COL_FREQUENCY */
G_TYPE_STRING, /* SC_COL_C1 */
G_TYPE_STRING, /* SC_COL_C2 */
G_TYPE_STRING, /* SC_COL_RX_LEVEL */
G_TYPE_STRING, /* SC_COL_STATION_ID */
G_TYPE_STRING, /* SC_COL_CELL_ID */
G_TYPE_STRING, /* SC_COL_TX_LEVEL */
G_TYPE_STRING, /* SC_COL_TIMESLOT_NUMBER */
G_TYPE_STRING, /* SC_COL_LAC */
G_TYPE_STRING); /* SC_COL_TMSI */
scrolled = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
engineering->sc_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(
engineering->sc_store));
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(engineering->sc_view), TRUE);
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(
engineering->sc_view)),
GTK_SELECTION_NONE);
/* columns */
for(i = 0; _engineering_sc_columns[i].title != NULL; i++)
{
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(
_engineering_sc_columns[i].title, renderer,
"text", _engineering_sc_columns[i].col, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(engineering->sc_view),
column);
}
gtk_container_add(GTK_CONTAINER(scrolled), engineering->sc_view);
gtk_container_add(GTK_CONTAINER(frame), scrolled);
gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
gtk_paned_add1(GTK_PANED(paned), frame);
/* neighbor cells view */
frame = gtk_frame_new("Neighbor cells");
engineering->nc_store = gtk_list_store_new(NC_COL_COUNT,
G_TYPE_STRING, /* NC_COL_FREQUENCY */
G_TYPE_STRING, /* NC_COL_C1 */
G_TYPE_STRING, /* NC_COL_C2 */
G_TYPE_STRING, /* NC_COL_RXLEV */
G_TYPE_STRING, /* NC_COL_BSIC */
G_TYPE_STRING, /* NC_COL_CELL_ID */
G_TYPE_STRING, /* NC_COL_LAC */
G_TYPE_STRING, /* NC_COL_FRAME_OFFSET */
G_TYPE_STRING, /* NC_COL_CBA */
G_TYPE_STRING, /* NC_COL_CBQ */
G_TYPE_STRING, /* NC_COL_CELL_TYPE_IND */
G_TYPE_STRING); /* NC_COL_RAC */
scrolled = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
engineering->nc_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(
engineering->nc_store));
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(engineering->nc_view), TRUE);
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(
engineering->nc_view)),
GTK_SELECTION_NONE);
/* columns */
for(i = 0; _engineering_nc_columns[i].title != NULL; i++)
{
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes(
_engineering_nc_columns[i].title, renderer,
"text", _engineering_nc_columns[i].col, NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(engineering->nc_view),
column);
}
gtk_container_add(GTK_CONTAINER(scrolled), engineering->nc_view);
gtk_container_add(GTK_CONTAINER(frame), scrolled);
gtk_container_set_border_width(GTK_CONTAINER(frame), 4);
gtk_container_add(GTK_CONTAINER(engineering->window), vbox);
gtk_paned_add2(GTK_PANED(paned), frame);
gtk_box_pack_start(GTK_BOX(vbox), paned, TRUE, TRUE, 0);
gtk_widget_show_all(engineering->window);
/* trigger */
#if 0 /* FIXME reimplement using an extension to the Hayes modem plug-in */
helper->register_trigger(helper->phone, plugin, "%EM",
_on_engineering_trigger_em);
#endif
return engineering;
}
/* engineering_destroy */
static void _engineering_destroy(Engineering * engineering)
{
if(engineering->source != 0)
g_source_remove(engineering->source);
gtk_widget_destroy(engineering->window);
object_delete(engineering);
}
/* engineering_get_frequency */
static double _engineering_get_frequency(unsigned int arfcn)
{
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(%u)\n", __func__, arfcn);
#endif
if(arfcn == 0)
return 0 / 0.0;
else if(arfcn < 124) /* 900 MHz */
return 935 + (arfcn - 511) * 0.2;
else if(arfcn <= 172)
return 0 / 0.0;
else if(arfcn < 252) /* 850 MHz */
return 869 + (arfcn - 127) * 0.2;
else if(arfcn <= 511)
return 0 / 0.0;
/* XXX the values for the 1800 and 1900 MHz band overlap */
else if(arfcn < 811) /* 1900 MHz */
return 1930 + (arfcn - 511) * 0.2;
else if(arfcn < 886) /* 1800 MHz */
return 1805 + (arfcn - 511) * 0.2;
else if(arfcn <= 974)
return 0 / 0.0;
else if(arfcn < 1023) /* 900 MHz */
return 925 + (arfcn - 974) * 0.2;
else
return 0 / 0.0;
}
/* callbacks */
/* on_engineering_closex */
static gboolean _on_engineering_closex(gpointer data)
{
Engineering * engineering = data;
gtk_widget_hide(engineering->window);
return TRUE;
}
/* on_engineering_fullscreen_toggled */
static void _on_engineering_fullscreen_toggled(gpointer data)
{
Engineering * engineering = data;
if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(
engineering->tb_fullscreen)))
gtk_window_fullscreen(GTK_WINDOW(engineering->window));
else
gtk_window_unfullscreen(GTK_WINDOW(engineering->window));
}
/* on_engineering_play_toggled */
static void _on_engineering_play_toggled(gpointer data)
{
Engineering * engineering = data;
if(gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(
engineering->tb_play)))
engineering->source = _on_engineering_timeout(engineering);
else if(engineering->source != 0)
{
g_source_remove(engineering->source);
engineering->source = 0;
}
}
/* on_engineering_timeout */
static gboolean _on_engineering_timeout(gpointer data)
{
Engineering * engineering = data;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
engineering->source = 0;
#if 0 /* FIXME implement again otherwise */
engineering->helper->queue(engineering->helper->phone, "AT%EM=2,1");
engineering->helper->queue(engineering->helper->phone, "AT%EM=2,2");
engineering->helper->queue(engineering->helper->phone, "AT%EM=2,3");
engineering->helper->queue(engineering->helper->phone, "AT%EM=2,4");
#endif
return FALSE;
}
/* on_engineering_trigger_em */
static int _trigger_em1_do(Engineering * engineering, unsigned int * p,
size_t cnt);
static int _trigger_em2_do(Engineering * engineering, unsigned int * p,
size_t cnt);
static int _trigger_em3_do(Engineering * engineering, char const * buf,
GtkTreeIter * iter);
static int _trigger_em4_do(Engineering * engineering, unsigned int * p,
size_t cnt);
static int _do_arfcn(Engineering * engineering, unsigned int arfcn,
GtkTreeIter * iter);
static int _do_c1(Engineering * engineering, int c1, GtkTreeIter * iter);
static int _do_c2(Engineering * engineering, int c2, GtkTreeIter * iter);
static int _do_rxlev(Engineering * engineering, unsigned int rxlev,
GtkTreeIter * iter);
static int _do_bsic(Engineering * engineering, unsigned int bsic,
GtkTreeIter * iter);
static int _do_cell_id(Engineering * engineering, unsigned int cell_id,
GtkTreeIter * iter);
static int _do_lac(Engineering * engineering, unsigned int lac,
GtkTreeIter * iter);
static int _do_frame_offset(Engineering * engineering,
unsigned int frame_offset, GtkTreeIter * iter);
static int _do_time_alignment(Engineering * engineering,
unsigned int time_alignment);
static int _do_cba(Engineering * engineering, unsigned int cba,
GtkTreeIter * iter);
static int _do_cbq(Engineering * engineering, unsigned int cbq,
GtkTreeIter * iter);
static int _do_cell_type_ind(Engineering * engineering,
unsigned int cell_type_ind, GtkTreeIter * iter);
static int _do_rac(Engineering * engineering, unsigned int rac,
GtkTreeIter * iter);
static int _do_cell_resel_offset(Engineering * engineering,
unsigned int cell_resel_offset);
static int _do_temp_offset(Engineering * engineering, unsigned int temp_offset);
static int _do_rxlev_acc_min(Engineering * engineering,
unsigned int rxlev_acc_min);
static int _on_engineering_trigger_em(Engineering * engineering, char const * result)
{
int res;
unsigned int p[20];
size_t i;
size_t j;
gboolean valid;
GtkTreeIter iter;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result);
#endif
if(engineering->source == 0)
engineering->source = g_timeout_add(5000,
_on_engineering_timeout, engineering);
/* scan as many as we may expect */
res = sscanf(result, "%%EM: %u,%u,%u,%u,%u"",%u,%u,%u,%u,%u"
",%u,%u,%u,%u,%u"",%u,%u,%u,%u,%u",
&p[0], &p[1], &p[2], &p[3], &p[4],
&p[5], &p[6], &p[7], &p[8], &p[9],
&p[10], &p[11], &p[12], &p[13], &p[14],
&p[15], &p[16], &p[17], &p[18], &p[19]);
if(res == 20)
return _trigger_em1_do(engineering, p, 20);
if(res == 11)
return _trigger_em2_do(engineering, p, 11);
if(res == 5)
return _trigger_em4_do(engineering, p, 5);
if(res == 1)
{
engineering->enci = 0;
engineering->enci_cnt = p[0];
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\") => %u\n", __func__, result,
p[0]);
#endif
return 0;
}
if(res != 0)
return 1;
/* XXX assumes it's em3 */
valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(
engineering->nc_store), &iter);
for(i = 0; i < engineering->enci_cnt; i++)
{
if(valid == FALSE)
gtk_list_store_append(engineering->nc_store, &iter);
for(j = 0; result[j] != ',' && result[j] != '\0'; j++);
_trigger_em3_do(engineering, result, &iter);
if(result[j] == '\0')
break; /* XXX report when did not parse as many cells */
result += j + 1;
valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(
engineering->nc_store), &iter);
}
if(valid && gtk_tree_model_iter_next(GTK_TREE_MODEL(
engineering->nc_store), &iter))
while(gtk_list_store_remove(engineering->nc_store, &iter));
engineering->enci++;
return 0;
}
static int _trigger_em1_do(Engineering * engineering, unsigned int * p,
size_t cnt)
{
EngineeringServingCellInformation esci;
GtkTreeIter iter;
size_t i;
char buf[32];
double freq;
if(cnt != 20)
return 1;
if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(engineering->sc_store),
&iter) == FALSE)
gtk_list_store_append(engineering->sc_store, &iter);
for(i = 0; i < cnt; i++)
{
esci = i;
snprintf(buf, sizeof(buf), "%u", p[i]);
switch(esci)
{
case ESCI_ARFCN:
freq = _engineering_get_frequency(p[i]);
snprintf(buf, sizeof(buf), "%.1f", freq);
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_FREQUENCY, buf, -1);
break;
case ESCI_C1:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_C1, buf, -1);
break;
case ESCI_C2:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_C2, buf, -1);
break;
case ESCI_RXLEV:
snprintf(buf, sizeof(buf), "%u", (p[i] / 2)
+ 2);
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_RX_LEVEL, buf, -1);
break;
case ESCI_BSIC:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_STATION_ID, buf, -1);
break;
case ESCI_CELL_ID:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_CELL_ID, buf, -1);
break;
case ESCI_TXLEV:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_TX_LEVEL, buf, -1);
break;
case ESCI_TN:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_TIMESLOT_NUMBER, buf,
-1);
break;
case ESCI_LAC:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_LAC, buf, -1);
break;
case ESCI_DSC:
case ESCI_RLT:
case ESCI_TAV:
case ESCI_RXLEV_F:
case ESCI_RXLEV_S:
case ESCI_RXQUAL_F:
case ESCI_RXQUAL_S:
case ESCI_CBA:
case ESCI_CBQ:
case ESCI_CELL_TYPE_IND:
case ESCI_VOCODER:
/* FIXME implement */
break;
}
}
return 0;
}
static int _trigger_em2_do(Engineering * engineering, unsigned int * p,
size_t cnt)
{
if(cnt != 11)
return 1;
/* FIXME implement */
return 1;
}
static int _trigger_em3_do(Engineering * engineering, char const * buf,
GtkTreeIter * iter)
{
unsigned int u;
if(sscanf(buf, "%u", &u) != 1)
return 1;
switch(engineering->enci)
{
case ENCI_ARFCN:
return _do_arfcn(engineering, u, iter);
case ENCI_C1:
return _do_c1(engineering, u, iter);
case ENCI_C2:
return _do_c2(engineering, u, iter);
case ENCI_RXLEV:
return _do_rxlev(engineering, u, iter);
case ENCI_BSIC:
return _do_bsic(engineering, u, iter);
case ENCI_CELL_ID:
return _do_cell_id(engineering, u, iter);
case ENCI_LAC:
return _do_lac(engineering, u, iter);
case ENCI_FRAME_OFFSET:
return _do_frame_offset(engineering, u, iter);
case ENCI_TIME_ALIGNMENT:
return _do_time_alignment(engineering, u);
case ENCI_CBA:
return _do_cba(engineering, u, iter);
case ENCI_CBQ:
return _do_cbq(engineering, u, iter);
case ENCI_CELL_TYPE_IND:
return _do_cell_type_ind(engineering, u, iter);
case ENCI_RAC:
return _do_rac(engineering, u, iter);
case ENCI_CELL_RESEL_OFFSET:
return _do_cell_resel_offset(engineering, u);
case ENCI_TEMP_OFFSET:
return _do_temp_offset(engineering, u);
case ENCI_RXLEV_ACC_MIN:
return _do_rxlev_acc_min(engineering, u);
}
return 1;
}
static int _trigger_em4_do(Engineering * engineering, unsigned int * p,
size_t cnt)
{
GtkTreeIter iter;
size_t i;
EngineeringLocationPagingParameter elpp;
char buf[32];
if(cnt != 5)
return 1;
if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(engineering->sc_store),
&iter) == FALSE)
gtk_list_store_append(engineering->sc_store, &iter);
for(i = 0; i < cnt; i++)
{
elpp = i;
snprintf(buf, sizeof(buf), "%u", p[i]);
switch(elpp)
{
case ELPP_BS_PA_MFRMS:
case ELPP_T3212:
case ELPP_MCC:
case ELPP_MNC:
/* FIXME implement */
break;
case ELPP_TMSI:
gtk_list_store_set(engineering->sc_store, &iter,
SC_COL_TMSI, buf, -1);
break;
}
}
return 0;
}
static int _do_arfcn(Engineering * engineering, unsigned int arfcn,
GtkTreeIter * iter)
{
double freq;
char buf[32];
freq = _engineering_get_frequency(arfcn);
snprintf(buf, sizeof(buf), "%.1f", freq);
gtk_list_store_set(engineering->nc_store, iter, 0, buf, -1);
return 0;
}
static int _do_c1(Engineering * engineering, int c1, GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%d", c1);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_C1, buf, -1);
return 0;
}
static int _do_c2(Engineering * engineering, int c2, GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%d", c2);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_C2, buf, -1);
return 0;
}
static int _do_rxlev(Engineering * engineering, unsigned int rxlev,
GtkTreeIter * iter)
{
char buf[32];
/* FIXME implement with a progress bar */
snprintf(buf, sizeof(buf), "%u", (rxlev / 2) + 2);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_RXLEV, buf, -1);
return 0;
}
static int _do_bsic(Engineering * engineering, unsigned int bsic,
GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%u", bsic);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_BSIC, buf, -1);
return 0;
}
static int _do_cell_id(Engineering * engineering, unsigned int cell_id,
GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%u", cell_id);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_CELL_ID, buf,
-1);
return 0;
}
static int _do_lac(Engineering * engineering, unsigned int lac,
GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%u", lac);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_LAC, buf, -1);
return 0;
}
static int _do_frame_offset(Engineering * engineering,
unsigned int frame_offset, GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%u", frame_offset);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_FRAME_OFFSET,
buf, -1);
return 0;
}
static int _do_time_alignment(Engineering * engineering,
unsigned int time_alignment)
{
return 0;
}
static int _do_cba(Engineering * engineering, unsigned int cba,
GtkTreeIter * iter)
{
char const * buf = cba ? "Yes" : "No";
gtk_list_store_set(engineering->nc_store, iter, NC_COL_CBA, buf, -1);
return 0;
}
static int _do_cbq(Engineering * engineering, unsigned int cbq,
GtkTreeIter * iter)
{
char const * buf = cbq ? "Yes" : "No";
gtk_list_store_set(engineering->nc_store, iter, NC_COL_CBQ, buf, -1);
return 0;
}
static int _do_cell_type_ind(Engineering * engineering,
unsigned int cell_type_ind, GtkTreeIter * iter)
{
char const * type = "NA";
switch(cell_type_ind)
{
case 1:
type = "GSM";
break;
case 2:
type = "GPRS";
break;
}
gtk_list_store_set(engineering->nc_store, iter, NC_COL_CELL_TYPE_IND,
type, -1);
return 0;
}
static int _do_rac(Engineering * engineering, unsigned int rac,
GtkTreeIter * iter)
{
char buf[32];
snprintf(buf, sizeof(buf), "%u", rac);
gtk_list_store_set(engineering->nc_store, iter, NC_COL_RAC, buf, -1);
return 0;
}
static int _do_cell_resel_offset(Engineering * engineering,
unsigned int cell_resel_offset)
{
return 0;
}
static int _do_temp_offset(Engineering * engineering, unsigned int temp_offset)
{
return 0;
}
static int _do_rxlev_acc_min(Engineering * engineering,
unsigned int rxlev_acc_min)
{
return 0;
}