Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AT_CellularNetwork.cpp Source File

AT_CellularNetwork.cpp

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include <stdlib.h>
00019 #include "AT_CellularNetwork.h"
00020 #include "CellularUtil.h"
00021 #include "CellularLog.h"
00022 #include "CellularCommon.h"
00023 #include "AT_CellularDevice.h"
00024 
00025 using namespace std;
00026 using namespace mbed_cellular_util;
00027 using namespace mbed;
00028 
00029 struct at_reg_t {
00030     const CellularNetwork::RegistrationType type;
00031     const char *const cmd;
00032     const char *const urc_prefix;
00033 };
00034 
00035 static const at_reg_t at_reg[] = {
00036     { CellularNetwork::C_EREG, "+CEREG", "+CEREG:"},
00037     { CellularNetwork::C_GREG, "+CGREG", "+CGREG:"},
00038     { CellularNetwork::C_REG,  "+CREG", "+CREG:"}
00039 };
00040 
00041 #if MBED_CONF_MBED_TRACE_ENABLE
00042 static const char *const reg_type_str[(int)AT_CellularNetwork::RegistrationStatusMax] = {
00043     "NotRegistered",
00044     "RegisteredHomeNetwork",
00045     "SearchingNetwork",
00046     "RegistrationDenied",
00047     "RegistrationUnknown",
00048     "RegisteredRoaming",
00049     "RegisteredSMSOnlyHome",
00050     "RegisteredSMSOnlyRoaming",
00051     "AttachedEmergencyOnly",
00052     "RegisteredCSFBNotPreferredHome",
00053     "RegisteredCSFBNotPreferredRoaming",
00054     "AlreadyRegistered"
00055 };
00056 
00057 static const char *const rat_str[AT_CellularNetwork::RAT_MAX] = {
00058     "GSM",
00059     "GSM_COMPACT",
00060     "UTRAN",
00061     "EGPRS",
00062     "HSDPA",
00063     "HSUPA",
00064     "HSDPA_HSUPA",
00065     "E_UTRAN",
00066     "CATM1",
00067     "NB1",
00068     "RAT unknown",
00069 };
00070 
00071 #endif
00072 
00073 
00074 AT_CellularNetwork::AT_CellularNetwork(ATHandler &atHandler, AT_CellularDevice &device) :
00075     _connection_status_cb(NULL), _ciotopt_network_support_cb(NULL), _op_act(RAT_UNKNOWN),
00076     _connect_status(NSAPI_STATUS_DISCONNECTED ), _supported_network_opt(CIOT_OPT_MAX),
00077     _at(atHandler), _device(device)
00078 {
00079     _urc_funcs[C_EREG] = callback(this, &AT_CellularNetwork::urc_cereg);
00080     _urc_funcs[C_GREG] = callback(this, &AT_CellularNetwork::urc_cgreg);
00081     _urc_funcs[C_REG] = callback(this, &AT_CellularNetwork::urc_creg);
00082 
00083     for (int type = 0; type < CellularNetwork::C_MAX; type++) {
00084         if (_device.get_property((AT_CellularDevice::CellularProperty)type) != RegistrationModeDisable) {
00085             _at.set_urc_handler(at_reg[type].urc_prefix, _urc_funcs[type]);
00086         }
00087     }
00088 
00089     if (_device.get_property(AT_CellularDevice::PROPERTY_AT_CGEREP)) {
00090         // additional urc to get better disconnect info for application. Not critical.
00091         _at.set_urc_handler("+CGEV: NW DET", callback(this, &AT_CellularNetwork::urc_cgev));
00092         _at.set_urc_handler("+CGEV: ME DET", callback(this, &AT_CellularNetwork::urc_cgev));
00093     }
00094 
00095 
00096     _at.set_urc_handler("+CCIOTOPTI:", callback(this, &AT_CellularNetwork::urc_cciotopti));
00097 }
00098 
00099 AT_CellularNetwork::~AT_CellularNetwork()
00100 {
00101     (void)set_packet_domain_event_reporting(false);
00102     for (int type = 0; type < CellularNetwork::C_MAX; type++) {
00103         if (_device.get_property((AT_CellularDevice::CellularProperty)type) != RegistrationModeDisable) {
00104             _at.set_urc_handler(at_reg[type].urc_prefix, 0);
00105         }
00106     }
00107 
00108     if (_device.get_property(AT_CellularDevice::PROPERTY_AT_CGEREP)) {
00109         _at.set_urc_handler("+CGEV: ME DET", 0);
00110         _at.set_urc_handler("+CGEV: NW DET", 0);
00111     }
00112     _at.set_urc_handler("+CCIOTOPTI:", 0);
00113 }
00114 
00115 void AT_CellularNetwork::urc_cgev()
00116 {
00117     call_network_cb(NSAPI_STATUS_DISCONNECTED );
00118 }
00119 
00120 void AT_CellularNetwork::read_reg_params_and_compare(RegistrationType type)
00121 {
00122     registration_params_t reg_params;
00123     read_reg_params(type, reg_params);
00124 
00125     if (_at.get_last_error() == NSAPI_ERROR_OK  && _connection_status_cb) {
00126         _reg_params._type = type;
00127         cell_callback_data_t data;
00128         data.error = NSAPI_ERROR_OK ;
00129         if (reg_params._act != _reg_params._act) {
00130             _reg_params._act = reg_params._act;
00131             data.status_data = reg_params._act;
00132             _connection_status_cb((nsapi_event_t)CellularRadioAccessTechnologyChanged, (intptr_t)&data);
00133         }
00134         if (reg_params._status != _reg_params._status) {
00135             RegistrationStatus previous_registration_status = _reg_params._status;
00136             _reg_params._status = reg_params._status;
00137             data.status_data = reg_params._status;
00138             _connection_status_cb((nsapi_event_t)CellularRegistrationStatusChanged, (intptr_t)&data);
00139             if (reg_params._status == NotRegistered) { // Other states means that we are trying to connect or connected
00140                 if (previous_registration_status == RegisteredHomeNetwork ||
00141                         previous_registration_status == RegisteredRoaming) {
00142                     if (type != C_REG) {// we are interested only if we drop from packet network
00143                         _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00144                     }
00145                 }
00146             }
00147         }
00148         if (reg_params._cell_id != -1 && reg_params._cell_id != _reg_params._cell_id) {
00149             _reg_params._cell_id = reg_params._cell_id;
00150             _reg_params._lac = reg_params._lac;
00151             data.status_data = reg_params._cell_id;
00152             _connection_status_cb((nsapi_event_t)CellularCellIDChanged, (intptr_t)&data);
00153         }
00154     }
00155 }
00156 
00157 void AT_CellularNetwork::urc_creg()
00158 {
00159     read_reg_params_and_compare(C_REG);
00160 }
00161 
00162 void AT_CellularNetwork::urc_cereg()
00163 {
00164     read_reg_params_and_compare(C_EREG);
00165 }
00166 
00167 void AT_CellularNetwork::urc_cgreg()
00168 {
00169     read_reg_params_and_compare(C_GREG);
00170 }
00171 
00172 void AT_CellularNetwork::call_network_cb(nsapi_connection_status_t status)
00173 {
00174     if (_connection_status_cb) {
00175         _connection_status_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , _connect_status);
00176     }
00177 }
00178 
00179 void AT_CellularNetwork::attach(Callback<void(nsapi_event_t, intptr_t)> status_cb)
00180 {
00181     _connection_status_cb = status_cb;
00182 }
00183 
00184 nsapi_error_t AT_CellularNetwork::set_registration_urc(RegistrationType type, bool urc_on)
00185 {
00186     int index = (int)type;
00187     MBED_ASSERT(index >= 0 && index < C_MAX);
00188 
00189     RegistrationMode mode = (RegistrationMode)_device.get_property((AT_CellularDevice::CellularProperty)type);
00190     if (mode == RegistrationModeDisable) {
00191         return NSAPI_ERROR_UNSUPPORTED ;
00192     } else {
00193         if (urc_on) {
00194             return _at.at_cmd_discard(at_reg[index].cmd, "=", "%d", mode);
00195         } else {
00196             return _at.at_cmd_discard(at_reg[index].cmd, "=0");
00197         }
00198     }
00199 }
00200 
00201 nsapi_error_t AT_CellularNetwork::get_network_registering_mode(NWRegisteringMode &mode)
00202 {
00203     int ret;
00204     nsapi_error_t error = _at.at_cmd_int("+COPS", "?", ret);
00205     mode = (NWRegisteringMode)ret;
00206     return error;
00207 }
00208 
00209 nsapi_error_t AT_CellularNetwork::set_registration(const char *plmn)
00210 {
00211 
00212     if (!plmn) {
00213         tr_debug("Automatic network registration");
00214         NWRegisteringMode mode;
00215         if (get_network_registering_mode(mode) != NSAPI_ERROR_OK ) {
00216             return NSAPI_ERROR_DEVICE_ERROR ;
00217         }
00218         if (mode != NWModeAutomatic) {
00219             return _at.at_cmd_discard("+COPS", "=0");
00220         }
00221         return NSAPI_ERROR_OK ;
00222     } else {
00223         tr_debug("Manual network registration to %s", plmn);
00224         if (_op_act != RAT_UNKNOWN) {
00225             return _at.at_cmd_discard("+COPS", "=1,2,", "%s%d", plmn, _op_act);
00226         } else {
00227             return _at.at_cmd_discard("+COPS", "=1,2,", "%s", plmn);
00228         }
00229     }
00230 }
00231 
00232 void AT_CellularNetwork::read_reg_params(RegistrationType type, registration_params_t &reg_params)
00233 {
00234     const int MAX_STRING_LENGTH = 9;
00235     char string_param[MAX_STRING_LENGTH] = {0};
00236 
00237     reg_params._type = type;
00238 
00239     int int_param = _at.read_int();
00240     reg_params._status = (int_param >= 0 && int_param < RegistrationStatusMax) ? (RegistrationStatus)int_param : NotRegistered;
00241 
00242     int len = _at.read_string(string_param, TWO_BYTES_HEX + 1);
00243     if (len > 0) {
00244         reg_params._lac = hex_str_to_int(string_param, TWO_BYTES_HEX);
00245     } else {
00246         reg_params._lac = -1;
00247     }
00248 
00249     len = _at.read_string(string_param, FOUR_BYTES_HEX + 1);
00250     if (len > 0) {
00251         reg_params._cell_id = hex_str_to_int(string_param, FOUR_BYTES_HEX);
00252     } else {
00253         reg_params._cell_id = -1;
00254     }
00255 
00256     int_param = _at.read_int();
00257     reg_params._act = (int_param >= 0 && int_param < RAT_MAX) ? (RadioAccessTechnology)int_param : RAT_UNKNOWN ;
00258 
00259     // Skip [<cause_type>],[<reject_cause>]
00260     _at.skip_param(2);
00261 
00262     len = _at.read_string(string_param, ONE_BYTE_BINARY + 1);
00263     reg_params._active_time = calculate_active_time(string_param, len);
00264 
00265     len = _at.read_string(string_param, ONE_BYTE_BINARY + 1);
00266     reg_params._periodic_tau = calculate_periodic_tau(string_param, len);
00267 
00268 #if MBED_CONF_MBED_TRACE_ENABLE
00269     tr_debug("%s %s, LAC %d, cell %d, %s", at_reg[(int)type].urc_prefix, reg_type_str[reg_params._status], reg_params._lac, reg_params._cell_id, rat_str[reg_params._act]);
00270 #endif
00271 }
00272 
00273 nsapi_error_t AT_CellularNetwork::set_attach()
00274 {
00275     _at.lock();
00276     AttachStatus status;
00277     get_attach(status);
00278 
00279     if (status == Detached) {
00280         tr_debug("Network attach");
00281         _at.at_cmd_discard("+CGATT", "=1");
00282     }
00283 
00284     return _at.unlock_return_error();
00285 }
00286 
00287 nsapi_error_t AT_CellularNetwork::get_attach(AttachStatus &status)
00288 {
00289     int attach_status;
00290     nsapi_error_t err = _at.at_cmd_int("+CGATT", "?", attach_status);
00291     status = (attach_status == 1) ? Attached : Detached;
00292 
00293     return err;
00294 }
00295 
00296 nsapi_error_t AT_CellularNetwork::detach()
00297 {
00298     _at.lock();
00299     tr_debug("Network detach");
00300     _at.at_cmd_discard("+CGATT", "=0");
00301 
00302     _at.at_cmd_discard("+COPS", "=2");
00303 
00304     call_network_cb(NSAPI_STATUS_DISCONNECTED );
00305 
00306     return _at.unlock_return_error();
00307 }
00308 
00309 nsapi_error_t AT_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
00310 {
00311     _op_act = RAT_UNKNOWN;
00312     return NSAPI_ERROR_UNSUPPORTED ;
00313 }
00314 
00315 nsapi_error_t AT_CellularNetwork::set_access_technology(RadioAccessTechnology opAct)
00316 {
00317     if (opAct == RAT_UNKNOWN) {
00318         return NSAPI_ERROR_UNSUPPORTED ;
00319     }
00320 
00321     _op_act = opAct;
00322 
00323     return set_access_technology_impl(opAct);
00324 }
00325 
00326 nsapi_error_t AT_CellularNetwork::scan_plmn(operList_t &operators, int &opsCount)
00327 {
00328     int idx = 0;
00329 
00330     _at.lock();
00331 
00332     _at.cmd_start_stop("+COPS", "=?");
00333 
00334     _at.resp_start("+COPS:");
00335 
00336     int ret, error_code = -1;
00337     operator_t *op = NULL;
00338 
00339     while (_at.info_elem('(')) {
00340 
00341         op = operators.add_new();
00342         op->op_status = (operator_t::Status)_at.read_int();
00343         _at.read_string(op->op_long, sizeof(op->op_long));
00344         _at.read_string(op->op_short, sizeof(op->op_short));
00345         _at.read_string(op->op_num, sizeof(op->op_num));
00346 
00347         // Optional - try read an int
00348         ret = _at.read_int();
00349         op->op_rat = (ret == error_code) ? RAT_UNKNOWN : (RadioAccessTechnology)ret;
00350 
00351         if ((_op_act == RAT_UNKNOWN) ||
00352                 ((op->op_rat != RAT_UNKNOWN) && (op->op_rat == _op_act))) {
00353             idx++;
00354         } else {
00355             operators.delete_last();
00356         }
00357     }
00358 
00359     _at.resp_stop();
00360 
00361     opsCount = idx;
00362     return _at.unlock_return_error();
00363 }
00364 
00365 nsapi_error_t AT_CellularNetwork::set_ciot_optimization_config(CIoT_Supported_Opt supported_opt,
00366                                                                CIoT_Preferred_UE_Opt preferred_opt,
00367                                                                Callback<void(CIoT_Supported_Opt)> network_support_cb)
00368 {
00369     _ciotopt_network_support_cb = network_support_cb;
00370     return _at.at_cmd_discard("+CCIOTOPT", "=1,", "%d%d", supported_opt, preferred_opt);
00371 }
00372 
00373 void AT_CellularNetwork::urc_cciotopti()
00374 {
00375     _supported_network_opt = (CIoT_Supported_Opt)_at.read_int();
00376 
00377     if (_ciotopt_network_support_cb) {
00378         _ciotopt_network_support_cb(_supported_network_opt);
00379     }
00380 }
00381 
00382 nsapi_error_t AT_CellularNetwork::get_ciot_ue_optimization_config(CIoT_Supported_Opt &supported_opt,
00383                                                                   CIoT_Preferred_UE_Opt &preferred_opt)
00384 {
00385     _at.lock();
00386 
00387     _at.cmd_start_stop("+CCIOTOPT", "?");
00388 
00389     _at.resp_start("+CCIOTOPT:");
00390     _at.read_int();
00391     if (_at.get_last_error() == NSAPI_ERROR_OK ) {
00392         supported_opt = (CIoT_Supported_Opt)_at.read_int();
00393         preferred_opt = (CIoT_Preferred_UE_Opt)_at.read_int();
00394     }
00395 
00396     _at.resp_stop();
00397 
00398     return _at.unlock_return_error();
00399 }
00400 
00401 nsapi_error_t AT_CellularNetwork::get_ciot_network_optimization_config(CIoT_Supported_Opt &supported_network_opt)
00402 {
00403     supported_network_opt = _supported_network_opt;
00404     return NSAPI_ERROR_OK ;
00405 }
00406 
00407 nsapi_error_t AT_CellularNetwork::get_signal_quality(int &rssi, int *ber)
00408 {
00409     _at.lock();
00410 
00411     _at.cmd_start_stop("+CSQ", "");
00412 
00413     _at.resp_start("+CSQ:");
00414     int t_rssi = _at.read_int();
00415     int t_ber = _at.read_int();
00416     _at.resp_stop();
00417     if (t_rssi < 0 || t_ber < 0) {
00418         _at.unlock();
00419         return NSAPI_ERROR_DEVICE_ERROR ;
00420     }
00421 
00422     // RSSI value is returned in dBm with range from -51 to -113 dBm, see 3GPP TS 27.007
00423     if (t_rssi == 99) {
00424         rssi = SignalQualityUnknown;
00425     } else {
00426         rssi = -113 + 2 * t_rssi;
00427     }
00428 
00429     if (ber) {
00430         if (t_ber == 99) {
00431             *ber = SignalQualityUnknown;
00432         } else {
00433             *ber = t_ber;
00434         }
00435     }
00436 
00437     return _at.unlock_return_error();
00438 }
00439 
00440 /** Get the last 3GPP error code
00441  *  @return see 3GPP TS 27.007 error codes
00442  */
00443 int AT_CellularNetwork::get_3gpp_error()
00444 {
00445     return _at.get_3gpp_error();
00446 }
00447 
00448 nsapi_error_t AT_CellularNetwork::get_operator_params(int &format, operator_t &operator_params)
00449 {
00450     _at.lock();
00451 
00452     _at.cmd_start_stop("+COPS", "?");
00453 
00454     _at.resp_start("+COPS:");
00455     _at.read_int(); //ignore mode
00456     format = _at.read_int();
00457 
00458     if (_at.get_last_error() == NSAPI_ERROR_OK ) {
00459         switch (format) {
00460             case 0:
00461                 _at.read_string(operator_params.op_long, sizeof(operator_params.op_long));
00462                 break;
00463             case 1:
00464                 _at.read_string(operator_params.op_short, sizeof(operator_params.op_short));
00465                 break;
00466             default:
00467                 _at.read_string(operator_params.op_num, sizeof(operator_params.op_num));
00468                 break;
00469         }
00470         operator_params.op_rat = (RadioAccessTechnology)_at.read_int();
00471     }
00472 
00473     _at.resp_stop();
00474 
00475     return _at.unlock_return_error();
00476 }
00477 
00478 nsapi_error_t AT_CellularNetwork::get_operator_names(operator_names_list &op_names)
00479 {
00480     _at.lock();
00481 
00482     _at.cmd_start_stop("+COPN", "");
00483 
00484     _at.resp_start("+COPN:");
00485     operator_names_t *names = NULL;
00486     while (_at.info_resp()) {
00487         names = op_names.add_new();
00488         _at.read_string(names->numeric, sizeof(names->numeric));
00489         _at.read_string(names->alpha, sizeof(names->alpha));
00490     }
00491 
00492     _at.resp_stop();
00493     return _at.unlock_return_error();
00494 }
00495 
00496 void AT_CellularNetwork::get_context_state_command()
00497 {
00498     _at.cmd_start_stop("+CGACT", "?");
00499     _at.resp_start("+CGACT:");
00500 }
00501 
00502 bool AT_CellularNetwork::is_active_context(int *number_of_active_contexts, int cid)
00503 {
00504     _at.lock();
00505 
00506     if (number_of_active_contexts) {
00507         *number_of_active_contexts = 0;
00508     }
00509     bool active_found = false;
00510     int context_id;
00511     // read active contexts
00512     get_context_state_command();
00513 
00514     while (_at.info_resp()) {
00515         context_id = _at.read_int(); // discard context id
00516         if (_at.read_int() == 1) { // check state
00517             tr_debug("Found active context");
00518             if (number_of_active_contexts) {
00519                 (*number_of_active_contexts)++;
00520             }
00521             if (cid == -1) {
00522                 active_found = true;
00523             } else if (context_id == cid) {
00524                 active_found = true;
00525             }
00526             if (!number_of_active_contexts && active_found) {
00527                 break;
00528             }
00529         }
00530     }
00531     _at.resp_stop();
00532     _at.unlock();
00533 
00534     return active_found;
00535 }
00536 
00537 nsapi_error_t AT_CellularNetwork::get_registration_params(registration_params_t &reg_params)
00538 {
00539     reg_params = _reg_params;
00540     return NSAPI_ERROR_OK ;
00541 }
00542 
00543 nsapi_error_t AT_CellularNetwork::get_registration_params(RegistrationType type, registration_params_t &reg_params)
00544 {
00545     int i = (int)type;
00546     MBED_ASSERT(i >= 0 && i < C_MAX);
00547 
00548     if (!_device.get_property((AT_CellularDevice::CellularProperty)at_reg[i].type)) {
00549         return NSAPI_ERROR_UNSUPPORTED ;
00550     }
00551 
00552     _at.lock();
00553 
00554     _at.cmd_start_stop(at_reg[i].cmd, "?");
00555 
00556     _at.resp_start(at_reg[i].urc_prefix);
00557     (void)_at.read_int(); // ignore urc mode subparam
00558     read_reg_params(type, reg_params);
00559     _at.resp_stop();
00560 
00561     _reg_params = reg_params;
00562 
00563     return _at.unlock_return_error();
00564 }
00565 
00566 int AT_CellularNetwork::calculate_active_time(const char *active_time_string, int active_time_length)
00567 {
00568     if (active_time_length != ONE_BYTE_BINARY) {
00569         return -1;
00570     }
00571 
00572     uint32_t ie_unit = binary_str_to_uint(active_time_string, TIMER_UNIT_LENGTH);
00573     uint32_t ie_value = binary_str_to_uint(active_time_string + TIMER_UNIT_LENGTH, active_time_length - TIMER_UNIT_LENGTH);
00574 
00575     switch (ie_unit) {
00576         case 0: // multiples of 2 seconds
00577             return 2 * ie_value;
00578         case 1: // multiples of 1 minute
00579             return 60 * ie_value;
00580         case 2: // multiples of decihours
00581             return 6 * 60 * ie_value;
00582         case 7: // timer is deactivated
00583             return 0;
00584         default: // other values shall be interpreted as multiples of 1 minute
00585             return 60 * ie_value;
00586     }
00587 }
00588 
00589 int AT_CellularNetwork::calculate_periodic_tau(const char *periodic_tau_string, int periodic_tau_length)
00590 {
00591     if (periodic_tau_length != ONE_BYTE_BINARY) {
00592         return -1;
00593     }
00594 
00595     uint32_t ie_unit = binary_str_to_uint(periodic_tau_string, TIMER_UNIT_LENGTH);
00596     uint32_t ie_value = binary_str_to_uint(periodic_tau_string + TIMER_UNIT_LENGTH, periodic_tau_length - TIMER_UNIT_LENGTH);
00597 
00598     switch (ie_unit) {
00599         case 0: // multiples of 10 minutes
00600             return 60 * 10 * ie_value;
00601         case 1: // multiples of 1 hour
00602             return 60 * 60 * ie_value;
00603         case 2: // multiples of 10 hours
00604             return 10 * 60 * 60 * ie_value;
00605         case 3: // multiples of 2 seconds
00606             return 2 * ie_value;
00607         case 4: // multiples of 30 seconds
00608             return 30 * ie_value;
00609         case 5: // multiples of 1 minute
00610             return 60 * ie_value;
00611         case 6: // multiples of 320 hours
00612             return 320 * 60 * 60 * ie_value;
00613         default: // timer is deactivated
00614             return 0;
00615     }
00616 }
00617 
00618 nsapi_error_t AT_CellularNetwork::set_receive_period(int mode, EDRXAccessTechnology act_type, uint8_t edrx_value)
00619 {
00620     char edrx[5];
00621     uint_to_binary_str(edrx_value, edrx, 5, 4);
00622     edrx[4] = '\0';
00623 
00624     return _at.at_cmd_discard("+CEDRXS", "=", "%d%d%s", mode, act_type, edrx);
00625 }
00626 
00627 nsapi_error_t AT_CellularNetwork::set_packet_domain_event_reporting(bool on)
00628 {
00629     if (!_device.get_property(AT_CellularDevice::PROPERTY_AT_CGEREP)) {
00630         return NSAPI_ERROR_UNSUPPORTED ;
00631     }
00632 
00633     return _at.at_cmd_discard("+CGEREP", "=", "%d", on ? 1 : 0);
00634 }
00635 
00636 nsapi_error_t AT_CellularNetwork::clear()
00637 {
00638     tr_info("AT_CellularNetwork::clear");
00639 
00640     _at.lock();
00641     _at.cmd_start_stop("+CGDCONT", "?");
00642     _at.resp_start("+CGDCONT:");
00643 
00644     struct context_s {
00645         int id;
00646         context_s *next;
00647     };
00648     CellularList<context_s> contexts;
00649     while (_at.info_resp()) {
00650         int cid = _at.read_int();
00651         // clear all but the default context
00652         if (cid <= 0) {
00653             continue;
00654         } else if (cid == 1) {
00655 #ifndef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
00656             continue;
00657 #else
00658             char pdp_type_from_context[10];
00659             int pdp_type_len = _at.read_string(pdp_type_from_context, sizeof(pdp_type_from_context));
00660             if (pdp_type_len > 0) {
00661                 char apn[MAX_ACCESSPOINT_NAME_LENGTH];
00662                 int apn_len = _at.read_string(apn, sizeof(apn));
00663                 if (apn_len >= 0) {
00664                     if (strcmp(apn, MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN) == 0) {
00665                         continue;
00666                     }
00667                 }
00668             }
00669 #endif
00670         }
00671         contexts.add_new()->id = cid;
00672     }
00673     _at.resp_stop();
00674 
00675     if (contexts.get_head()) {
00676         // try to detach from network before deleting contexts
00677         (void)detach();
00678         context_s *context = contexts.get_head();
00679         while (context) {
00680             if (_at.at_cmd_discard("+CGDCONT", "=", "%d", context->id) != NSAPI_ERROR_OK ) {
00681                 tr_warn("Clear context %d failed", context->id);
00682             }
00683             context = context->next;
00684         }
00685 #ifdef MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN
00686         char pdp_type_str[sizeof("IPV4V6")];
00687         if (_device.get_property(AT_CellularDevice::PROPERTY_IPV4V6_PDP_TYPE) ||
00688                 (_device.get_property(AT_CellularDevice::PROPERTY_IPV4_PDP_TYPE) && _device.get_property(AT_CellularDevice::PROPERTY_IPV6_PDP_TYPE))) {
00689             strcpy(pdp_type_str, "IPV4V6");
00690         } else if (_device.get_property(AT_CellularDevice::PROPERTY_IPV6_PDP_TYPE)) {
00691             strcpy(pdp_type_str, "IPV6");
00692         } else {
00693             strcpy(pdp_type_str, "IP");
00694         }
00695         _at.at_cmd_discard("+CGDCONT", "=", "%d%s%s", 1, pdp_type_str, MBED_CONF_NSAPI_DEFAULT_CELLULAR_APN);
00696 #endif
00697     }
00698 
00699     return _at.unlock_return_error();
00700 }
00701 
00702 ATHandler &AT_CellularNetwork::get_at_handler()
00703 {
00704     return _at;
00705 }