1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 16daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov 17c54afe521739065a5d77e7c049acdb5e603f0592Ben Chan#include "shill/cellular/cellular_capability_gsm.h" 18daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov 194c0724af38d0eaf7155bb789280940a41ef9f08cJason Glasgow#include <string> 204c0724af38d0eaf7155bb789280940a41ef9f08cJason Glasgow#include <vector> 214c0724af38d0eaf7155bb789280940a41ef9f08cJason Glasgow 223e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/bind.h> 233e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood#include <base/stl_util.h> 24a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_number_conversions.h> 25a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h> 26289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#if defined(__ANDROID__) 27289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#include <dbus/service_constants.h> 28289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#else 2920c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov#include <chromeos/dbus/service_constants.h> 30289a5a5e18bb1a676b3dfce111af4c2c00c7776eSamuel Tan#endif // __ANDROID__ 3120c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov#include <mm/mm-modem.h> 32daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov 333cfbf216f1f918384866bf0d1a4c9a447d8109e8Darin Petkov#include "shill/adaptor_interfaces.h" 34c54afe521739065a5d77e7c049acdb5e603f0592Ben Chan#include "shill/cellular/cellular_service.h" 35608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu#include "shill/control_interface.h" 365de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood#include "shill/error.h" 37b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 38721ac93ab19a9169872a296626adb49279031af5Darin Petkov#include "shill/property_accessor.h" 39daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov 403e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbroodusing base::Bind; 41b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkovusing std::string; 424c0724af38d0eaf7155bb789280940a41ef9f08cJason Glasgowusing std::vector; 43b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov 44daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkovnamespace shill { 45daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov 46c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging { 47c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kCellular; 48f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartstatic string ObjectID(CellularCapabilityGSM* c) { 49c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein return c->cellular()->GetRpcIdentifier(); 50c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 51c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 52c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein 53ac635a8fb539fd44f3e24c33872b61fd064c0d60Darin Petkov// static 541272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkovconst char CellularCapabilityGSM::kNetworkPropertyAccessTechnology[] = 551272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "access-tech"; 561272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkovconst char CellularCapabilityGSM::kNetworkPropertyID[] = "operator-num"; 571272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkovconst char CellularCapabilityGSM::kNetworkPropertyLongName[] = "operator-long"; 581272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkovconst char CellularCapabilityGSM::kNetworkPropertyShortName[] = 591272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "operator-short"; 601272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkovconst char CellularCapabilityGSM::kNetworkPropertyStatus[] = "status"; 61ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkovconst char CellularCapabilityGSM::kPhoneNumber[] = "*99#"; 62ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkovconst char CellularCapabilityGSM::kPropertyAccessTechnology[] = 63ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov "AccessTechnology"; 6463138a9b8249fd69c83a772ee3170551a589d57aDarin Petkovconst char CellularCapabilityGSM::kPropertyEnabledFacilityLocks[] = 6563138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov "EnabledFacilityLocks"; 66721ac93ab19a9169872a296626adb49279031af5Darin Petkovconst char CellularCapabilityGSM::kPropertyUnlockRequired[] = "UnlockRequired"; 67721ac93ab19a9169872a296626adb49279031af5Darin Petkovconst char CellularCapabilityGSM::kPropertyUnlockRetries[] = "UnlockRetries"; 681272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov 69c89b928f1dd9240a7466585821ed8f277bdc4203Ben Chanconst int CellularCapabilityGSM::kGetIMSIRetryLimit = 40; 707fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst int64_t CellularCapabilityGSM::kGetIMSIRetryDelayMilliseconds = 500; 7182a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain 7282a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain 73608ec29525f553d51f0a92e84176e3d4b45930a9Peter QiuCellularCapabilityGSM::CellularCapabilityGSM( 74608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu Cellular* cellular, 75608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu ControlInterface* control_interface, 76608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu ModemInfo* modem_info) 77608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu : CellularCapabilityClassic(cellular, control_interface, modem_info), 783e20a2341d0aeb7681e4ee0f89eae6817ade2b3bEric Shienbrood weak_ptr_factory_(this), 79afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu mobile_operator_info_(new MobileOperatorInfo(cellular->dispatcher(), 80afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu "ParseScanResult")), 81184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov registration_state_(MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN), 82ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov access_technology_(MM_MODEM_GSM_ACCESS_TECH_UNKNOWN), 83ea18c6c99743aeee9b2e544532ef9fe55dbd182dBen Chan home_provider_info_(nullptr), 8482a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain get_imsi_retries_(0), 8549ffffd458c2407c67c2d0d572974e91c7e9bea7Prathmesh Prabhu get_imsi_retry_delay_milliseconds_(kGetIMSIRetryDelayMilliseconds) { 86c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Cellular capability constructed: GSM"; 87afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu mobile_operator_info_->Init(); 88bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawal HelpRegisterConstDerivedKeyValueStore( 897ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan kSIMLockStatusProperty, &CellularCapabilityGSM::SimLockStatusToProperty); 909f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu this->cellular()->set_scanning_supported(true); 913ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan 923ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // TODO(benchan): This is a hack to initialize the GSM card proxy for GetIMSI 933ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // before InitProxies is called. There are side-effects of calling InitProxies 943ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // before the device is enabled. It's better to refactor InitProxies such that 953ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // proxies can be created when the cellular device/capability is constructed, 963ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // but callbacks for DBus signal updates are not set up until the device is 973ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // enabled. 983ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan card_proxy_.reset( 99608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu control_interface->CreateModemGSMCardProxy(cellular->dbus_path(), 10005d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu cellular->dbus_service())); 1013ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // TODO(benchan): To allow unit testing using a mock proxy without further 102ea18c6c99743aeee9b2e544532ef9fe55dbd182dBen Chan // complicating the code, the test proxy factory is set up to return a nullptr 1033ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // pointer when CellularCapabilityGSM is constructed. Refactor the code to 1043ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // avoid this hack. 1053ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan if (card_proxy_.get()) 1063ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan InitProperties(); 1071272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov} 108daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov 109f98f00e52f3408fd3ca6184f19636efb7e66b986Ben ChanCellularCapabilityGSM::~CellularCapabilityGSM() {} 110f98f00e52f3408fd3ca6184f19636efb7e66b986Ben Chan 111f98f00e52f3408fd3ca6184f19636efb7e66b986Ben Chanstring CellularCapabilityGSM::GetTypeString() const { 112f98f00e52f3408fd3ca6184f19636efb7e66b986Ben Chan return kTechnologyFamilyGsm; 113f98f00e52f3408fd3ca6184f19636efb7e66b986Ben Chan} 114f98f00e52f3408fd3ca6184f19636efb7e66b986Ben Chan 115f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul StewartKeyValueStore CellularCapabilityGSM::SimLockStatusToProperty(Error* /*error*/) { 11663138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov KeyValueStore status; 1177ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan status.SetBool(kSIMLockEnabledProperty, sim_lock_status_.enabled); 1187ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan status.SetString(kSIMLockTypeProperty, sim_lock_status_.lock_type); 1197ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan status.SetUint(kSIMLockRetriesLeftProperty, sim_lock_status_.retries_left); 12063138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov return status; 121721ac93ab19a9169872a296626adb49279031af5Darin Petkov} 122721ac93ab19a9169872a296626adb49279031af5Darin Petkov 123bebf1b8bce52b88c2cc2d93200b9405f9c19cf21mukesh agrawalvoid CellularCapabilityGSM::HelpRegisterConstDerivedKeyValueStore( 124f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& name, 125f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart KeyValueStore(CellularCapabilityGSM::*get)(Error* error)) { 12663138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov cellular()->mutable_store()->RegisterDerivedKeyValueStore( 127721ac93ab19a9169872a296626adb49279031af5Darin Petkov name, 12863138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov KeyValueStoreAccessor( 12963138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov new CustomAccessor<CellularCapabilityGSM, KeyValueStore>( 130ea18c6c99743aeee9b2e544532ef9fe55dbd182dBen Chan this, get, nullptr))); 131721ac93ab19a9169872a296626adb49279031af5Darin Petkov} 132721ac93ab19a9169872a296626adb49279031af5Darin Petkov 1339a24553461df7036755060423f90804011612249Eric Shienbroodvoid CellularCapabilityGSM::InitProxies() { 13482f9ab3f404c8f414348c6effdc57c4d3b9223d7Jason Glasgow CellularCapabilityClassic::InitProxies(); 1353ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // TODO(benchan): Remove this check after refactoring the proxy 1363ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan // initialization. 1373ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan if (!card_proxy_.get()) { 1383ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan card_proxy_.reset( 13905d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu control_interface()->CreateModemGSMCardProxy( 14005d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu cellular()->dbus_path(), cellular()->dbus_service())); 1413ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan } 142184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov network_proxy_.reset( 143608ec29525f553d51f0a92e84176e3d4b45930a9Peter Qiu control_interface()->CreateModemGSMNetworkProxy( 14405d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu cellular()->dbus_path(), cellular()->dbus_service())); 1459a24553461df7036755060423f90804011612249Eric Shienbrood network_proxy_->set_signal_quality_callback( 1469a24553461df7036755060423f90804011612249Eric Shienbrood Bind(&CellularCapabilityGSM::OnSignalQualitySignal, 1479a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr())); 1489a24553461df7036755060423f90804011612249Eric Shienbrood network_proxy_->set_network_mode_callback( 1499a24553461df7036755060423f90804011612249Eric Shienbrood Bind(&CellularCapabilityGSM::OnNetworkModeSignal, 1509a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr())); 1519a24553461df7036755060423f90804011612249Eric Shienbrood network_proxy_->set_registration_info_callback( 1529a24553461df7036755060423f90804011612249Eric Shienbrood Bind(&CellularCapabilityGSM::OnRegistrationInfoSignal, 1539a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr())); 1549a24553461df7036755060423f90804011612249Eric Shienbrood} 1559a24553461df7036755060423f90804011612249Eric Shienbrood 1563ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chanvoid CellularCapabilityGSM::InitProperties() { 157f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart CellularTaskList* tasks = new CellularTaskList(); 1583ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan ResultCallback cb_ignore_error = 1593ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan Bind(&CellularCapabilityGSM::StepCompletedCallback, 1603ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan weak_ptr_factory_.GetWeakPtr(), ResultCallback(), true, tasks); 161bd3aee80be371d838863eccf708fd107153503efBen Chan // Chrome checks if a SIM is present before allowing the modem to be enabled, 162bd3aee80be371d838863eccf708fd107153503efBen Chan // so shill needs to obtain IMSI, as an indicator of SIM presence, even 163bd3aee80be371d838863eccf708fd107153503efBen Chan // before the device is enabled. 1643ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI, 1653ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan weak_ptr_factory_.GetWeakPtr(), cb_ignore_error)); 1663ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan RunNextStep(tasks); 1673ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan} 1683ecdf823b0ae196bd6824d5dc140da752776b3f9Ben Chan 169f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::StartModem(Error* error, 170f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultCallback& callback) { 1719a24553461df7036755060423f90804011612249Eric Shienbrood InitProxies(); 1729a24553461df7036755060423f90804011612249Eric Shienbrood 173f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart CellularTaskList* tasks = new CellularTaskList(); 1749a24553461df7036755060423f90804011612249Eric Shienbrood ResultCallback cb = 1759a24553461df7036755060423f90804011612249Eric Shienbrood Bind(&CellularCapabilityGSM::StepCompletedCallback, 176923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le weak_ptr_factory_.GetWeakPtr(), callback, false, tasks); 177923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le ResultCallback cb_ignore_error = 178923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le Bind(&CellularCapabilityGSM::StepCompletedCallback, 179923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le weak_ptr_factory_.GetWeakPtr(), callback, true, tasks); 1807fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood if (!cellular()->IsUnderlyingDeviceEnabled()) 1817fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::EnableModem, 1827fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb)); 1837fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood // If we're within range of the home network, the modem will try to 1847fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood // register once it's enabled, or may be already registered if we 1857fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood // started out enabled. 1869f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu if (!IsUnderlyingDeviceRegistered() && 1879f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu !cellular()->selected_network().empty()) 1887fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::Register, 1897fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb)); 1909a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::GetIMEI, 1919a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb)); 19282a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain get_imsi_retries_ = 0; 1939a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::GetIMSI, 1949a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb)); 1959a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::GetSPN, 196923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le weak_ptr_factory_.GetWeakPtr(), cb_ignore_error)); 1979a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::GetMSISDN, 198923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le weak_ptr_factory_.GetWeakPtr(), cb_ignore_error)); 1999a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::GetProperties, 2009a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb)); 2019a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::GetModemInfo, 2027fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb_ignore_error)); 2039a24553461df7036755060423f90804011612249Eric Shienbrood tasks->push_back(Bind(&CellularCapabilityGSM::FinishEnable, 2049a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), cb)); 2059a24553461df7036755060423f90804011612249Eric Shienbrood 2069a24553461df7036755060423f90804011612249Eric Shienbrood RunNextStep(tasks); 2079a24553461df7036755060423f90804011612249Eric Shienbrood} 2089a24553461df7036755060423f90804011612249Eric Shienbrood 2097fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbroodbool CellularCapabilityGSM::IsUnderlyingDeviceRegistered() const { 2107fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood switch (cellular()->modem_state()) { 2117b7d63db971ac701b765cee74f6664334de69280Ben Chan case Cellular::kModemStateFailed: 2127fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateUnknown: 2137fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateDisabled: 2147fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateInitializing: 2157fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateLocked: 2167fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateDisabling: 2177fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateEnabling: 2187fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateEnabled: 2197fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood return false; 2207fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateSearching: 2217fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateRegistered: 2227fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateDisconnecting: 2237fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateConnecting: 2247fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood case Cellular::kModemStateConnected: 2257fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood return true; 2267fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood } 2277fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood return false; 2287fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood} 2297fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood 2309a24553461df7036755060423f90804011612249Eric Shienbroodvoid CellularCapabilityGSM::ReleaseProxies() { 231c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 23282f9ab3f404c8f414348c6effdc57c4d3b9223d7Jason Glasgow CellularCapabilityClassic::ReleaseProxies(); 233721ac93ab19a9169872a296626adb49279031af5Darin Petkov card_proxy_.reset(); 234721ac93ab19a9169872a296626adb49279031af5Darin Petkov network_proxy_.reset(); 235721ac93ab19a9169872a296626adb49279031af5Darin Petkov} 236721ac93ab19a9169872a296626adb49279031af5Darin Petkov 23763881a73f4aa10521e0173e4fa5e4dedec45730fThieu Lebool CellularCapabilityGSM::AreProxiesInitialized() const { 23863881a73f4aa10521e0173e4fa5e4dedec45730fThieu Le return (CellularCapabilityClassic::AreProxiesInitialized() && 23963881a73f4aa10521e0173e4fa5e4dedec45730fThieu Le card_proxy_.get() && network_proxy_.get()); 24063881a73f4aa10521e0173e4fa5e4dedec45730fThieu Le} 24163881a73f4aa10521e0173e4fa5e4dedec45730fThieu Le 2425f316f65dd63b21c050f48410170482bfe92e286Darin Petkovvoid CellularCapabilityGSM::OnServiceCreated() { 2437ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan cellular()->service()->SetActivationState(kActivationStateActivated); 244ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov} 245ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov 24630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// Create the list of APNs to try, in the following order: 24730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// - last APN that resulted in a successful connection attempt on the 24830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// current network (if any) 24930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// - the APN, if any, that was set by the user 25030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// - the list of APNs found in the mobile broadband provider DB for the 25130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// home provider associated with the current SIM 25230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood// - as a last resort, attempt to connect with no APN 25330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularCapabilityGSM::SetupApnTryList() { 25430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood apn_try_list_.clear(); 25530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 25630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood DCHECK(cellular()->service().get()); 257f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Stringmap* apn_info = cellular()->service()->GetLastGoodApn(); 25830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood if (apn_info) 25930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood apn_try_list_.push_back(*apn_info); 26030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 26130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood apn_info = cellular()->service()->GetUserSpecifiedApn(); 26230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood if (apn_info) 26330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood apn_try_list_.push_back(*apn_info); 26430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 2659f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu apn_try_list_.insert(apn_try_list_.end(), 2669f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->apn_list().begin(), 2679f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->apn_list().end()); 26830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood} 26930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 270ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkovvoid CellularCapabilityGSM::SetupConnectProperties( 27105d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu KeyValueStore* properties) { 27230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood SetupApnTryList(); 27330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood FillConnectPropertyMap(properties); 27430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood} 27530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 27630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbroodvoid CellularCapabilityGSM::FillConnectPropertyMap( 27705d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu KeyValueStore* properties) { 27805d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties->SetString(kConnectPropertyPhoneNumber, kPhoneNumber); 27930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 28082f9ab3f404c8f414348c6effdc57c4d3b9223d7Jason Glasgow if (!AllowRoaming()) 28105d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties->SetBool(kConnectPropertyHomeOnly, true); 28230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 28330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood if (!apn_try_list_.empty()) { 28430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood // Leave the APN at the front of the list, so that it can be recorded 28530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood // if the connect attempt succeeds. 28630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood Stringmap apn_info = apn_try_list_.front(); 287c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << ": Using APN " << apn_info[kApnProperty]; 28805d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties->SetString(kConnectPropertyApn, apn_info[kApnProperty]); 2897ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan if (ContainsKey(apn_info, kApnUsernameProperty)) 29005d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties->SetString(kConnectPropertyApnUsername, 29105d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu apn_info[kApnUsernameProperty]); 2927ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan if (ContainsKey(apn_info, kApnPasswordProperty)) 29305d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties->SetString(kConnectPropertyApnPassword, 29405d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu apn_info[kApnPasswordProperty]); 29530bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood } 29630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood} 29730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood 29805d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiuvoid CellularCapabilityGSM::Connect(const KeyValueStore& properties, 299f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart Error* error, 300f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultCallback& callback) { 301c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 302b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams ResultCallback cb = Bind(&CellularCapabilityGSM::OnConnectReply, 303b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams weak_ptr_factory_.GetWeakPtr(), 304b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams callback); 305b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams simple_proxy_->Connect(properties, error, cb, kTimeoutConnect); 306b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams} 307b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams 308f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::OnConnectReply(const ResultCallback& callback, 309f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 310b5954a249c1346e5a0da097330a3639753392ecbThieu Le CellularServiceRefPtr service = cellular()->service(); 311b5954a249c1346e5a0da097330a3639753392ecbThieu Le if (!service) { 312b5954a249c1346e5a0da097330a3639753392ecbThieu Le // The service could have been deleted before our Connect() request 313b5954a249c1346e5a0da097330a3639753392ecbThieu Le // completes if the modem was enabled and then quickly disabled. 314b5954a249c1346e5a0da097330a3639753392ecbThieu Le apn_try_list_.clear(); 315b5954a249c1346e5a0da097330a3639753392ecbThieu Le } else if (error.IsFailure()) { 316b5954a249c1346e5a0da097330a3639753392ecbThieu Le service->ClearLastGoodApn(); 31730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood // The APN that was just tried (and failed) is still at the 31830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood // front of the list, about to be removed. If the list is empty 31930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood // after that, try one last time without an APN. This may succeed 32030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood // with some modems in some cases. 32130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood if (error.type() == Error::kInvalidApn && !apn_try_list_.empty()) { 32230bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood apn_try_list_.pop_front(); 323c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Connect failed with invalid APN, " 324c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << apn_try_list_.size() << " remaining APNs to try"; 32505d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu KeyValueStore props; 32630bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood FillConnectPropertyMap(&props); 32730bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood Error error; 32830bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood Connect(props, &error, callback); 32930bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood return; 33030bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood } 33130bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood } else if (!apn_try_list_.empty()) { 332b5954a249c1346e5a0da097330a3639753392ecbThieu Le service->SetLastGoodApn(apn_try_list_.front()); 33330bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood apn_try_list_.clear(); 33430bc0ecfcdad79f652eab10c7cda9adca33a04faEric Shienbrood } 335b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams if (!callback.is_null()) 336b54974f033f713690135f3f3516ca14aa7ee6cfdNathan Williams callback.Run(error); 33782f9ab3f404c8f414348c6effdc57c4d3b9223d7Jason Glasgow} 33882f9ab3f404c8f414348c6effdc57c4d3b9223d7Jason Glasgow 33982f9ab3f404c8f414348c6effdc57c4d3b9223d7Jason Glasgowbool CellularCapabilityGSM::AllowRoaming() { 3409f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu return cellular()->provider_requires_roaming() || allow_roaming_property(); 341ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov} 342ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov 3439a24553461df7036755060423f90804011612249Eric Shienbrood// always called from an async context 344f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::GetIMEI(const ResultCallback& callback) { 345c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 3469a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(!callback.is_null()); 3479a24553461df7036755060423f90804011612249Eric Shienbrood Error error; 3489f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu if (cellular()->imei().empty()) { 3499a24553461df7036755060423f90804011612249Eric Shienbrood GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMEIReply, 3509a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), callback); 3519a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->GetIMEI(&error, cb, kTimeoutDefault); 3529a24553461df7036755060423f90804011612249Eric Shienbrood if (error.IsFailure()) 3539a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 3545de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 355c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Already have IMEI " << cellular()->imei(); 3569a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 3575de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 3585de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 3595de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 3609a24553461df7036755060423f90804011612249Eric Shienbrood// always called from an async context 361f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::GetIMSI(const ResultCallback& callback) { 362c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 3639a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(!callback.is_null()); 3649a24553461df7036755060423f90804011612249Eric Shienbrood Error error; 3659f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu if (cellular()->imsi().empty()) { 3669a24553461df7036755060423f90804011612249Eric Shienbrood GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetIMSIReply, 3679a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), 3689a24553461df7036755060423f90804011612249Eric Shienbrood callback); 3699a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->GetIMSI(&error, cb, kTimeoutDefault); 37028b4a3b38737f29b98e0e19aefd92b2454165040Prathmesh Prabhu if (error.IsFailure()) { 3718599e052529c222da6cefd934bd52ceb9c194f5fPrathmesh Prabhu cellular()->home_provider_info()->Reset(); 3729a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 37328b4a3b38737f29b98e0e19aefd92b2454165040Prathmesh Prabhu } 3745de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 375c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Already have IMSI " << cellular()->imsi(); 3769a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 377cb547737d288052935052eeb341b30922b4022a0Darin Petkov } 3785de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 3795de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 3809a24553461df7036755060423f90804011612249Eric Shienbrood// always called from an async context 381f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::GetSPN(const ResultCallback& callback) { 382c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 3839a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(!callback.is_null()); 3849a24553461df7036755060423f90804011612249Eric Shienbrood Error error; 385ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov if (spn_.empty()) { 3869a24553461df7036755060423f90804011612249Eric Shienbrood GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetSPNReply, 3879a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), 3889a24553461df7036755060423f90804011612249Eric Shienbrood callback); 3899a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->GetSPN(&error, cb, kTimeoutDefault); 3909a24553461df7036755060423f90804011612249Eric Shienbrood if (error.IsFailure()) 3919a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 3925de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 393c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Already have SPN " << spn_; 3949a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 395cb547737d288052935052eeb341b30922b4022a0Darin Petkov } 3965de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 3975de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 3989a24553461df7036755060423f90804011612249Eric Shienbrood// always called from an async context 399f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::GetMSISDN(const ResultCallback& callback) { 400c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 4019a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(!callback.is_null()); 4029a24553461df7036755060423f90804011612249Eric Shienbrood Error error; 4039f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu string mdn = cellular()->mdn(); 4049f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu if (mdn.empty()) { 4059a24553461df7036755060423f90804011612249Eric Shienbrood GSMIdentifierCallback cb = Bind(&CellularCapabilityGSM::OnGetMSISDNReply, 4069a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), 4079a24553461df7036755060423f90804011612249Eric Shienbrood callback); 4089a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->GetMSISDN(&error, cb, kTimeoutDefault); 4099a24553461df7036755060423f90804011612249Eric Shienbrood if (error.IsFailure()) 4109a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 4115de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 412c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Already have MSISDN " << mdn; 4139a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 414cb547737d288052935052eeb341b30922b4022a0Darin Petkov } 415cb547737d288052935052eeb341b30922b4022a0Darin Petkov} 416cb547737d288052935052eeb341b30922b4022a0Darin Petkov 4173e509242f1a0e2e018a5c18a8d7b9224c6044d9aDarin Petkovvoid CellularCapabilityGSM::GetSignalQuality() { 418c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 4199a24553461df7036755060423f90804011612249Eric Shienbrood SignalQualityCallback callback = 4209a24553461df7036755060423f90804011612249Eric Shienbrood Bind(&CellularCapabilityGSM::OnGetSignalQualityReply, 4219a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr()); 422ea18c6c99743aeee9b2e544532ef9fe55dbd182dBen Chan network_proxy_->GetSignalQuality(nullptr, callback, kTimeoutDefault); 4233e509242f1a0e2e018a5c18a8d7b9224c6044d9aDarin Petkov} 4243e509242f1a0e2e018a5c18a8d7b9224c6044d9aDarin Petkov 4259a24553461df7036755060423f90804011612249Eric Shienbroodvoid CellularCapabilityGSM::GetRegistrationState() { 426c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 4279a24553461df7036755060423f90804011612249Eric Shienbrood RegistrationInfoCallback callback = 4289a24553461df7036755060423f90804011612249Eric Shienbrood Bind(&CellularCapabilityGSM::OnGetRegistrationInfoReply, 4299a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr()); 430ea18c6c99743aeee9b2e544532ef9fe55dbd182dBen Chan network_proxy_->GetRegistrationInfo(nullptr, callback, kTimeoutDefault); 4315de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 4325de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 433f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::GetProperties(const ResultCallback& callback) { 434c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__; 43563138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov 436ee6b3d7f9d49fa52072a352fbb59f06127b1ba4cPaul Stewart // TODO(petkov): Switch to asynchronous calls (crbug.com/200687). 4377fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t tech = network_proxy_->AccessTechnology(); 438ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov SetAccessTechnology(tech); 439c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GSM AccessTechnology: " << tech; 44063138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov 441ee6b3d7f9d49fa52072a352fbb59f06127b1ba4cPaul Stewart // TODO(petkov): Switch to asynchronous calls (crbug.com/200687). 4427fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t locks = card_proxy_->EnabledFacilityLocks(); 44363138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM; 444c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GSM EnabledFacilityLocks: " << locks; 44563138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov 4469a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(Error()); 447184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov} 448184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov 4499a24553461df7036755060423f90804011612249Eric Shienbrood// always called from an async context 450f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::Register(const ResultCallback& callback) { 451c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << " \"" << cellular()->selected_network() 452c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << "\""; 4539a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(!callback.is_null()); 4549a24553461df7036755060423f90804011612249Eric Shienbrood Error error; 4559a24553461df7036755060423f90804011612249Eric Shienbrood ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply, 4569a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), callback); 4579f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu network_proxy_->Register(cellular()->selected_network(), &error, cb, 4589f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu kTimeoutRegister); 4599a24553461df7036755060423f90804011612249Eric Shienbrood if (error.IsFailure()) 4609a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 461184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov} 462184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov 463184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkovvoid CellularCapabilityGSM::RegisterOnNetwork( 464f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& network_id, 465f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart Error* error, 466f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultCallback& callback) { 467c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << network_id << ")"; 4689a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(error); 4695de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood desired_network_ = network_id; 4709a24553461df7036755060423f90804011612249Eric Shienbrood ResultCallback cb = Bind(&CellularCapabilityGSM::OnRegisterReply, 4719a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), callback); 4729a24553461df7036755060423f90804011612249Eric Shienbrood network_proxy_->Register(network_id, error, cb, kTimeoutRegister); 4735de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 4745de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 475f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::OnRegisterReply(const ResultCallback& callback, 476f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 477c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << "(" << error << ")"; 4785de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 4795de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood if (error.IsSuccess()) { 4809f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_selected_network(desired_network_); 4815de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood desired_network_.clear(); 4829a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 4835de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood return; 4845de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 4855de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood // If registration on the desired network failed, 4865de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood // try to register on the home network. 4875de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood if (!desired_network_.empty()) { 4885de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood desired_network_.clear(); 4899f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_selected_network(""); 4909a24553461df7036755060423f90804011612249Eric Shienbrood LOG(INFO) << "Couldn't register on selected network, trying home network"; 4919a24553461df7036755060423f90804011612249Eric Shienbrood Register(callback); 4925de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood return; 4935de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 4949a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 495184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov} 496184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov 49731ce564d64f68172299d4cde60edd7a5c004b38eBen Chanbool CellularCapabilityGSM::IsRegistered() const { 498b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov return (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || 499b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING); 500b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov} 501b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov 5027fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbroodvoid CellularCapabilityGSM::SetUnregistered(bool searching) { 5037fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood // If we're already in some non-registered state, don't override that 5047fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood if (registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || 5057fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood registration_state_ == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) { 5067fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood registration_state_ = 5077fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood (searching ? MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING : 5087fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE); 5097fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood } 5107fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood} 5117fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood 512b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkovvoid CellularCapabilityGSM::RequirePIN( 513f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const std::string& pin, bool require, 514f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart Error* error, const ResultCallback& callback) { 5159a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(error); 5169a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->EnablePIN(pin, require, error, callback, kTimeoutDefault); 517b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov} 518b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov 519f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::EnterPIN(const string& pin, 520f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart Error* error, 521f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultCallback& callback) { 5229a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(error); 5239a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->SendPIN(pin, error, callback, kTimeoutDefault); 524b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov} 525b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov 526f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::UnblockPIN(const string& unblock_code, 527f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& pin, 528f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart Error* error, 529f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultCallback& callback) { 5309a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(error); 5319a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->SendPUK(unblock_code, pin, error, callback, kTimeoutDefault); 532b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov} 533b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov 534b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkovvoid CellularCapabilityGSM::ChangePIN( 535f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& old_pin, const string& new_pin, 536f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart Error* error, const ResultCallback& callback) { 5379a24553461df7036755060423f90804011612249Eric Shienbrood CHECK(error); 5389a24553461df7036755060423f90804011612249Eric Shienbrood card_proxy_->ChangePIN(old_pin, new_pin, error, callback, kTimeoutDefault); 539b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov} 540b05315fa7beab387bcbfd9330215aa50cdd6c8f4Darin Petkov 541f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::Scan(Error* error, 542f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultStringmapsCallback& callback) { 5439a24553461df7036755060423f90804011612249Eric Shienbrood ScanResultsCallback cb = Bind(&CellularCapabilityGSM::OnScanReply, 5449a24553461df7036755060423f90804011612249Eric Shienbrood weak_ptr_factory_.GetWeakPtr(), callback); 5459a24553461df7036755060423f90804011612249Eric Shienbrood network_proxy_->Scan(error, cb, kTimeoutScan); 5461272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov} 5471272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov 54849ffffd458c2407c67c2d0d572974e91c7e9bea7Prathmesh Prabhuvoid CellularCapabilityGSM::OnScanReply( 549f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const ResultStringmapsCallback& callback, 550f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const GSMScanResults& results, 551f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 5529f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu Stringmaps found_networks; 553f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart for (const auto& result : results) 55449ffffd458c2407c67c2d0d572974e91c7e9bea7Prathmesh Prabhu found_networks.push_back(ParseScanResult(result)); 55549ffffd458c2407c67c2d0d572974e91c7e9bea7Prathmesh Prabhu callback.Run(found_networks, error); 5561272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov} 5571272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov 558f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul StewartStringmap CellularCapabilityGSM::ParseScanResult(const GSMScanResult& result) { 5591272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov Stringmap parsed; 5605de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood for (GSMScanResult::const_iterator it = result.begin(); 5615de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood it != result.end(); ++it) { 5621272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov // TODO(petkov): Define these in system_api/service_constants.h. The 5631272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov // numerical values are taken from 3GPP TS 27.007 Section 7.3. 564f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart static const char* const kStatusString[] = { 5651272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "unknown", 5661272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "available", 5671272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "current", 5681272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "forbidden", 5691272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov }; 570f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart static const char* const kTechnologyString[] = { 5717ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan kNetworkTechnologyGsm, 5721272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "GSM Compact", 5737ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan kNetworkTechnologyUmts, 5747ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan kNetworkTechnologyEdge, 5751272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "HSDPA", 5761272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov "HSUPA", 5777ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan kNetworkTechnologyHspa, 5781272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov }; 579c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "Network property: " << it->first << " = " 580c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << it->second; 5811272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov if (it->first == kNetworkPropertyStatus) { 5821272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov int status = 0; 5831272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov if (base::StringToInt(it->second, &status) && 5841272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov status >= 0 && 5851272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov status < static_cast<int>(arraysize(kStatusString))) { 5867ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan parsed[kStatusProperty] = kStatusString[status]; 5871272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else { 5881272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov LOG(ERROR) << "Unexpected status value: " << it->second; 5891272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } 5901272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else if (it->first == kNetworkPropertyID) { 5917ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan parsed[kNetworkIdProperty] = it->second; 5921272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else if (it->first == kNetworkPropertyLongName) { 5937ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan parsed[kLongNameProperty] = it->second; 5941272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else if (it->first == kNetworkPropertyShortName) { 5957ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan parsed[kShortNameProperty] = it->second; 5961272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else if (it->first == kNetworkPropertyAccessTechnology) { 5971272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov int tech = 0; 5981272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov if (base::StringToInt(it->second, &tech) && 5991272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov tech >= 0 && 6001272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov tech < static_cast<int>(arraysize(kTechnologyString))) { 6017ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan parsed[kTechnologyProperty] = kTechnologyString[tech]; 6021272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else { 6031272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov LOG(ERROR) << "Unexpected technology value: " << it->second; 6041272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } 6051272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } else { 6061272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov LOG(WARNING) << "Unknown network property ignored: " << it->first; 6071272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } 6081272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } 6091272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov // If the long name is not available but the network ID is, look up the long 6101272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov // name in the mobile provider database. 6117ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan if ((!ContainsKey(parsed, kLongNameProperty) || 6127ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan parsed[kLongNameProperty].empty()) && 6137ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan ContainsKey(parsed, kNetworkIdProperty)) { 614afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu mobile_operator_info_->Reset(); 615afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu mobile_operator_info_->UpdateMCCMNC(parsed[kNetworkIdProperty]); 616afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu if (mobile_operator_info_->IsMobileNetworkOperatorKnown() && 617afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu !mobile_operator_info_->operator_name().empty()) { 618afe636676760df31a8db2f4b77bfd19faae52782Prathmesh Prabhu parsed[kLongNameProperty] = mobile_operator_info_->operator_name(); 6191272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } 6201272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov } 6211272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov return parsed; 6221272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov} 6231272a43bf73f6a99f51a6cc6345183aa503cfb67Darin Petkov 6247fab89734d88724a288e96a9996b15548c5294c7Ben Chanvoid CellularCapabilityGSM::SetAccessTechnology(uint32_t access_technology) { 625ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov access_technology_ = access_technology; 626ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov if (cellular()->service().get()) { 627b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov cellular()->service()->SetNetworkTechnology(GetNetworkTechnologyString()); 628ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov } 629ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov} 630ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov 63120c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkovstring CellularCapabilityGSM::GetNetworkTechnologyString() const { 632b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov switch (access_technology_) { 633b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_GSM: 634b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT: 6357ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kNetworkTechnologyGsm; 636b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_GPRS: 6377ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kNetworkTechnologyGprs; 638b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_EDGE: 6397ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kNetworkTechnologyEdge; 640b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_UMTS: 6417ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kNetworkTechnologyUmts; 642b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_HSDPA: 643b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_HSUPA: 644b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_HSPA: 6457ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kNetworkTechnologyHspa; 646b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov case MM_MODEM_GSM_ACCESS_TECH_HSPA_PLUS: 6477ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kNetworkTechnologyHspaPlus; 648b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov default: 649b72cf40dc315f9ae3537980f4fd85e737c125a03Darin Petkov break; 65020c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov } 65120c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov return ""; 65220c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov} 65320c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov 65420c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkovstring CellularCapabilityGSM::GetRoamingStateString() const { 655184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov switch (registration_state_) { 65620c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME: 6577ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kRoamingStateHome; 65820c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING: 6597ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kRoamingStateRoaming; 66020c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov default: 66120c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov break; 66220c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov } 6637ea768e15de860c8a27143ead02a8d3f15ab9f47Ben Chan return kRoamingStateUnknown; 66420c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov} 66520c13ec645faacb9c517fd2c574aa7fa30d890d0Darin Petkov 66605d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiuvoid CellularCapabilityGSM::OnPropertiesChanged( 667f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& interface, 66805d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu const KeyValueStore& properties, 669f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const vector<string>& invalidated_properties) { 67005d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu CellularCapabilityClassic::OnPropertiesChanged(interface, 67105d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties, 67205d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu invalidated_properties); 6737fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood if (interface == MM_MODEM_GSM_NETWORK_INTERFACE) { 67405d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu if (properties.ContainsUint(kPropertyAccessTechnology)) { 67505d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu SetAccessTechnology(properties.GetUint(kPropertyAccessTechnology)); 6767fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood } 677baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain } else { 6787fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood bool emit = false; 679baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain if (interface == MM_MODEM_GSM_CARD_INTERFACE) { 68005d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu if (properties.ContainsUint(kPropertyEnabledFacilityLocks)) { 68105d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu uint32_t locks = properties.GetUint(kPropertyEnabledFacilityLocks); 682baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain sim_lock_status_.enabled = locks & MM_MODEM_GSM_FACILITY_SIM; 683baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain emit = true; 684baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain } 685baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain } else if (interface == MM_MODEM_INTERFACE) { 68605d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu if (properties.ContainsString(kPropertyUnlockRequired)) { 68705d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu sim_lock_status_.lock_type = 68805d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties.GetString(kPropertyUnlockRequired); 689baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain emit = true; 690baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain } 69105d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu if (properties.ContainsUint(kPropertyUnlockRetries)) { 69205d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu sim_lock_status_.retries_left = 69305d87e34869f44473edc1eec25d2fe1110d777a7Peter Qiu properties.GetUint(kPropertyUnlockRetries); 694baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain emit = true; 695baeefdf544bfcfe2895e4e15c348db3f7ce4d45bGary Morain } 6967fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood } 6979f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu // TODO(pprabhu) Rename |emit| to |sim_present| after |sim_lock_status| 6989f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu // moves to cellular. 6997fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood if (emit) { 7009f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_sim_present(true); 7017fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood cellular()->adaptor()->EmitKeyValueStoreChanged( 702ea18c6c99743aeee9b2e544532ef9fe55dbd182dBen Chan kSIMLockStatusProperty, SimLockStatusToProperty(nullptr)); 7037fce52c4afdc5e73a9e740dc9b90f1e61ae8cea4Eric Shienbrood } 70463138a9b8249fd69c83a772ee3170551a589d57aDarin Petkov } 705ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov} 706ae0c64ea644748f28b7a320e9663f30cd69e344eDarin Petkov 7077fab89734d88724a288e96a9996b15548c5294c7Ben Chanvoid CellularCapabilityGSM::OnNetworkModeSignal(uint32_t /*mode*/) { 708184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov // TODO(petkov): Implement this. 709184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov NOTIMPLEMENTED(); 710184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov} 711184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov 7129a24553461df7036755060423f90804011612249Eric Shienbroodvoid CellularCapabilityGSM::OnRegistrationInfoSignal( 713f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart uint32_t status, const string& operator_code, const string& operator_name) { 714c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << ": regstate=" << status 715c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << ", opercode=" << operator_code 716c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein << ", opername=" << operator_name; 7179a24553461df7036755060423f90804011612249Eric Shienbrood registration_state_ = status; 7188599e052529c222da6cefd934bd52ceb9c194f5fPrathmesh Prabhu cellular()->serving_operator_info()->UpdateMCCMNC(operator_code); 7198599e052529c222da6cefd934bd52ceb9c194f5fPrathmesh Prabhu cellular()->serving_operator_info()->UpdateOperatorName(operator_name); 7209a24553461df7036755060423f90804011612249Eric Shienbrood cellular()->HandleNewRegistrationState(); 721184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov} 722184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov 7237fab89734d88724a288e96a9996b15548c5294c7Ben Chanvoid CellularCapabilityGSM::OnSignalQualitySignal(uint32_t quality) { 724184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov cellular()->HandleNewSignalQuality(quality); 725184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov} 726184c54e6091b21fc2a8ba40d8957ca6c84c37d6eDarin Petkov 7279a24553461df7036755060423f90804011612249Eric Shienbroodvoid CellularCapabilityGSM::OnGetRegistrationInfoReply( 728f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart uint32_t status, const string& operator_code, const string& operator_name, 729f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 7309a24553461df7036755060423f90804011612249Eric Shienbrood if (error.IsSuccess()) 7319a24553461df7036755060423f90804011612249Eric Shienbrood OnRegistrationInfoSignal(status, operator_code, operator_name); 7329a24553461df7036755060423f90804011612249Eric Shienbrood} 7339a24553461df7036755060423f90804011612249Eric Shienbrood 7347fab89734d88724a288e96a9996b15548c5294c7Ben Chanvoid CellularCapabilityGSM::OnGetSignalQualityReply(uint32_t quality, 735f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 7369a24553461df7036755060423f90804011612249Eric Shienbrood if (error.IsSuccess()) 7379a24553461df7036755060423f90804011612249Eric Shienbrood OnSignalQualitySignal(quality); 7389a24553461df7036755060423f90804011612249Eric Shienbrood} 7399a24553461df7036755060423f90804011612249Eric Shienbrood 740f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::OnGetIMEIReply(const ResultCallback& callback, 741f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& imei, 742f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 7435de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood if (error.IsSuccess()) { 744c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "IMEI: " << imei; 7459f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_imei(imei); 7465de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 747c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GetIMEI failed - " << error; 7485de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 7499a24553461df7036755060423f90804011612249Eric Shienbrood callback.Run(error); 7505de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 7515de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 752f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::OnGetIMSIReply(const ResultCallback& callback, 753f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& imsi, 754f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 7555de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood if (error.IsSuccess()) { 756c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "IMSI: " << imsi; 7579f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_imsi(imsi); 7589f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_sim_present(true); 7598599e052529c222da6cefd934bd52ceb9c194f5fPrathmesh Prabhu cellular()->home_provider_info()->UpdateIMSI(imsi); 760c93b6bc9b0fdb1a04240cca858a8f61add0a21e3Prathmesh Prabhu // We do not currently obtain the IMSI OTA at all. Provide the IMSI from the 761c93b6bc9b0fdb1a04240cca858a8f61add0a21e3Prathmesh Prabhu // SIM to the serving operator as well to aid in MVNO identification. 762c93b6bc9b0fdb1a04240cca858a8f61add0a21e3Prathmesh Prabhu cellular()->serving_operator_info()->UpdateIMSI(imsi); 76382a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain callback.Run(error); 76429505ec166c72afd3dee2317795ca13f7ff94e10Arman Uguray } else if (!sim_lock_status_.lock_type.empty()) { 765c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GetIMSI failed - SIM lock in place."; 7669f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_sim_present(true); 76729505ec166c72afd3dee2317795ca13f7ff94e10Arman Uguray callback.Run(error); 7685de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 7699f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_sim_present(false); 77082a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain if (get_imsi_retries_++ < kGetIMSIRetryLimit) { 771c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GetIMSI failed - " << error << ". Retrying"; 77282a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain base::Callback<void(void)> retry_get_imsi_cb = 77382a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain Bind(&CellularCapabilityGSM::GetIMSI, 77482a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain weak_ptr_factory_.GetWeakPtr(), callback); 77582a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain cellular()->dispatcher()->PostDelayedTask( 77682a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain retry_get_imsi_cb, 77782a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain get_imsi_retry_delay_milliseconds_); 77882a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain } else { 77982a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain LOG(INFO) << "GetIMSI failed - " << error; 7808599e052529c222da6cefd934bd52ceb9c194f5fPrathmesh Prabhu cellular()->home_provider_info()->Reset(); 78182a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain callback.Run(error); 78282a31a0323d2f7b72045e5ee6ef25f9a7dfbc3bbGary Morain } 7835de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 7845de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 7855de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 786f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::OnGetSPNReply(const ResultCallback& callback, 787f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& spn, 788f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 7895de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood if (error.IsSuccess()) { 790c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "SPN: " << spn; 7915de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood spn_ = spn; 7928599e052529c222da6cefd934bd52ceb9c194f5fPrathmesh Prabhu cellular()->home_provider_info()->UpdateOperatorName(spn); 7935de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 794c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GetSPN failed - " << error; 7955de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 796923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le callback.Run(error); 7975de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 7985de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 799f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewartvoid CellularCapabilityGSM::OnGetMSISDNReply(const ResultCallback& callback, 800f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const string& msisdn, 801f58b28e08efb9e3beccb993bc27dd68e0025a7daPaul Stewart const Error& error) { 8025de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood if (error.IsSuccess()) { 803c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "MSISDN: " << msisdn; 8049f06c870229b00cdd19224cb12c4202de65772aePrathmesh Prabhu cellular()->set_mdn(msisdn); 8055de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } else { 806c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << "GetMSISDN failed - " << error; 8075de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood } 808923006bc5f3fde53ea8651de16200d7226f065a2Thieu Le callback.Run(error); 8095de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood} 8105de44ab664b7cbb7619e31431e346ec8309548a6Eric Shienbrood 811daf4386a4775be7c965493749ccfe2fecc2e4167Darin Petkov} // namespace shill 812