huawei: clean up and simplify band handling
This commit is contained in:
@@ -40,7 +40,7 @@ G_DEFINE_TYPE_EXTENDED (MMModemHuaweiGsm, mm_modem_huawei_gsm, MM_TYPE_GENERIC_G
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Cached state */
|
/* Cached state */
|
||||||
MMModemGsmBand band;
|
guint32 band;
|
||||||
} MMModemHuaweiGsmPrivate;
|
} MMModemHuaweiGsmPrivate;
|
||||||
|
|
||||||
MMModem *
|
MMModem *
|
||||||
@@ -59,6 +59,61 @@ mm_modem_huawei_gsm_new (const char *device,
|
|||||||
NULL));
|
NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MMModemGsmBand mm;
|
||||||
|
guint32 huawei;
|
||||||
|
} BandTable;
|
||||||
|
|
||||||
|
static BandTable bands[] = {
|
||||||
|
/* Sort 3G first since it's preferred */
|
||||||
|
{ MM_MODEM_GSM_BAND_U2100, 0x00400000 },
|
||||||
|
{ MM_MODEM_GSM_BAND_U1900, 0x00800000 },
|
||||||
|
{ MM_MODEM_GSM_BAND_U850, 0x04000000 },
|
||||||
|
{ MM_MODEM_GSM_BAND_U900, 0x00020000 },
|
||||||
|
{ MM_MODEM_GSM_BAND_G850, 0x00080000 },
|
||||||
|
/* 2G second */
|
||||||
|
{ MM_MODEM_GSM_BAND_DCS, 0x00000080 },
|
||||||
|
{ MM_MODEM_GSM_BAND_EGSM, 0x00000300 }, /* 0x100 = Extended GSM, 0x200 = Primary GSM */
|
||||||
|
{ MM_MODEM_GSM_BAND_PCS, 0x00200000 },
|
||||||
|
/* And ANY last since it's most inclusive */
|
||||||
|
{ MM_MODEM_GSM_BAND_ANY, 0x3FFFFFFF },
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
band_mm_to_huawei (MMModemGsmBand band, guint32 *out_huawei)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (bands) / sizeof (BandTable); i++) {
|
||||||
|
if (bands[i].mm == band) {
|
||||||
|
*out_huawei = bands[i].huawei;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
band_huawei_to_mm (guint32 huawei, MMModemGsmBand *out_mm)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (bands) / sizeof (BandTable); i++) {
|
||||||
|
/* The dongle returns a bitfield, but since we don't support that
|
||||||
|
* yet in MM, take the "best" band and return it.
|
||||||
|
*/
|
||||||
|
if (bands[i].huawei & huawei) {
|
||||||
|
*out_mm = bands[i].mm;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
parse_syscfg (MMModemHuaweiGsm *self,
|
parse_syscfg (MMModemHuaweiGsm *self,
|
||||||
const char *reply,
|
const char *reply,
|
||||||
@@ -90,12 +145,7 @@ parse_syscfg (MMModemHuaweiGsm *self,
|
|||||||
*out_mode = new_mode;
|
*out_mode = new_mode;
|
||||||
|
|
||||||
/* Band */
|
/* Band */
|
||||||
if (*band == 0x3FFFFFFF)
|
priv->band = *band;
|
||||||
priv->band = MM_MODEM_GSM_BAND_ANY;
|
|
||||||
else if (*band == 0x400380)
|
|
||||||
priv->band = MM_MODEM_GSM_BAND_DCS;
|
|
||||||
else if (*band == 0x200000)
|
|
||||||
priv->band = MM_MODEM_GSM_BAND_PCS;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -236,62 +286,14 @@ set_band_done (MMAtSerialPort *port,
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
info->error = g_error_copy (error);
|
info->error = g_error_copy (error);
|
||||||
else
|
else {
|
||||||
/* Success, cache the value */
|
/* Success, cache the value */
|
||||||
priv->band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
|
priv->band = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"));
|
||||||
|
}
|
||||||
|
|
||||||
mm_callback_info_schedule (info);
|
mm_callback_info_schedule (info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_band_get_done (MMAtSerialPort *port,
|
|
||||||
GString *response,
|
|
||||||
GError *error,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
|
||||||
MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (info->modem);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
info->error = g_error_copy (error);
|
|
||||||
mm_callback_info_schedule (info);
|
|
||||||
} else {
|
|
||||||
int a, b, u1, u2;
|
|
||||||
guint32 band;
|
|
||||||
|
|
||||||
if (parse_syscfg (self, response->str, &a, &b, &band, &u1, &u2, NULL)) {
|
|
||||||
char *command;
|
|
||||||
|
|
||||||
switch (GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"))) {
|
|
||||||
case MM_MODEM_GSM_BAND_ANY:
|
|
||||||
band = 0x3FFFFFFF;
|
|
||||||
break;
|
|
||||||
case MM_MODEM_GSM_BAND_EGSM:
|
|
||||||
band = 0x100;
|
|
||||||
break;
|
|
||||||
case MM_MODEM_GSM_BAND_DCS:
|
|
||||||
band = 0x80;
|
|
||||||
break;
|
|
||||||
case MM_MODEM_GSM_BAND_U2100:
|
|
||||||
band = 0x400000;
|
|
||||||
break;
|
|
||||||
case MM_MODEM_GSM_BAND_PCS:
|
|
||||||
band = 0x200000;
|
|
||||||
break;
|
|
||||||
case MM_MODEM_GSM_BAND_G850:
|
|
||||||
band = 0x80000;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2);
|
|
||||||
mm_at_serial_port_queue_command (port, command, 3, set_band_done, info);
|
|
||||||
g_free (command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_band (MMModemGsmNetwork *modem,
|
set_band (MMModemGsmNetwork *modem,
|
||||||
MMModemGsmBand band,
|
MMModemGsmBand band,
|
||||||
@@ -299,27 +301,35 @@ set_band (MMModemGsmNetwork *modem,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MMCallbackInfo *info;
|
MMCallbackInfo *info;
|
||||||
MMAtSerialPort *primary;
|
MMAtSerialPort *port, *primary, *secondary;
|
||||||
|
char *command;
|
||||||
|
guint32 huawei_band = 0x3FFFFFFF;
|
||||||
|
|
||||||
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
|
info = mm_callback_info_new (MM_MODEM (modem), callback, user_data);
|
||||||
|
|
||||||
switch (band) {
|
port = primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
|
||||||
case MM_MODEM_GSM_BAND_ANY:
|
if (mm_port_get_connected (MM_PORT (primary))) {
|
||||||
case MM_MODEM_GSM_BAND_EGSM:
|
secondary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_SECONDARY);
|
||||||
case MM_MODEM_GSM_BAND_DCS:
|
if (!secondary) {
|
||||||
case MM_MODEM_GSM_BAND_U2100:
|
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_CONNECTED,
|
||||||
case MM_MODEM_GSM_BAND_PCS:
|
"Cannot set band while connected");
|
||||||
mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (band), NULL);
|
mm_callback_info_schedule (info);
|
||||||
primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY);
|
return;
|
||||||
g_assert (primary);
|
}
|
||||||
mm_at_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_band_get_done, info);
|
|
||||||
return;
|
/* Use secondary port if primary is connected */
|
||||||
default:
|
port = secondary;
|
||||||
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band.");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mm_callback_info_schedule (info);
|
if (!band_mm_to_huawei (band, &huawei_band)) {
|
||||||
|
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band.");
|
||||||
|
mm_callback_info_schedule (info);
|
||||||
|
} else {
|
||||||
|
mm_callback_info_set_data (info, "band", GUINT_TO_POINTER (huawei_band), NULL);
|
||||||
|
command = g_strdup_printf ("AT^SYSCFG=16,3,%X,2,4", huawei_band);
|
||||||
|
mm_at_serial_port_queue_command (port, command, 3, set_band_done, info);
|
||||||
|
g_free (command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -330,14 +340,17 @@ get_band_done (MMAtSerialPort *port,
|
|||||||
{
|
{
|
||||||
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
|
||||||
MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (info->modem);
|
MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (info->modem);
|
||||||
MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self);
|
|
||||||
int mode_a, mode_b, u1, u2;
|
int mode_a, mode_b, u1, u2;
|
||||||
guint32 band;
|
guint32 band;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
info->error = g_error_copy (error);
|
info->error = g_error_copy (error);
|
||||||
else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2, NULL))
|
else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2, NULL)) {
|
||||||
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->band), NULL);
|
MMModemGsmBand mm_band = MM_MODEM_GSM_BAND_ANY;
|
||||||
|
|
||||||
|
band_huawei_to_mm (band, &mm_band);
|
||||||
|
mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
mm_callback_info_schedule (info);
|
mm_callback_info_schedule (info);
|
||||||
}
|
}
|
||||||
@@ -350,12 +363,15 @@ get_band (MMModemGsmNetwork *modem,
|
|||||||
MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (modem);
|
MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (modem);
|
||||||
MMAtSerialPort *primary;
|
MMAtSerialPort *primary;
|
||||||
|
|
||||||
if (priv->band != MM_MODEM_GSM_BAND_ANY) {
|
if (priv->band != 0) {
|
||||||
/* have cached mode (from an unsolicited message). Use that */
|
/* have cached band (from an unsolicited message). Use that */
|
||||||
MMCallbackInfo *info;
|
MMCallbackInfo *info;
|
||||||
|
MMModemGsmBand mm_band = MM_MODEM_GSM_BAND_ANY;
|
||||||
|
|
||||||
|
band_huawei_to_mm (priv->band, &mm_band);
|
||||||
|
|
||||||
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
|
info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
|
||||||
mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->band), NULL);
|
mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL);
|
||||||
mm_callback_info_schedule (info);
|
mm_callback_info_schedule (info);
|
||||||
} else {
|
} else {
|
||||||
/* Get it from modem */
|
/* Get it from modem */
|
||||||
|
Reference in New Issue
Block a user