OLD | NEW |
(Empty) | |
| 1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
| 2 /* |
| 3 * This program is free software; you can redistribute it and/or modify |
| 4 * it under the terms of the GNU General Public License as published by |
| 5 * the Free Software Foundation; either version 2 of the License, or |
| 6 * (at your option) any later version. |
| 7 * |
| 8 * This program is distributed in the hope that it will be useful, |
| 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 * GNU General Public License for more details: |
| 12 * |
| 13 * Copyright (C) 2008 - 2009 Novell, Inc. |
| 14 * Copyright (C) 2009 Red Hat, Inc. |
| 15 * Copyright 2011 by Samsung Electronics, Inc., |
| 16 */ |
| 17 |
| 18 #include <stdlib.h> |
| 19 #include <stdio.h> |
| 20 #include <string.h> |
| 21 #include <unistd.h> |
| 22 #include <glib.h> |
| 23 #include <errno.h> |
| 24 #include <arpa/inet.h> |
| 25 #include <dbus/dbus-glib.h> |
| 26 |
| 27 #include "mm-modem-samsung-gsm.h" |
| 28 #include "mm-modem-simple.h" |
| 29 #include "mm-errors.h" |
| 30 #include "mm-callback-info.h" |
| 31 #include "mm-modem-gsm-card.h" |
| 32 |
| 33 static void modem_init (MMModem *modem_class); |
| 34 static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class); |
| 35 static void modem_simple_init (MMModemSimple *class); |
| 36 |
| 37 |
| 38 G_DEFINE_TYPE_EXTENDED (MMModemSamsungGsm, mm_modem_samsung_gsm, MM_TYPE_GENERIC
_GSM, 0, |
| 39 G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init) |
| 40 G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simpl
e_init) |
| 41 G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_
gsm_network_init)) |
| 42 |
| 43 #define MM_MODEM_SAMSUNG_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), M
M_TYPE_MODEM_SAMSUNG_GSM, MMModemSamsungGsmPrivate)) |
| 44 |
| 45 #define SAMSUNG_IPDPACT_DISCONNECTED 0 |
| 46 #define SAMSUNG_IPDPACT_CONNECTED 1 |
| 47 #define SAMSUNG_IPDPACT_CONNECTING 2 |
| 48 #define SAMSUNG_IPDPACT_CONNECTED_FAILED 3 |
| 49 |
| 50 typedef struct { |
| 51 char * band; |
| 52 MMCallbackInfo *connect_pending_data; |
| 53 gboolean init_retried; |
| 54 |
| 55 char *username; |
| 56 char *password; |
| 57 |
| 58 MMModemGsmAccessTech last_act; |
| 59 |
| 60 } MMModemSamsungGsmPrivate; |
| 61 |
| 62 #define IPDPADDR_TAG "%IPDPADDR: " |
| 63 |
| 64 |
| 65 MMModem * |
| 66 mm_modem_samsung_gsm_new (const char *device, |
| 67 const char *driver, |
| 68 const char *plugin) |
| 69 { |
| 70 g_return_val_if_fail (device != NULL, NULL); |
| 71 g_return_val_if_fail (driver != NULL, NULL); |
| 72 g_return_val_if_fail (plugin != NULL, NULL); |
| 73 |
| 74 return MM_MODEM (g_object_new (MM_TYPE_MODEM_SAMSUNG_GSM, |
| 75 MM_MODEM_MASTER_DEVICE, device, |
| 76 MM_MODEM_DRIVER, driver, |
| 77 MM_MODEM_PLUGIN, plugin, |
| 78 MM_MODEM_IP_METHOD, MM_MODEM_IP_METHOD_DHCP, |
| 79 NULL)); |
| 80 } |
| 81 |
| 82 static void |
| 83 connect_pending_done (MMModemSamsungGsm *self) |
| 84 { |
| 85 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self); |
| 86 GError *error = NULL; |
| 87 |
| 88 if (priv->connect_pending_data) { |
| 89 if (priv->connect_pending_data->error) { |
| 90 error = priv->connect_pending_data->error; |
| 91 priv->connect_pending_data->error = NULL; |
| 92 } |
| 93 |
| 94 /* Complete the connect */ |
| 95 mm_generic_gsm_connect_complete (MM_GENERIC_GSM (self), error, priv->con
nect_pending_data); |
| 96 priv->connect_pending_data = NULL; |
| 97 } |
| 98 } |
| 99 |
| 100 void |
| 101 mm_modem_samsung_cleanup (MMModemSamsungGsm *self) |
| 102 { |
| 103 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self); |
| 104 |
| 105 /* Clear the pending connection if necessary */ |
| 106 connect_pending_done (self); |
| 107 g_free (priv->username); |
| 108 g_free (priv->password); |
| 109 memset (priv, 0, sizeof (MMModemSamsungGsmPrivate)); |
| 110 } |
| 111 |
| 112 void |
| 113 mm_modem_samsung_change_unsolicited_messages (MMModemSamsungGsm *self, gboolean
enabled) |
| 114 { |
| 115 MMAtSerialPort *primary; |
| 116 |
| 117 primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PR
IMARY); |
| 118 g_assert (primary); |
| 119 |
| 120 mm_at_serial_port_queue_command (primary, enabled ? "%NWSTATE=1" : "%NWSTATE
=0", 3, NULL, NULL); |
| 121 } |
| 122 |
| 123 typedef struct { |
| 124 MMModemGsmBand mm; |
| 125 char band[50]; |
| 126 } BandTable; |
| 127 |
| 128 static BandTable bands[12] = { |
| 129 /* Sort 3G first since it's preferred */ |
| 130 { MM_MODEM_GSM_BAND_U2100, "FDD_BAND_I" }, |
| 131 { MM_MODEM_GSM_BAND_U1900, "FDD_BAND_II" }, |
| 132 { MM_MODEM_GSM_BAND_U1800, "FDD_BAND_III" }, |
| 133 { MM_MODEM_GSM_BAND_U17IV, "FDD_BAND_IV" }, |
| 134 { MM_MODEM_GSM_BAND_U850, "FDD_BAND_V" }, |
| 135 { MM_MODEM_GSM_BAND_U800, "FDD_BAND_VI" }, |
| 136 { MM_MODEM_GSM_BAND_U900, "FDD_BAND_VIII" }, |
| 137 { MM_MODEM_GSM_BAND_G850, "G850" }, |
| 138 /* 2G second */ |
| 139 { MM_MODEM_GSM_BAND_DCS, "DCS" }, |
| 140 { MM_MODEM_GSM_BAND_EGSM, "EGSM" }, /* 0x100 = Extended GSM, 0x200 = Primar
y GSM */ |
| 141 { MM_MODEM_GSM_BAND_PCS, "PCS" }, |
| 142 /* And ANY last since it's most inclusive */ |
| 143 { MM_MODEM_GSM_BAND_ANY, "ANY" }, |
| 144 }; |
| 145 |
| 146 static gboolean |
| 147 band_mm_to_samsung (MMModemGsmBand band, MMModemGsmNetwork *modem) |
| 148 { |
| 149 int i; |
| 150 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (modem); |
| 151 |
| 152 for (i = 0; i < sizeof (bands) / sizeof (BandTable); i++) { |
| 153 if (bands[i].mm == band) { |
| 154 priv->band = bands[i].band; |
| 155 return TRUE; |
| 156 } |
| 157 } |
| 158 return FALSE; |
| 159 } |
| 160 |
| 161 static gint samsung_get_cid (MMModemSamsungGsm *self) |
| 162 { |
| 163 gint cid; |
| 164 |
| 165 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)); |
| 166 if (cid < 0) { |
| 167 g_warn_if_fail (cid >= 0); |
| 168 cid = 0; |
| 169 } |
| 170 |
| 171 return cid; |
| 172 } |
| 173 |
| 174 static gboolean |
| 175 parse_ipsys (MMModemSamsungGsm *self, |
| 176 const char *reply, |
| 177 int *mode, |
| 178 int *domain, |
| 179 MMModemGsmAllowedMode *out_mode) |
| 180 { |
| 181 if(reply == NULL || !g_str_has_prefix(reply, "%IPSYS:")) |
| 182 return FALSE; |
| 183 |
| 184 if (sscanf (reply + 7, "%d,%d", mode, domain) == 2) { |
| 185 MMModemGsmAllowedMode new_mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; |
| 186 |
| 187 /* Network mode */ |
| 188 if (*mode == 2) |
| 189 new_mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; |
| 190 else if (*mode == 3) |
| 191 new_mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; |
| 192 else if (*mode == 0) |
| 193 new_mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; |
| 194 else if (*mode == 1) |
| 195 new_mode = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY; |
| 196 |
| 197 if (out_mode) |
| 198 *out_mode = new_mode; |
| 199 |
| 200 return TRUE; |
| 201 } |
| 202 |
| 203 return FALSE; |
| 204 } |
| 205 |
| 206 |
| 207 static void |
| 208 get_allowed_mode_done (MMAtSerialPort *port, |
| 209 GString *response, |
| 210 GError *error, |
| 211 gpointer user_data) |
| 212 { |
| 213 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 214 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (info->modem); |
| 215 int mode, domain; |
| 216 MMModemGsmAllowedMode mode_out = MM_MODEM_GSM_ALLOWED_MODE_ANY; |
| 217 |
| 218 if (error) |
| 219 info->error = g_error_copy (error); |
| 220 else if (parse_ipsys (self, response->str, &mode, &domain, &mode_out)) |
| 221 mm_callback_info_set_result (info, GUINT_TO_POINTER (mode), NULL); |
| 222 |
| 223 mm_callback_info_schedule (info); |
| 224 } |
| 225 |
| 226 |
| 227 static void |
| 228 get_allowed_mode (MMGenericGsm *gsm, |
| 229 MMModemUIntFn callback, |
| 230 gpointer user_data) |
| 231 { |
| 232 MMCallbackInfo *info; |
| 233 MMAtSerialPort *port; |
| 234 |
| 235 info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); |
| 236 |
| 237 port = mm_generic_gsm_get_best_at_port (gsm, &info->error); |
| 238 if (!port) { |
| 239 mm_callback_info_schedule (info); |
| 240 return; |
| 241 } |
| 242 |
| 243 mm_at_serial_port_queue_command (port, "AT%IPSYS?", 3, get_allowed_mode_done
, info); |
| 244 } |
| 245 |
| 246 static void |
| 247 set_allowed_mode_done (MMAtSerialPort *port, |
| 248 GString *response, |
| 249 GError *error, |
| 250 gpointer user_data) |
| 251 { |
| 252 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 253 |
| 254 if (error) |
| 255 info->error = g_error_copy (error); |
| 256 |
| 257 mm_callback_info_schedule (info); |
| 258 } |
| 259 |
| 260 |
| 261 static void |
| 262 set_allowed_mode (MMGenericGsm *gsm, |
| 263 MMModemGsmAllowedMode mode, |
| 264 MMModemFn callback, |
| 265 gpointer user_data) |
| 266 { |
| 267 MMCallbackInfo *info; |
| 268 MMAtSerialPort *port; |
| 269 int i; |
| 270 char *command; |
| 271 |
| 272 info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); |
| 273 |
| 274 port = mm_generic_gsm_get_best_at_port (gsm, &info->error); |
| 275 if (!port) { |
| 276 mm_callback_info_schedule (info); |
| 277 return; |
| 278 } |
| 279 |
| 280 switch (mode) { |
| 281 case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: |
| 282 i = 0; |
| 283 break; |
| 284 case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: |
| 285 i = 1; |
| 286 break; |
| 287 case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: |
| 288 i = 2; |
| 289 break; |
| 290 case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: |
| 291 i = 3; |
| 292 break; |
| 293 case MM_MODEM_GSM_ALLOWED_MODE_ANY: |
| 294 default: |
| 295 i = 5; |
| 296 break; |
| 297 } |
| 298 |
| 299 command = g_strdup_printf ("AT%%IPSYS=%d,3",i); |
| 300 |
| 301 mm_at_serial_port_queue_command (port, command, 3, set_allowed_mode_done, in
fo); |
| 302 g_free (command); |
| 303 } |
| 304 |
| 305 static void |
| 306 set_band_done (MMAtSerialPort *port, |
| 307 GString *response, |
| 308 GError *error, |
| 309 gpointer user_data) |
| 310 { |
| 311 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 312 |
| 313 if (error) |
| 314 info->error = g_error_copy (error); |
| 315 |
| 316 mm_callback_info_schedule (info); |
| 317 } |
| 318 |
| 319 static void |
| 320 set_band (MMModemGsmNetwork *modem, |
| 321 MMModemGsmBand band, |
| 322 MMModemFn callback, |
| 323 gpointer user_data) |
| 324 { |
| 325 MMCallbackInfo *info; |
| 326 MMAtSerialPort *port; |
| 327 char *command; |
| 328 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (modem); |
| 329 |
| 330 info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); |
| 331 |
| 332 port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error
); |
| 333 if (!port) { |
| 334 mm_callback_info_schedule (info); |
| 335 return; |
| 336 } |
| 337 |
| 338 if (!band_mm_to_samsung (band, modem)) { |
| 339 info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERA
L, "Invalid band."); |
| 340 mm_callback_info_schedule (info); |
| 341 } else { |
| 342 mm_callback_info_set_data (info, "band", g_strdup(priv->band), NULL); |
| 343 command = g_strdup_printf ("AT%%IPBM=\"%s\",1", priv->band); |
| 344 mm_at_serial_port_queue_command (port, command, 3, set_band_done, info); |
| 345 g_free (command); |
| 346 priv->band = NULL; |
| 347 } |
| 348 } |
| 349 |
| 350 static gboolean parse_ipbm(MMModemSamsungGsm *self, |
| 351 const char *reply, |
| 352 MMModemGsmBand *band) |
| 353 { |
| 354 int enable[12]; |
| 355 |
| 356 g_assert(band != NULL); |
| 357 |
| 358 if (reply == NULL) |
| 359 return FALSE; |
| 360 |
| 361 if (sscanf (reply, "\"ANY\": %d\r\n\"EGSM\": %d\r\n\"DCS\": %d\r\n\"PCS\": %
d\r\n\"G850\": %d\r\n\"FDD_BAND_I\": %d\r\n\"FDD_BAND_II\": %d\r\n\"FDD_BAND_III
\": %d\r\n\"FDD_BAND_IV\": %d\r\n\"FDD_BAND_V\": %d\r\n\"FDD_BAND_VI\": %d\r\n\"
FDD_BAND_VIII\": %d", &enable[0], &enable[1], &enable[2], &enable[3], &enable[4]
, &enable[5], &enable[6], &enable[7], &enable[8], &enable[9], &enable[10], &enab
le[11])== 12) { |
| 362 |
| 363 if(enable[5] == 1) { |
| 364 *band = MM_MODEM_GSM_BAND_U2100; |
| 365 return TRUE;} |
| 366 else if(enable[6] == 1) { |
| 367 *band = MM_MODEM_GSM_BAND_U1900; |
| 368 return TRUE;} |
| 369 else if(enable[7] == 1) { |
| 370 *band = MM_MODEM_GSM_BAND_U1800; |
| 371 return TRUE;} |
| 372 else if(enable[8] == 1) { |
| 373 *band = MM_MODEM_GSM_BAND_U17IV; |
| 374 return TRUE;} |
| 375 else if(enable[9] == 1) { |
| 376 *band = MM_MODEM_GSM_BAND_U850; |
| 377 return TRUE;} |
| 378 else if(enable[10] == 1) { |
| 379 *band = MM_MODEM_GSM_BAND_U800; |
| 380 return TRUE;} |
| 381 else if(enable[11] == 1) { |
| 382 *band = MM_MODEM_GSM_BAND_U900; |
| 383 return TRUE;} |
| 384 else if(enable[1] == 1) { |
| 385 *band = MM_MODEM_GSM_BAND_EGSM; |
| 386 return TRUE;} |
| 387 else if(enable[2] == 1) { |
| 388 *band = MM_MODEM_GSM_BAND_DCS; |
| 389 return TRUE;} |
| 390 else if(enable[3] == 1) { |
| 391 *band = MM_MODEM_GSM_BAND_PCS; |
| 392 return TRUE;} |
| 393 else if(enable[4] == 1) { |
| 394 *band = MM_MODEM_GSM_BAND_G850; |
| 395 return TRUE;} |
| 396 else{ |
| 397 *band = MM_MODEM_GSM_BAND_ANY;} |
| 398 |
| 399 return TRUE; |
| 400 } |
| 401 |
| 402 return FALSE; |
| 403 } |
| 404 |
| 405 static void |
| 406 get_band_done (MMAtSerialPort *port, |
| 407 GString *response, |
| 408 GError *error, |
| 409 gpointer user_data) |
| 410 { |
| 411 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 412 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (info->modem); |
| 413 MMModemGsmBand mm_band = MM_MODEM_GSM_BAND_ANY; |
| 414 |
| 415 if (error) |
| 416 info->error = g_error_copy (error); |
| 417 else if (parse_ipbm (self, response->str, &mm_band)) { |
| 418 |
| 419 mm_callback_info_set_result (info, GUINT_TO_POINTER (mm_band), NULL); |
| 420 } |
| 421 |
| 422 mm_callback_info_schedule (info); |
| 423 } |
| 424 |
| 425 static void |
| 426 get_band (MMModemGsmNetwork *modem, |
| 427 MMModemUIntFn callback, |
| 428 gpointer user_data) |
| 429 { |
| 430 MMAtSerialPort *port; |
| 431 MMCallbackInfo *info; |
| 432 |
| 433 info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); |
| 434 |
| 435 /* Otherwise ask the modem */ |
| 436 port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error
); |
| 437 if (!port) { |
| 438 mm_callback_info_schedule (info); |
| 439 return; |
| 440 } |
| 441 |
| 442 mm_at_serial_port_queue_command (port, "AT%IPBM?", 3, get_band_done, info); |
| 443 } |
| 444 |
| 445 static void |
| 446 get_nwstate_done (MMAtSerialPort *port, |
| 447 GString *response, |
| 448 GError *error, |
| 449 gpointer user_data) |
| 450 { |
| 451 MMCallbackInfo *info = user_data; |
| 452 |
| 453 info->error = mm_modem_check_removed (info->modem, error); |
| 454 if (!info->error) { |
| 455 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (info->modem); |
| 456 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self)
; |
| 457 |
| 458 /* The unsolicited message handler will already have run and |
| 459 * removed the NWSTATE response, so we have to work around that. |
| 460 */ |
| 461 mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->last_act), NU
LL); |
| 462 priv->last_act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; |
| 463 } |
| 464 |
| 465 mm_callback_info_schedule (info); |
| 466 } |
| 467 |
| 468 static void |
| 469 get_access_technology (MMGenericGsm *gsm, |
| 470 MMModemUIntFn callback, |
| 471 gpointer user_data) |
| 472 { |
| 473 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (gsm); |
| 474 MMAtSerialPort *port; |
| 475 MMCallbackInfo *info; |
| 476 |
| 477 info = mm_callback_info_uint_new (MM_MODEM (self), callback, user_data); |
| 478 |
| 479 port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error)
; |
| 480 if (!port) { |
| 481 mm_callback_info_schedule (info); |
| 482 return; |
| 483 } |
| 484 |
| 485 mm_at_serial_port_queue_command (port, "%NWSTATE=1", 3, get_nwstate_done, in
fo); |
| 486 } |
| 487 |
| 488 typedef struct { |
| 489 MMModem *modem; |
| 490 MMModemFn callback; |
| 491 gpointer user_data; |
| 492 } DisableInfo; |
| 493 |
| 494 static void |
| 495 disable_unsolicited_done (MMAtSerialPort *port, |
| 496 GString *response, |
| 497 GError *error, |
| 498 gpointer user_data) |
| 499 |
| 500 { |
| 501 MMModem *parent_modem_iface; |
| 502 DisableInfo *info = user_data; |
| 503 |
| 504 parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (i
nfo->modem)); |
| 505 parent_modem_iface->disable (info->modem, info->callback, info->user_data); |
| 506 g_free (info); |
| 507 } |
| 508 |
| 509 static void |
| 510 disable (MMModem *modem, |
| 511 MMModemFn callback, |
| 512 gpointer user_data) |
| 513 { |
| 514 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (modem); |
| 515 MMAtSerialPort *primary; |
| 516 DisableInfo *info; |
| 517 |
| 518 priv->init_retried = FALSE; |
| 519 |
| 520 info = g_malloc0 (sizeof (DisableInfo)); |
| 521 info->callback = callback; |
| 522 info->user_data = user_data; |
| 523 info->modem = modem; |
| 524 |
| 525 primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_P
RIMARY); |
| 526 g_assert (primary); |
| 527 |
| 528 /* Turn off unsolicited responses */ |
| 529 mm_modem_samsung_cleanup (MM_MODEM_SAMSUNG_GSM (modem)); |
| 530 mm_modem_samsung_change_unsolicited_messages (MM_MODEM_SAMSUNG_GSM (modem),
FALSE); |
| 531 |
| 532 /* Random command to ensure unsolicited message disable completes */ |
| 533 mm_at_serial_port_queue_command (primary, "AT+CFUN=0", 5, disable_unsolicite
d_done, info); |
| 534 } |
| 535 |
| 536 static void |
| 537 init_modem_done (MMAtSerialPort *port, |
| 538 GString *response, |
| 539 GError *error, |
| 540 gpointer user_data) |
| 541 { |
| 542 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 543 |
| 544 mm_at_serial_port_queue_command (port, "ATE0;+CFUN=1", 5, NULL, NULL); |
| 545 |
| 546 mm_modem_samsung_change_unsolicited_messages (MM_MODEM_SAMSUNG_GSM (info->mo
dem), TRUE); |
| 547 |
| 548 mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); |
| 549 } |
| 550 |
| 551 static void enable_flash_done (MMSerialPort *port, |
| 552 GError *error, |
| 553 gpointer user_data); |
| 554 |
| 555 static void |
| 556 pre_init_done (MMAtSerialPort *port, |
| 557 GString *response, |
| 558 GError *error, |
| 559 gpointer user_data) |
| 560 { |
| 561 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 562 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (info->modem); |
| 563 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self); |
| 564 |
| 565 if (error) { |
| 566 /* Retry the init string one more time; the modem sometimes throws it aw
ay */ |
| 567 if ( !priv->init_retried |
| 568 && g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE
_TIMEOUT)) { |
| 569 priv->init_retried = TRUE; |
| 570 enable_flash_done (MM_SERIAL_PORT (port), NULL, user_data); |
| 571 } else |
| 572 mm_generic_gsm_enable_complete (MM_GENERIC_GSM (self), error, info); |
| 573 } else { |
| 574 /* Finish the initialization */ |
| 575 mm_at_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;"
, 10, init_modem_done, info); |
| 576 } |
| 577 } |
| 578 |
| 579 static void |
| 580 enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data) |
| 581 { |
| 582 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 583 |
| 584 if (error) |
| 585 mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, inf
o); |
| 586 else |
| 587 mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), "E0 V1", 3, p
re_init_done, user_data); |
| 588 } |
| 589 |
| 590 static void |
| 591 do_enable (MMGenericGsm *modem, MMModemFn callback, gpointer user_data) |
| 592 { |
| 593 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (modem); |
| 594 MMCallbackInfo *info; |
| 595 MMAtSerialPort *primary; |
| 596 |
| 597 priv->init_retried = FALSE; |
| 598 |
| 599 primary = mm_generic_gsm_get_at_port (modem, MM_PORT_TYPE_PRIMARY); |
| 600 g_assert (primary); |
| 601 |
| 602 info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); |
| 603 mm_serial_port_flash (MM_SERIAL_PORT (primary), 100, FALSE, enable_flash_don
e, info); |
| 604 } |
| 605 |
| 606 static void |
| 607 Samsung_call_control (MMModemSamsungGsm *self, |
| 608 gboolean activate, |
| 609 MMAtSerialResponseFn callback, |
| 610 gpointer user_data) |
| 611 { |
| 612 char *command; |
| 613 MMAtSerialPort *primary; |
| 614 |
| 615 primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PR
IMARY); |
| 616 g_assert (primary); |
| 617 |
| 618 command = g_strdup_printf ("%%IPDPACT=%d,%d", samsung_get_cid(self), activat
e ? 1 : 0); |
| 619 mm_at_serial_port_queue_command (primary, command, 3, callback, user_data); |
| 620 g_free (command); |
| 621 } |
| 622 |
| 623 static void |
| 624 Samsung_enabled (MMAtSerialPort *port, |
| 625 GString *response, |
| 626 GError *error, |
| 627 gpointer user_data) |
| 628 { |
| 629 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 630 |
| 631 if (error) { |
| 632 mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), error, in
fo); |
| 633 } else { |
| 634 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (info->modem); |
| 635 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self)
; |
| 636 |
| 637 priv->connect_pending_data = info; |
| 638 } |
| 639 } |
| 640 |
| 641 static void |
| 642 auth_done (MMAtSerialPort *port, |
| 643 GString *response, |
| 644 GError *error, |
| 645 gpointer user_data) |
| 646 { |
| 647 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 648 |
| 649 if (error) |
| 650 mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), error, in
fo); |
| 651 else { |
| 652 /* Activate the PDP context and start the data session */ |
| 653 Samsung_call_control (MM_MODEM_SAMSUNG_GSM (info->modem), TRUE, Samsung_enab
led, info); |
| 654 } |
| 655 } |
| 656 |
| 657 static void |
| 658 old_context_clear_done (MMAtSerialPort *port, |
| 659 GString *response, |
| 660 GError *error, |
| 661 gpointer user_data) |
| 662 { |
| 663 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 664 gint cid; |
| 665 char *command; |
| 666 MMAtSerialPort *primary; |
| 667 |
| 668 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (info->modem); |
| 669 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self); |
| 670 |
| 671 cid = samsung_get_cid (self); |
| 672 |
| 673 primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (self), MM_PORT_TYPE_PR
IMARY); |
| 674 g_assert (primary); |
| 675 |
| 676 /* Both user and password are required; otherwise firmware returns an error
*/ |
| 677 if (!priv->username || !priv->password) |
| 678 command = g_strdup_printf ("%%IPDPCFG=%d,0,0,\"\",\"\"", cid); |
| 679 else { |
| 680 command = g_strdup_printf ("%%IPDPCFG=%d,0,1,\"%s\",\"%s\"", |
| 681 cid, |
| 682 priv->password ? priv->password : "", |
| 683 priv->username ? priv->username : ""); |
| 684 |
| 685 } |
| 686 |
| 687 mm_at_serial_port_queue_command (primary, command, 3, auth_done, info); |
| 688 g_free (command); |
| 689 } |
| 690 |
| 691 void |
| 692 mm_modem_samsung_do_connect (MMModemSamsungGsm *self, |
| 693 const char *number, |
| 694 MMModemFn callback, |
| 695 gpointer user_data) |
| 696 { |
| 697 MMModem *modem = MM_MODEM (self); |
| 698 MMCallbackInfo *info; |
| 699 |
| 700 mm_modem_set_state (modem, MM_MODEM_STATE_CONNECTING, MM_MODEM_STATE_REASON_
NONE); |
| 701 |
| 702 info = mm_callback_info_new (modem, callback, user_data); |
| 703 |
| 704 |
| 705 /* Ensure the PDP context is deactivated */ |
| 706 Samsung_call_control (MM_MODEM_SAMSUNG_GSM (info->modem), FALSE, old_context
_clear_done, info); |
| 707 |
| 708 } |
| 709 |
| 710 static void |
| 711 do_connect (MMModem *modem, |
| 712 const char *number, |
| 713 MMModemFn callback, |
| 714 gpointer user_data) |
| 715 { |
| 716 |
| 717 mm_modem_samsung_do_connect (MM_MODEM_SAMSUNG_GSM (modem), number, callback,
user_data); |
| 718 |
| 719 } |
| 720 |
| 721 static void |
| 722 do_disconnect (MMGenericGsm *gsm, |
| 723 gint cid, |
| 724 MMModemFn callback, |
| 725 gpointer user_data) |
| 726 { |
| 727 MMCallbackInfo *info; |
| 728 MMAtSerialPort *primary; |
| 729 char *command; |
| 730 |
| 731 info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); |
| 732 |
| 733 primary = mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY); |
| 734 g_assert (primary); |
| 735 |
| 736 command = g_strdup_printf ("AT%%IPDPACT=%d,0", cid); |
| 737 |
| 738 mm_at_serial_port_queue_command (primary, command, 3, NULL, NULL); |
| 739 g_free (command); |
| 740 |
| 741 MM_GENERIC_GSM_CLASS (mm_modem_samsung_gsm_parent_class)->do_disconnect (gsm
, cid, callback, user_data); |
| 742 |
| 743 } |
| 744 |
| 745 static void |
| 746 Samsung_disconnect_done (MMModem *modem, |
| 747 GError *error, |
| 748 gpointer user_data) |
| 749 { |
| 750 g_message ("Modem signaled disconnection from the network"); |
| 751 } |
| 752 |
| 753 static void |
| 754 connection_enabled (MMAtSerialPort *port, |
| 755 GMatchInfo *match_info, |
| 756 gpointer user_data) |
| 757 { |
| 758 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (user_data); |
| 759 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self); |
| 760 MMCallbackInfo *info = priv->connect_pending_data; |
| 761 char *str; |
| 762 int status, cid, tmp; |
| 763 |
| 764 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (self)); |
| 765 if (cid < 0) |
| 766 return; |
| 767 |
| 768 str = g_match_info_fetch (match_info, 1); |
| 769 g_return_if_fail (str != NULL); |
| 770 tmp = atoi (str); |
| 771 g_free (str); |
| 772 |
| 773 /* Make sure the unsolicited message's CID matches the current CID */ |
| 774 if (tmp != cid) |
| 775 return; |
| 776 |
| 777 str = g_match_info_fetch (match_info, 2); |
| 778 g_return_if_fail (str != NULL); |
| 779 status = atoi (str); |
| 780 g_free (str); |
| 781 |
| 782 switch (status) { |
| 783 case 0: |
| 784 /* Disconnected */ |
| 785 if (mm_modem_get_state (MM_MODEM (self)) >= MM_MODEM_STATE_CONNECTED) |
| 786 mm_modem_disconnect (MM_MODEM (self), Samsung_disconnect_done, NULL)
; |
| 787 break; |
| 788 case 1: |
| 789 /* Connected */ |
| 790 connect_pending_done (self); |
| 791 break; |
| 792 case 2: |
| 793 /* Connecting */ |
| 794 break; |
| 795 case 3: |
| 796 /* Call setup failure? */ |
| 797 if (info) { |
| 798 info->error = g_error_new_literal (MM_MODEM_ERROR, |
| 799 MM_MODEM_ERROR_GENERAL, |
| 800 "Call setup failed"); |
| 801 } |
| 802 connect_pending_done (self); |
| 803 break; |
| 804 default: |
| 805 g_warning ("Unknown Samsung connect status %d", status); |
| 806 break; |
| 807 } |
| 808 } |
| 809 |
| 810 static void |
| 811 handle_mode_change (MMAtSerialPort *port, |
| 812 GMatchInfo *match_info, |
| 813 gpointer user_data) |
| 814 { |
| 815 MMModemSamsungGsm *self = MM_MODEM_SAMSUNG_GSM (user_data); |
| 816 MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; |
| 817 char *str; |
| 818 int rssi = -1; |
| 819 |
| 820 str = g_match_info_fetch (match_info, 1); |
| 821 if (str) { |
| 822 rssi = atoi (str); |
| 823 rssi = CLAMP (rssi, -1, 5); |
| 824 g_free (str); |
| 825 } |
| 826 |
| 827 str = g_match_info_fetch (match_info, 3); |
| 828 |
| 829 /* Better technologies are listed first since modems sometimes say |
| 830 * stuff like "GPRS/EDGE" and that should be handled as EDGE. |
| 831 */ |
| 832 g_debug ("Access Technology: %s", str); |
| 833 if (strcmp (str, "3G-HSDPA-HSUPA")==0) |
| 834 act = MM_MODEM_GSM_ACCESS_TECH_HSPA; |
| 835 else if (strcmp (str, "3G-HSUPA")==0) |
| 836 act = MM_MODEM_GSM_ACCESS_TECH_HSUPA; |
| 837 else if (strcmp (str, "3G-HSDPA")==0) |
| 838 act = MM_MODEM_GSM_ACCESS_TECH_HSDPA; |
| 839 else if (strcmp (str, "3G")==0) |
| 840 act = MM_MODEM_GSM_ACCESS_TECH_UMTS; |
| 841 else if (strcmp (str, "3g")==0) |
| 842 act = MM_MODEM_GSM_ACCESS_TECH_UMTS; |
| 843 else if (strcmp (str, "2G-EDGE")==0) |
| 844 act = MM_MODEM_GSM_ACCESS_TECH_EDGE; |
| 845 else if (strcmp (str, "2G-GPRS")==0) |
| 846 act = MM_MODEM_GSM_ACCESS_TECH_GPRS; |
| 847 else if (strcmp (str, "2g")==0) |
| 848 act = MM_MODEM_GSM_ACCESS_TECH_GSM; |
| 849 else |
| 850 act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; |
| 851 g_free (str); |
| 852 |
| 853 g_debug ("Access Technology: %d", act); |
| 854 MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (self)->last_act = act; |
| 855 mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), act); |
| 856 } |
| 857 |
| 858 static void |
| 859 free_dns_array (gpointer data) |
| 860 { |
| 861 g_array_free ((GArray *) data, TRUE); |
| 862 } |
| 863 |
| 864 static void |
| 865 ip4_config_invoke (MMCallbackInfo *info) |
| 866 { |
| 867 MMModemIp4Fn callback = (MMModemIp4Fn) info->callback; |
| 868 |
| 869 callback (info->modem, |
| 870 GPOINTER_TO_UINT (mm_callback_info_get_data (info, "ip4-address"))
, |
| 871 (GArray *) mm_callback_info_get_data (info, "ip4-dns"), |
| 872 info->error, info->user_data); |
| 873 } |
| 874 |
| 875 static void |
| 876 get_ip4_config_done (MMAtSerialPort *port, |
| 877 GString *response, |
| 878 GError *error, |
| 879 gpointer user_data) |
| 880 { |
| 881 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 882 char **items, **iter; |
| 883 GArray *dns_array; |
| 884 int i; |
| 885 guint32 tmp; |
| 886 gint cid; |
| 887 |
| 888 if (error) { |
| 889 info->error = g_error_copy (error); |
| 890 goto out; |
| 891 } else if (!g_str_has_prefix (response->str, IPDPADDR_TAG)) { |
| 892 info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERA
L, |
| 893 "Retrieving failed: invalid response.
"); |
| 894 goto out; |
| 895 } |
| 896 |
| 897 cid = samsung_get_cid (MM_MODEM_SAMSUNG_GSM (info->modem)); |
| 898 dns_array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 2); |
| 899 items = g_strsplit (response->str + strlen (IPDPADDR_TAG), ", ", 0); |
| 900 |
| 901 /* Appending data from at%IPDPADDR command |
| 902 * Skipping when i = 2. Gateway address is not what we want |
| 903 */ |
| 904 for (iter = items, i = 0; *iter; iter++, i++) { |
| 905 if (i == 0) { /* CID */ |
| 906 long int num; |
| 907 |
| 908 errno = 0; |
| 909 num = strtol (*iter, NULL, 10); |
| 910 if (errno != 0 || num < 0 || (gint) num != cid) { |
| 911 info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERA
L, |
| 912 "Unknown CID in OWANDATA response (" |
| 913 "got %d, expected %d)", (guint) num,
cid); |
| 914 break; |
| 915 } |
| 916 } else if (i == 1) { /* IP address */ |
| 917 if (inet_pton (AF_INET, *iter, &tmp) > 0) |
| 918 mm_callback_info_set_data (info, "ip4-address", GUINT_TO_POINTER
(tmp), NULL); |
| 919 } else if (i == 3) { /* DNS 1 */ |
| 920 if (inet_pton (AF_INET, *iter, &tmp) > 0) |
| 921 g_array_append_val (dns_array, tmp); |
| 922 } else if (i == 4) { /* DNS 2 */ |
| 923 if (inet_pton (AF_INET, *iter, &tmp) > 0) |
| 924 g_array_append_val (dns_array, tmp); |
| 925 } |
| 926 } |
| 927 |
| 928 g_strfreev (items); |
| 929 mm_callback_info_set_data (info, "ip4-dns", dns_array, free_dns_array); |
| 930 |
| 931 out: |
| 932 mm_callback_info_schedule (info); |
| 933 } |
| 934 |
| 935 |
| 936 static void |
| 937 get_ip4_config (MMModem *modem, |
| 938 MMModemIp4Fn callback, |
| 939 gpointer user_data) |
| 940 { |
| 941 MMCallbackInfo *info; |
| 942 char *command; |
| 943 MMAtSerialPort *primary; |
| 944 |
| 945 info = mm_callback_info_new_full (modem, ip4_config_invoke, G_CALLBACK (call
back), user_data); |
| 946 |
| 947 command = g_strdup_printf ("AT%%IPDPADDR=%d", samsung_get_cid (MM_MODEM_SAMS
UNG_GSM (modem))); |
| 948 |
| 949 primary = mm_generic_gsm_get_at_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_P
RIMARY); |
| 950 g_assert (primary); |
| 951 |
| 952 mm_at_serial_port_queue_command (primary, command, 3, get_ip4_config_done, i
nfo); |
| 953 g_free (command); |
| 954 } |
| 955 |
| 956 static const char * |
| 957 get_string_property (GHashTable *properties, const char *name) |
| 958 { |
| 959 GValue *value; |
| 960 |
| 961 value = (GValue *) g_hash_table_lookup (properties, name); |
| 962 if (value && G_VALUE_HOLDS_STRING (value)) |
| 963 return g_value_get_string (value); |
| 964 return NULL; |
| 965 } |
| 966 |
| 967 static void |
| 968 simple_connect (MMModemSimple *simple, |
| 969 GHashTable *properties, |
| 970 MMModemFn callback, |
| 971 gpointer user_data) |
| 972 { |
| 973 MMModemSamsungGsmPrivate *priv = MM_MODEM_SAMSUNG_GSM_GET_PRIVATE (simple); |
| 974 MMCallbackInfo *info = (MMCallbackInfo *) user_data; |
| 975 MMModemSimple *parent_iface; |
| 976 |
| 977 g_free (priv->username); |
| 978 priv->username = g_strdup (get_string_property (properties, "username")); |
| 979 g_free (priv->password); |
| 980 priv->password = g_strdup (get_string_property (properties, "password")); |
| 981 |
| 982 parent_iface = g_type_interface_peek_parent (MM_MODEM_SIMPLE_GET_INTERFACE (
simple)); |
| 983 parent_iface->connect (MM_MODEM_SIMPLE (simple), properties, callback, info)
; |
| 984 |
| 985 } |
| 986 |
| 987 static gboolean |
| 988 grab_port (MMModem *modem, |
| 989 const char *subsys, |
| 990 const char *name, |
| 991 MMPortType suggested_type, |
| 992 gpointer user_data, |
| 993 GError **error) |
| 994 { |
| 995 MMGenericGsm *gsm = MM_GENERIC_GSM (modem); |
| 996 MMPortType ptype = MM_PORT_TYPE_IGNORED; |
| 997 MMPort *port = NULL; |
| 998 |
| 999 if (suggested_type == MM_PORT_TYPE_UNKNOWN) { |
| 1000 if(g_str_has_prefix(name, "usb")) |
| 1001 ptype = MM_PORT_TYPE_ECM; |
| 1002 else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_PRIMARY)) |
| 1003 ptype = MM_PORT_TYPE_PRIMARY; |
| 1004 else if (!mm_generic_gsm_get_at_port (gsm, MM_PORT_TYPE_SECONDARY)) |
| 1005 ptype = MM_PORT_TYPE_SECONDARY; |
| 1006 } else |
| 1007 ptype = suggested_type; |
| 1008 |
| 1009 port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); |
| 1010 if (port && MM_IS_AT_SERIAL_PORT (port)) { |
| 1011 GRegex *regex; |
| 1012 |
| 1013 g_object_set (port, MM_PORT_CARRIER_DETECT, FALSE, NULL); |
| 1014 |
| 1015 |
| 1016 /* %NWSTATE: <rssi>,<mccmnc>,<tech>,<connected>,<regulation> */ |
| 1017 regex = g_regex_new ("\\r\\n\\%NWSTATE: (\\d),(\\d+),\\s*([^,\\s]*)\\s*,
(.+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); |
| 1018 mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port),
regex, handle_mode_change, modem, NULL); |
| 1019 g_regex_unref (regex); |
| 1020 |
| 1021 /* %IPDPACT: <cid>,<status>,0 */ |
| 1022 regex = g_regex_new ("\\r\\n%IPDPACT:\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)\\r
\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); |
| 1023 mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port),
regex, connection_enabled, modem, NULL); |
| 1024 g_regex_unref (regex); |
| 1025 } |
| 1026 |
| 1027 return !!port; |
| 1028 } |
| 1029 |
| 1030 static void |
| 1031 modem_init (MMModem *modem_class) |
| 1032 { |
| 1033 modem_class->disable = disable; |
| 1034 modem_class->connect = do_connect; |
| 1035 modem_class->get_ip4_config = get_ip4_config; |
| 1036 |
| 1037 modem_class->grab_port = grab_port; |
| 1038 } |
| 1039 |
| 1040 static void |
| 1041 modem_simple_init (MMModemSimple *class) |
| 1042 { |
| 1043 class->connect = simple_connect; |
| 1044 } |
| 1045 |
| 1046 static void |
| 1047 modem_gsm_network_init (MMModemGsmNetwork *class) |
| 1048 { |
| 1049 class->set_band = set_band; |
| 1050 class->get_band = get_band; |
| 1051 } |
| 1052 |
| 1053 static void |
| 1054 mm_modem_samsung_gsm_init (MMModemSamsungGsm *self) |
| 1055 { |
| 1056 } |
| 1057 |
| 1058 static void |
| 1059 mm_modem_samsung_gsm_class_init (MMModemSamsungGsmClass *klass) |
| 1060 { |
| 1061 |
| 1062 GObjectClass *object_class = G_OBJECT_CLASS (klass); |
| 1063 |
| 1064 MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass); |
| 1065 |
| 1066 mm_modem_samsung_gsm_parent_class = g_type_class_peek_parent (klass); |
| 1067 |
| 1068 g_type_class_add_private (object_class, sizeof (MMModemSamsungGsmPrivate)); |
| 1069 |
| 1070 gsm_class->do_disconnect = do_disconnect; |
| 1071 gsm_class->do_enable = do_enable; |
| 1072 |
| 1073 gsm_class->set_allowed_mode = set_allowed_mode; |
| 1074 gsm_class->get_allowed_mode = get_allowed_mode; |
| 1075 gsm_class->get_access_technology = get_access_technology; |
| 1076 } |
OLD | NEW |