823
910
/****************************************************************/
926
static const Band modem_bands[] = {
927
/* Sort 3G first since it's preferred */
928
{ MM_MODEM_GSM_BAND_U2100, "FDD_BAND_I", FALSE, NULL },
929
{ MM_MODEM_GSM_BAND_U1900, "FDD_BAND_II", FALSE, NULL },
930
{ MM_MODEM_GSM_BAND_U1800, "FDD_BAND_III", FALSE, NULL },
931
{ MM_MODEM_GSM_BAND_U17IV, "FDD_BAND_IV", FALSE, NULL },
932
{ MM_MODEM_GSM_BAND_U800, "FDD_BAND_VI", FALSE, NULL },
933
{ MM_MODEM_GSM_BAND_U850, "FDD_BAND_V", FALSE, NULL },
934
{ MM_MODEM_GSM_BAND_U900, "FDD_BAND_VIII", FALSE, NULL },
936
{ MM_MODEM_GSM_BAND_G850, "G850", FALSE, NULL },
937
{ MM_MODEM_GSM_BAND_DCS, "DCS", FALSE, NULL },
938
{ MM_MODEM_GSM_BAND_EGSM, "EGSM", FALSE, NULL },
939
{ MM_MODEM_GSM_BAND_PCS, "PCS", FALSE, NULL },
940
/* And ANY last since it's most inclusive */
941
{ MM_MODEM_GSM_BAND_ANY, "ANY", FALSE, NULL },
944
static MMModemGsmBand
945
icera_band_to_mm (const char *icera)
949
for (i = 0 ; i < G_N_ELEMENTS (modem_bands); i++) {
950
if (g_strcmp0 (icera, modem_bands[i].name) == 0)
951
return modem_bands[i].band;
953
return MM_MODEM_GSM_BAND_UNKNOWN;
957
mm_band_to_icera (MMModemGsmBand band)
961
for (i = 0; i < G_N_ELEMENTS (modem_bands); i++) {
962
if (modem_bands[i].band == band)
963
return modem_bands[i].name;
968
/* returns a list of 'Band' structs */
970
build_bands_info (const gchar *response, gboolean build_command)
972
GSList *bands = NULL;
977
* Response is a number of lines of the form:
981
* with 1 and 0 indicating whether the particular band is enabled or not.
983
r = g_regex_new ("^\"(\\w+)\": (\\d)",
984
G_REGEX_MULTILINE, G_REGEX_MATCH_NEWLINE_ANY,
986
g_assert (r != NULL);
988
g_regex_match (r, response, 0, &match);
989
while (g_match_info_matches (match)) {
990
gchar *name, *enabled;
994
name = g_match_info_fetch (match, 1);
995
enabled = g_match_info_fetch (match, 2);
996
band = icera_band_to_mm (name);
997
if (band != MM_MODEM_GSM_BAND_UNKNOWN && band != MM_MODEM_GSM_BAND_ANY) {
998
b = g_malloc0 (sizeof (Band));
1000
b->enabled = (enabled[0] == '1' ? TRUE : FALSE);
1001
if (build_command) {
1002
/* abuse 'name' for the AT command to check band support */
1003
b->name = g_strdup_printf ("%%IPBM=\"%s\",%c",
1005
b->enabled ? '1' : '0');
1007
bands = g_slist_append (bands, b);
1011
g_match_info_next (match, NULL);
1013
g_match_info_free (match);
1020
get_current_bands_done (MMAtSerialPort *port,
1025
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
1026
MMModemGsmBand mm_band = MM_MODEM_GSM_BAND_ANY;
1031
/* If the modem has already been removed, return without
1032
* scheduling callback */
1033
if (mm_callback_info_check_modem_removed (info))
1037
info->error = g_error_copy (error);
1038
mm_callback_info_schedule (info);
1042
bands = build_bands_info (response->str, FALSE);
1044
mm_callback_info_set_result (info, GUINT_TO_POINTER (MM_MODEM_GSM_BAND_UNKNOWN), NULL);
1045
mm_callback_info_schedule (info);
1049
for (iter = bands; iter; iter = g_slist_next (iter)) {
1054
g_slist_foreach (bands, (GFunc) band_free, NULL);
1055
g_slist_free (bands);
1057
mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL);
1058
mm_callback_info_schedule (info);
1062
mm_modem_icera_get_current_bands (MMModemIcera *self,
1063
MMModemUIntFn callback,
1066
MMAtSerialPort *port;
1067
MMCallbackInfo *info;
1069
info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
1071
/* Otherwise ask the modem */
1072
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
1074
mm_callback_info_schedule (info);
1078
mm_at_serial_port_queue_command (port, "AT%IPBM?", 3, get_current_bands_done, info);
1081
#define NUM_BANDS_TAG "num-bands"
1082
#define BAND_RESULT_TAG "band-result"
1085
get_one_supported_band_done (MMAtSerialPort *port,
1090
Band *b = user_data;
1091
MMCallbackInfo *info = b->data;
1092
MMModemGsmBand mm_bands = MM_MODEM_GSM_BAND_UNKNOWN;
1095
if (mm_callback_info_check_modem_removed (info) == FALSE) {
1096
/* Update supported bands list */
1097
mm_bands = GPOINTER_TO_UINT (mm_callback_info_get_data (info, BAND_RESULT_TAG));
1098
if (error == NULL) {
1099
mm_bands |= b->band;
1100
mm_callback_info_set_data (info, BAND_RESULT_TAG, GUINT_TO_POINTER (mm_bands), NULL);
1103
num = GPOINTER_TO_UINT (mm_callback_info_get_data (info, NUM_BANDS_TAG)) - 1;
1104
mm_callback_info_set_data (info, NUM_BANDS_TAG, GUINT_TO_POINTER (num), NULL);
1107
mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_bands), NULL);
1108
mm_callback_info_schedule (info);
1115
get_supported_bands_done (MMAtSerialPort *port,
1120
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
1121
GSList *bands, *iter;
1125
/* If the modem has already been removed, return without
1126
* scheduling callback */
1127
if (mm_callback_info_check_modem_removed (info))
1131
info->error = g_error_copy (error);
1132
mm_callback_info_schedule (info);
1136
bands = build_bands_info (response->str, TRUE);
1138
mm_callback_info_set_result (info, GUINT_TO_POINTER (MM_MODEM_GSM_BAND_UNKNOWN), NULL);
1139
mm_callback_info_schedule (info);
1143
for (iter = bands, i = 0; iter; iter = g_slist_next (iter), i++) {
1146
mm_at_serial_port_queue_command (port, b->name, 10, get_one_supported_band_done, b);
1148
/* Free list, but not items; they are freed when the AT response comes back */
1149
g_slist_free (bands);
1151
mm_callback_info_set_data (info, NUM_BANDS_TAG, GUINT_TO_POINTER (i), NULL);
1155
mm_modem_icera_get_supported_bands (MMModemIcera *self,
1156
MMModemUIntFn callback,
1159
MMAtSerialPort *port;
1160
MMCallbackInfo *info;
1162
info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data);
1164
/* Otherwise ask the modem */
1165
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
1167
mm_callback_info_schedule (info);
1171
/* The modems report some bands as disabled that they don't actually
1172
* support enabling. Thanks Icera! So we have to try setting each
1173
* band to it's current enabled/disabled value, and the modem will
1174
* return an error if it doesn't support that band at all.
1176
mm_at_serial_port_queue_command (port, "AT%IPBM?", 3, get_supported_bands_done, info);
1180
set_band_done (MMAtSerialPort *port,
1185
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
1187
/* If the modem has already been removed, return without
1188
* scheduling callback */
1189
if (mm_callback_info_check_modem_removed (info))
1193
info->error = g_error_copy (error);
1195
mm_callback_info_schedule (info);
1199
mm_modem_icera_set_band (MMModemIcera *self,
1200
MMModemGsmBand band,
1204
MMCallbackInfo *info;
1205
MMAtSerialPort *port;
1207
const char *icera_band;
1209
info = mm_callback_info_new (MM_MODEM (self), callback, user_data);
1211
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
1213
mm_callback_info_schedule (info);
1217
/* TODO: Check how to pass more than one band in the same AT%%IPBM command */
1218
if (!utils_check_for_single_value (band)) {
1219
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Cannot set more than one band.");
1220
mm_callback_info_schedule (info);
1224
icera_band = mm_band_to_icera (band);
1226
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid band.");
1227
mm_callback_info_schedule (info);
1231
command = g_strdup_printf ("AT%%IPBM=\"%s\",1", icera_band);
1232
mm_at_serial_port_queue_command (port, command, 10, set_band_done, info);
1236
/****************************************************************/
1239
get_unlock_retries_done (MMAtSerialPort *port,
1244
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
1246
GArray *retry_counts;
1247
PinRetryCount ur[4] = {
1248
{"sim-pin", 0}, {"sim-puk", 0}, {"sim-pin2", 0}, {"sim-puk2", 0}
1251
/* If the modem has already been removed, return without
1252
* scheduling callback */
1253
if (mm_callback_info_check_modem_removed (info))
1257
info->error = g_error_copy (error);
1261
matched = sscanf (response->str, "%%PINNUM: %d, %d, %d, %d",
1262
&ur[0].count, &ur[1].count, &ur[2].count, &ur[3].count);
1264
if (ur[0].count > 998) {
1265
info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
1266
"Invalid PIN attempts left %d", ur[0].count);
1270
retry_counts = g_array_sized_new (FALSE, TRUE, sizeof (PinRetryCount), 4);
1271
g_array_append_vals (retry_counts, &ur, 4);
1272
mm_callback_info_set_result (info, retry_counts, NULL);
1274
info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
1275
"Could not parse PIN retries results");
1279
mm_serial_port_close (MM_SERIAL_PORT (port));
1280
mm_callback_info_schedule (info);
1284
mm_modem_icera_get_unlock_retries (MMModemIcera *self,
1285
MMModemArrayFn callback,
1288
MMAtSerialPort *port;
1289
MMCallbackInfo *info;
1291
mm_dbg ("get_unlock_retries");
1293
info = mm_callback_info_array_new (MM_MODEM (self), callback, user_data);
1295
/* Ensure we have a usable port to use for the command */
1296
port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error);
1298
mm_callback_info_schedule (info);
1302
/* Modem may not be enabled yet, which sometimes can't be done until
1303
* the device has been unlocked. In this case we have to open the port
1306
if (!mm_serial_port_open (MM_SERIAL_PORT (port), &info->error)) {
1307
mm_callback_info_schedule (info);
1311
/* if the modem have not yet been enabled we need to make sure echoing is turned off */
1312
mm_at_serial_port_queue_command (port, "E0", 3, NULL, NULL);
1313
mm_at_serial_port_queue_command (port, "%PINNUM?", 3, get_unlock_retries_done, info);
1317
/****************************************************************/
825
1319
static const char *
826
1320
get_string_property (GHashTable *properties, const char *name)