4 * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hayoon Ko <hayoon.ko@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
26 #define FEATURE_SAMSUNG_ONEDRAM
30 #include <core_object.h>
34 #include <co_network.h>
39 #include "s_network.h"
40 #include "atchannel.h"
43 extern struct ATResponse *sp_response;
44 extern char *s_responsePrefix;
45 extern enum ATCommandType s_type;
47 #define AT_CREG_STAT_NOT_REG 0 /* not registered, MT is not currently searching a new operator to register to */
48 #define AT_CREG_STAT_REG_HOME 1 /* registered, home network */
49 #define AT_CREG_STAT_SEARCHING 2 /* not registered, but MT is currently searching a new operator to register to */
50 #define AT_CREG_STAT_REG_DENIED 3 /* registration denied */
51 #define AT_CREG_STAT_UNKNOWN 4 /* unknown */
52 #define AT_CREG_STAT_REG_ROAM 5 /* registered, roaming */
54 static unsigned int lookup_tbl_net_status[] = {
55 [AT_CREG_STAT_NOT_REG] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
56 [AT_CREG_STAT_REG_HOME] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
57 [AT_CREG_STAT_SEARCHING] = NETWORK_SERVICE_DOMAIN_STATUS_SEARCH,
58 [AT_CREG_STAT_REG_DENIED] = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY,
59 [AT_CREG_STAT_UNKNOWN] = NETWORK_SERVICE_DOMAIN_STATUS_NO,
60 [AT_CREG_STAT_REG_ROAM] = NETWORK_SERVICE_DOMAIN_STATUS_FULL,
63 #define AT_COPS_MODE_AUTOMATIC 0 /* automatic (<oper> field is ignored) */
64 #define AT_COPS_MODE_MANUAL 1 /* manual (<oper> field shall be present, and <AcT> optionally) */
65 #define AT_COPS_MODE_DEREGISTER 2 /* deregister from network */
66 #define AT_COPS_MODE_SET_ONLY 3 /* set only <format> */
68 #define AT_COPS_FORMAT_LONG_ALPHANUMERIC 0 /* long format alphanumeric <oper> */
69 #define AT_COPS_FORMAT_SHORT_ALPHANUMERIC 1 /* short format alphanumeric <oper> */
70 #define AT_COPS_FORMAT_NUMERIC 2 /* numeric <oper> */
72 #define AT_COPS_ACT_GSM 0 /* GSM */
73 #define AT_COPS_ACT_GSM_COMPACT 1 /* GSM Compact */
74 #define AT_COPS_ACT_UTRAN 2 /* UTRAN */
75 #define AT_COPS_ACT_GSM_EGPRS 3 /* GSM w/EGPRS */
76 #define AT_COPS_ACT_UTRAN_HSDPA 4 /* UTRAN w/HSDPA */
77 #define AT_COPS_ACT_UTRAN_HSUPA 5 /* UTRAN w/HSUPA */
78 #define AT_COPS_ACT_UTRAN_HSDPA_HSUPA 6 /* UTRAN w/HSDPA and HSUPA */
79 #define AT_COPS_ACT_E_UTRAN 7 /* E-UTRAN */
81 static unsigned int lookup_tbl_access_technology[] = {
82 [AT_COPS_ACT_GSM] = NETWORK_ACT_GSM,
83 [AT_COPS_ACT_GSM_COMPACT] = NETWORK_ACT_GSM,
84 [AT_COPS_ACT_UTRAN] = NETWORK_ACT_UTRAN,
85 [AT_COPS_ACT_GSM_EGPRS] = NETWORK_ACT_EGPRS,
86 [AT_COPS_ACT_UTRAN_HSDPA] = NETWORK_ACT_UTRAN,
87 [AT_COPS_ACT_UTRAN_HSUPA] = NETWORK_ACT_UTRAN,
88 [AT_COPS_ACT_UTRAN_HSDPA_HSUPA] = NETWORK_ACT_UTRAN,
89 [AT_COPS_ACT_E_UTRAN] = NETWORK_ACT_GSM_UTRAN,
91 static unsigned int current_lac=0;
92 static gboolean get_serving_network(CoreObject *o, UserRequest *ur);
93 static void on_confirmation_network_message_send( TcorePending *pending, gboolean result, void *user_data );
95 static void __set_metainfo(UserRequest *ur, struct ATReqMetaInfo *info, enum ATCommandType type, char *prefix)
99 memset(info, 0, sizeof(struct ATReqMetaInfo));
102 info->responsePrefix[0] ='\0';
104 memcpy(info->responsePrefix, prefix, strlen(prefix));
105 tcore_user_request_set_metainfo(ur, sizeof(struct ATReqMetaInfo), info);
107 static void __send_at_request(CoreObject *o, char* atcmd, UserRequest *ur, TcorePendingResponseCallback func)
109 TcorePlugin *plugin = NULL;
110 TcoreHal *hal = NULL;
111 TcorePending *pending = NULL;
113 plugin = tcore_object_ref_plugin(o);
114 hal = tcore_plugin_ref_hal(plugin);
116 pending = tcore_pending_new(o, ID_RESERVED_AT);
117 tcore_pending_set_request_data(pending, strlen(atcmd), atcmd);
118 tcore_pending_set_timeout(pending, 0);
119 tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_DEFAULT);
120 tcore_pending_set_response_callback(pending, func, NULL);
121 tcore_pending_link_user_request(pending, ur);
123 tcore_pending_set_send_callback(pending, on_confirmation_network_message_send, NULL);
125 tcore_hal_send_request(hal, pending);
128 static void _insert_mcc_mnc_oper_list(TcorePlugin *plugin, CoreObject *o)
133 char query[255] = { 0, };
136 GHashTable *result = NULL, *row = NULL;
137 struct tcore_network_operator_info *noi = NULL;
140 s = tcore_plugin_ref_server(plugin);
141 strg = tcore_server_find_storage(s, "database");
143 handle = tcore_storage_create_handle(strg, "/opt/dbspace/.mcc_mnc_oper_list.db");
145 dbg("fail to create database handle");
149 snprintf(query, 255, "select country, mcc, mnc, oper from mcc_mnc_oper_list");
151 result = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
152 (GDestroyNotify) g_hash_table_destroy);
154 tcore_storage_read_query_database(strg, handle, query, NULL, result, 4);
156 g_hash_table_iter_init(&iter, result);
157 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
160 noi = calloc(sizeof(struct tcore_network_operator_info), 1);
162 snprintf(noi->mcc, 4, "%s",(const gchar *)(g_hash_table_lookup(row, "1")));
163 snprintf(noi->mnc, 4, "%s",(const gchar *)(g_hash_table_lookup(row, "2")));
164 snprintf(noi->name, 41, "%s",(const gchar *)(g_hash_table_lookup(row, "3")));
165 snprintf(noi->country, 4, "%s",(const gchar *)(g_hash_table_lookup(row, "0")));
167 tcore_network_operator_info_add(o, noi);
172 dbg("count = %d", count);
174 g_hash_table_destroy(result);
176 tcore_storage_remove_handle(strg, handle);
180 static gboolean _is_cdma(int act)
183 case NETWORK_ACT_IS95A:
184 case NETWORK_ACT_IS95B:
185 case NETWORK_ACT_CDMA_1X:
186 case NETWORK_ACT_EVDO_REV0:
187 case NETWORK_ACT_CDMA_1X_EVDO_REV0:
188 case NETWORK_ACT_EVDO_REVA:
189 case NETWORK_ACT_CDMA_1X_EVDO_REVA:
190 case NETWORK_ACT_EVDV:
198 static enum telephony_network_service_type _get_service_type(enum telephony_network_service_type prev_type,
199 int domain, int act, int cs_status, int ps_status)
201 enum telephony_network_service_type ret;
206 case NETWORK_ACT_NOT_SPECIFIED:
207 ret = NETWORK_SERVICE_TYPE_UNKNOWN;
210 case NETWORK_ACT_GSM:
211 if (prev_type == NETWORK_SERVICE_TYPE_2_5G_EDGE && domain == NETWORK_SERVICE_DOMAIN_CS)
212 ret = NETWORK_SERVICE_TYPE_2_5G_EDGE;
214 ret = NETWORK_SERVICE_TYPE_2G;
217 case NETWORK_ACT_IS95A:
218 case NETWORK_ACT_IS95B:
219 ret = NETWORK_SERVICE_TYPE_2G;
222 case NETWORK_ACT_CDMA_1X:
223 case NETWORK_ACT_GPRS:
224 ret = NETWORK_SERVICE_TYPE_2_5G;
227 case NETWORK_ACT_EGPRS:
228 return NETWORK_SERVICE_TYPE_2_5G_EDGE;
231 case NETWORK_ACT_UMTS:
232 ret = NETWORK_SERVICE_TYPE_3G;
235 case NETWORK_ACT_EVDO_REV0:
236 case NETWORK_ACT_CDMA_1X_EVDO_REV0:
237 case NETWORK_ACT_EVDO_REVA:
238 case NETWORK_ACT_CDMA_1X_EVDO_REVA:
239 case NETWORK_ACT_EVDV:
240 ret = NETWORK_SERVICE_TYPE_3G;
244 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO && ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) {
245 ret = NETWORK_SERVICE_TYPE_NO_SERVICE;
247 else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_SEARCH) {
248 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
252 ret = NETWORK_SERVICE_TYPE_SEARCH;
255 else if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY) {
256 if (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL || ps_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
260 ret = NETWORK_SERVICE_TYPE_EMERGENCY;
267 static void _ps_set(TcorePlugin *plugin, int status)
269 GSList *co_list = NULL;
271 co_list = tcore_plugin_get_core_objects_bytype(plugin, CORE_OBJECT_TYPE_PS);
273 CoreObject *o = NULL;
274 o = (CoreObject *) co_list->data;
278 if (status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
279 tcore_ps_set_online(o, TRUE);
282 tcore_ps_set_online(o, FALSE);
284 } while ((co_list = g_slist_next(co_list)));
286 g_slist_free(co_list);
289 static TReturn _network_general_response_result(void)
291 if (sp_response->success > 0) {
293 return TCORE_RETURN_SUCCESS;
298 line = sp_response->finalResponse;
299 ret = at_tok_start(&line);
301 err("err cause not specified or string corrupted");
303 return TCORE_RETURN_3GPP_ERROR;
306 ret = at_tok_nextint(&line, &error);
308 err("err not specified or string not contail error");
310 return TCORE_RETURN_3GPP_ERROR;
315 return convertCMEError((enum ATCMEError)error);
321 static void on_confirmation_network_message_send( TcorePending *pending, gboolean result, void *user_data )
323 UserRequest* ur = NULL;
324 struct ATReqMetaInfo* metainfo = NULL;
325 unsigned int info_len =0;
326 dbg("AT msg goes out from queue. Allocate ATRsp buffer and write rspPrefix\n");
329 sp_response = at_response_new();
331 ur = tcore_pending_ref_user_request(pending);
332 metainfo = (struct ATReqMetaInfo*)tcore_user_request_ref_metainfo(ur,&info_len);
334 if ((metainfo->type == SINGLELINE) || (metainfo->type == MULTILINE)) {
335 s_responsePrefix = strdup(metainfo->responsePrefix);
336 dbg("duplicating responsePrefix : %s\n", s_responsePrefix);
339 s_responsePrefix = NULL;
342 s_type = metainfo->type;
344 if (result == FALSE) {
352 static void on_response_set_plmn_selection_mode(TcorePending *pending, int data_len, const void *data, void *user_data)
355 struct tresp_network_set_plmn_selection_mode resp;
359 resp.result = _network_general_response_result();
361 ur = tcore_pending_ref_user_request(pending);
363 tcore_user_request_send_response(ur, TRESP_NETWORK_SET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_set_plmn_selection_mode), &resp);
367 static void on_response_get_plmn_selection_mode(TcorePending *pending, int data_len, const void *data, void *user_data)
370 struct tresp_network_get_plmn_selection_mode resp = {0};
377 if (sp_response->success > 0) {
379 line = sp_response->p_intermediates->line;
380 ret = at_tok_start(&line);
384 ret = at_tok_nextint(&line,&mode);
388 dbg("mode = %d", mode);
390 case AT_COPS_MODE_AUTOMATIC:
391 resp.mode = NETWORK_SELECT_MODE_GLOBAL_AUTOMATIC;
393 case AT_COPS_MODE_MANUAL:
394 resp.mode = NETWORK_SELECT_MODE_GSM_MANUAL;
403 dbg("resp.mode = %d", resp.mode);
404 ur = tcore_pending_ref_user_request(pending);
406 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_PLMN_SELECTION_MODE, sizeof(struct tresp_network_get_plmn_selection_mode), &resp);
410 static void on_response_search_network(TcorePending *pending, int data_len, const void *data, void *user_data)
413 struct tresp_network_search resp;
417 memset(&resp, 0, sizeof(struct tresp_network_search));
419 if (sp_response->success > 0) {
421 line = sp_response->p_intermediates->line;
422 ret = at_tok_start(&line);
425 while(at_tok_hasmore(&line))
428 * +COPS: [list of supported (<stat>,long alphanumeric <oper>,short alphanumeric <oper>,numeric <oper>[,<AcT>])s]
429 * [,,(list of supported <mode>s),(list of supported <format>s)]
435 dbg("line0 %s", line);
436 at_tok_skip_bracket(&line);
437 for (p = line ; *p != ')' ;p++) {
442 /* <stat>: integer type */
443 ret = at_tok_nextint(&line,&stat);
447 /* long alphanumeric <oper> */
448 ret = at_tok_nextstr(&line,&oper);
452 /* short alphanumeric <oper> */
453 ret = at_tok_nextstr(&line,&oper);
458 /* [NOTICE] struct "tresp_network_search" only supports numeric type */
459 ret = at_tok_nextstr(&line,&oper);
464 /* [,<AcT>]: integer type; access technology selected */
465 ret = at_tok_nextint(&line,&AcT);
470 dbg("mode = %d, oper=%s, AcT=%d", stat, oper?oper:"null", AcT);
471 resp.list[i].status = stat;
472 resp.list[i].act = lookup_tbl_access_technology[AcT];
473 memcpy(resp.list[i].plmn, oper, 6);
474 if (resp.list[i].plmn[5] == '#')
475 resp.list[i].plmn[5] = '\0';
477 dbg("resp.list[%d].act = 0x%x, resp.list[%d].plmn=%s", i, resp.list[i].act, i, resp.list[i].plmn);
481 dbg("resp.list_count=%d", resp.list_count);
482 ur = tcore_pending_ref_user_request(pending);
484 tcore_user_request_send_response(ur, TRESP_NETWORK_SEARCH, sizeof(struct tresp_network_search), &resp);
494 static void on_response_get_serving_network(TcorePending *pending, int data_len, const void *data, void *user_data)
497 struct tresp_network_get_serving_network resp;
500 enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
503 /* AT parsing variable */
505 int mode=0, format=0, AcT=0;
508 if (sp_response->success > 0) {
510 line = sp_response->p_intermediates->line;
511 ret = at_tok_start(&line);
515 ret = at_tok_nextint(&line,&mode);
519 ret = at_tok_nextint(&line,&format);
523 ret = at_tok_nextstr(&line,&oper);
527 ret = at_tok_nextint(&line,&AcT);
531 dbg("mode = %d, format=%d, oper=%s, AcT=%d\n", mode, format, oper, AcT);
534 memcpy(plmn, oper, 6);
538 o = tcore_pending_ref_core_object(pending);
540 tcore_network_set_plmn(o, plmn);
541 tcore_network_get_access_technology(o, &act);
542 dbg("prev_act = 0x%x, new_act = 0x%x", act,lookup_tbl_access_technology[AcT]);
543 act = lookup_tbl_access_technology[AcT];
544 tcore_network_set_access_technology(o, act);
546 if (_is_cdma(act) == FALSE) {
547 tcore_network_set_lac(o, current_lac);
550 memcpy(resp.plmn, plmn, 6);
552 resp.gsm.lac = current_lac;
553 ur = tcore_pending_ref_user_request(pending);
555 tcore_user_request_send_response(ur, TRESP_NETWORK_GET_SERVING_NETWORK, sizeof(struct tresp_network_get_serving_network), &resp);
558 struct tnoti_network_change network_change;
560 memset(&network_change, 0, sizeof(struct tnoti_network_change));
561 memcpy(network_change.plmn, plmn, 6);
563 network_change.act = act;
564 network_change.gsm.lac = current_lac;
566 tcore_server_send_notification(tcore_plugin_ref_server(tcore_pending_ref_plugin(pending)), tcore_pending_ref_core_object(pending),
567 TNOTI_NETWORK_CHANGE, sizeof(struct tnoti_network_change), &network_change);
577 static void on_event_network_regist(CoreObject *o, const void *event_info, void *user_data)
579 struct tnoti_network_registration_status regist_status;
580 enum telephony_network_service_domain_status cs_status;
581 enum telephony_network_service_domain_status ps_status;
582 enum telephony_network_service_type service_type;
583 enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
585 char *line = (char *)event_info;
587 unsigned char svc_domain;
589 unsigned int lac=0, ci=0, rac=0;
591 dbg("NOTI RECEIVED");
594 if (strStartsWith(line,"+CREG:"))
595 svc_domain = NETWORK_SERVICE_DOMAIN_CS;
597 else if (strStartsWith(line,"+CGREG:"))
598 svc_domain = NETWORK_SERVICE_DOMAIN_PS;
602 dbg("svc_domain = 0x%x", svc_domain);
604 ret = at_tok_start(&line);
606 AT_NOTI_TOK_ERROR(line);
608 ret = at_tok_nextint(&line, &stat);
612 ret = at_tok_nexthexint(&line, (int *)&lac);
616 dbg("Found lac=0x%x",lac);
617 /* <stat> 1 : registered, home network */
618 /* 5 : registered, roaming */
619 if ( stat==1 || stat==5 )
623 ret = at_tok_nexthexint(&line, (int *)&ci);
627 dbg("Found ci=0x%x", ci);
629 ret = at_tok_nextint(&line, (int *)&AcT);
633 if (svc_domain == NETWORK_SERVICE_DOMAIN_PS) {
634 ret = at_tok_nexthexint(&line, (int *)&rac);
638 dbg("Found rac=0x%x", rac);
641 * <lac>: string type; two byte location area code or tracking area code in hexadecimal format
642 * <tac>: string type; two byte tracking area code in hexadecimal format (for +CEREG:)
643 * <ci>: string type; four byte GERAN/UTRAN/E-UTRAN cell ID in hexadecimal format
644 * <rac>: string type; one byte routing area code in hexadecimal format
648 dbg("stat=%d, lac=0x%lx, ci=0x%lx, Act=%d, rac=0x%lx", stat, lac, ci, AcT, rac);
650 switch (svc_domain) {
651 case NETWORK_SERVICE_DOMAIN_CS:
652 cs_status = lookup_tbl_net_status[stat];
653 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, cs_status);
656 case NETWORK_SERVICE_DOMAIN_PS:
657 ps_status = lookup_tbl_net_status[stat];
658 tcore_network_set_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, ps_status);
660 _ps_set(tcore_object_ref_plugin(o), ps_status);
664 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
665 tcore_network_get_service_status(o, TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status);
667 act = lookup_tbl_access_technology[AcT];
668 tcore_network_set_access_technology(o, act);
670 if (stat == AT_CREG_STAT_REG_ROAM)
671 tcore_network_set_roaming_state(o, TRUE);
673 tcore_network_set_roaming_state(o, FALSE);
675 tcore_network_get_service_type(o, &service_type);
676 dbg("prev_service_type = 0x%x", service_type);
677 service_type = _get_service_type(service_type, svc_domain, act, cs_status, ps_status);
678 dbg("new_service_type = 0x%x", service_type);
679 tcore_network_set_service_type(o, service_type);
681 tcore_network_set_lac(o, lac);
682 tcore_network_set_rac(o, rac);
683 tcore_network_set_cell_id(o, ci);
685 if (_is_cdma(act) == FALSE) {
686 struct tnoti_network_location_cellinfo net_lac_cell_info;
687 net_lac_cell_info.lac = lac;
688 net_lac_cell_info.cell_id = ci;
690 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_LOCATION_CELLINFO,
691 sizeof(struct tnoti_network_location_cellinfo), &net_lac_cell_info);
694 regist_status.cs_domain_status = cs_status;
695 regist_status.ps_domain_status = ps_status;
696 regist_status.service_type = service_type;
697 regist_status.roaming_status = tcore_network_get_roaming_state(o);
699 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o,
700 TNOTI_NETWORK_REGISTRATION_STATUS, sizeof(struct tnoti_network_registration_status), ®ist_status);
702 get_serving_network(o, NULL);
705 static void on_event_network_icon_info(CoreObject *o, const void *event_info, void *user_data)
707 char *line = (char *)event_info;
708 static struct tnoti_network_icon_info net_icon_info = {0xff,0,0,0};
712 #define CIND_NOTI_RSSI 10
713 #define CIND_NOTI_BATTERY 15
715 ret = at_tok_start(&line);
717 AT_NOTI_TOK_ERROR(line);
719 ret = at_tok_nextint(&line, &descr);
721 AT_NOTI_TOK_ERROR(line);
723 ret = at_tok_nextint(&line, &ind);
725 AT_NOTI_TOK_ERROR(line);
729 dbg("CIND_NOTI_RSSI. ind=%d",ind);
730 net_icon_info.rssi = ind;
732 case CIND_NOTI_BATTERY:
733 dbg("CIND_NOTI_BATTERY. ind=%d",ind);
734 net_icon_info.battery = ind;
738 err("This event is not handled val=%d",descr);
741 dbg("type=%d, rssi=%d, battery=%d, hdr_rssi=%d",
742 net_icon_info.type, net_icon_info.rssi, net_icon_info.battery, net_icon_info.hdr_rssi);
743 tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(o)), o, TNOTI_NETWORK_ICON_INFO,
744 sizeof(struct tnoti_network_icon_info), &net_icon_info);
747 static void on_sim_resp_hook_get_netname(UserRequest *ur, enum tcore_response_command command, unsigned int data_len,
748 const void *data, void *user_data)
750 const struct tresp_sim_read *resp = data;
751 CoreObject *o = user_data;
753 if (command == TRESP_SIM_GET_SPN) {
754 dbg("OK SPN GETTING!!");
755 dbg("resp->result = 0x%x", resp->result);
756 dbg("resp->data.spn.display_condition = 0x%x", resp->data.spn.display_condition);
757 dbg("resp->data.spn.spn = [%s]", resp->data.spn.spn);
759 tcore_network_set_network_name(o, TCORE_NETWORK_NAME_TYPE_SPN, (const char *)resp->data.spn.spn);
763 * bit[0]: 0 = display of registered PLMN name not required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
764 * 1 = display of registered PLMN name required when registered PLMN is either HPLMN or a PLMN in the service provider PLMN list
765 * bit[1]: 0 = display of the service provider name is required when registered PLMN is neither HPLMN nor a PLMN in the service provider PLMN list
766 * 1 = display of the service provider name is not required when registered PLMN is neither HPLMN nor a PLMN in the service provider PLMN list
768 if (resp->data.spn.display_condition & 0x01) {
769 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
771 if ((resp->data.spn.display_condition & 0x02) == 0) {
772 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_SPN);
774 if ((resp->data.spn.display_condition & 0x03) == 0x01) {
775 tcore_network_set_network_name_priority(o, TCORE_NETWORK_NAME_PRIORITY_ANY);
780 static enum tcore_hook_return on_hook_sim_init(Server *s, CoreObject *source, enum tcore_notification_command command,
781 unsigned int data_len, void *data, void *user_data)
783 const struct tnoti_sim_status *sim = data;
784 UserRequest *ur = NULL;
786 if (sim->sim_status == SIM_STATUS_INIT_COMPLETED) {
787 ur = tcore_user_request_new(NULL, NULL);
788 tcore_user_request_set_command(ur, TREQ_SIM_GET_SPN);
789 tcore_user_request_set_response_hook(ur, on_sim_resp_hook_get_netname, user_data);
790 tcore_object_dispatch_request(source, ur);
793 return TCORE_HOOK_RETURN_CONTINUE;
796 static TReturn search_network(CoreObject *o, UserRequest *ur)
798 /* AT command variable*/
799 struct ATReqMetaInfo metainfo;
803 return TCORE_RETURN_EINVAL;
805 __set_metainfo(ur, &metainfo, SINGLELINE,"+COPS:");
807 atcmd = g_strdup("AT+COPS=?\r");
808 dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",atcmd, "N/A", strlen(atcmd));
810 __send_at_request(o, atcmd, ur, on_response_search_network);
813 return TCORE_RETURN_SUCCESS;
816 static TReturn set_plmn_selection_mode(CoreObject *o, UserRequest *ur)
818 const struct treq_network_set_plmn_selection_mode *req_data;
820 /* AT command variable*/
821 struct ATReqMetaInfo metainfo;
826 return TCORE_RETURN_EINVAL;
828 req_data = tcore_user_request_ref_data(ur, NULL);
829 __set_metainfo(ur, &metainfo, NO_RESULT, NULL);
831 if (req_data->mode != NETWORK_SELECT_MODE_GSM_MANUAL) {
832 /* AT_COPS_MODE_AUTOMATIC 0*/
833 atcmd = g_strdup("AT+COPS=0\r");
837 memcpy(plmn, req_data->plmn, 6);
839 if (strlen(req_data->plmn) == 5) {
842 /* AT_COPS_MODE_MANUAL 1*/
843 /* AT_COPS_FORMAT_NUMERIC 2*/
844 atcmd = g_strdup_printf("AT+COPS=0%s\r", plmn);
846 dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",atcmd, "N/A", strlen(atcmd));
848 __send_at_request(o, atcmd, ur, on_response_set_plmn_selection_mode);
851 return TCORE_RETURN_SUCCESS;
855 static TReturn get_plmn_selection_mode(CoreObject *o, UserRequest *ur)
857 /* AT command variable*/
858 struct ATReqMetaInfo metainfo;
862 return TCORE_RETURN_EINVAL;
864 __set_metainfo(ur, &metainfo, SINGLELINE,"+COPS:");
866 atcmd = g_strdup("AT+COPS?\r");
867 dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",atcmd, "N/A", strlen(atcmd));
869 __send_at_request(o, atcmd, ur, on_response_get_plmn_selection_mode);
872 return TCORE_RETURN_SUCCESS;
875 static TReturn set_service_domain(CoreObject *o, UserRequest *ur)
877 dbg("set_service_domain is not supported!");
878 return TCORE_RETURN_SUCCESS;
881 static TReturn get_service_domain(CoreObject *o, UserRequest *ur)
883 dbg("get_service_domain is not supported!");
884 return TCORE_RETURN_SUCCESS;
887 static TReturn set_band(CoreObject *o, UserRequest *ur)
889 dbg("set_band is not supported!");
890 return TCORE_RETURN_SUCCESS;
893 static TReturn get_band(CoreObject *o, UserRequest *ur)
895 dbg("get_band is not supported!");
896 return TCORE_RETURN_SUCCESS;
899 static TReturn set_preferred_plmn(CoreObject *o, UserRequest *ur)
901 dbg("set_preferred_plmn is not supported!");
902 return TCORE_RETURN_SUCCESS;
905 static TReturn get_preferred_plmn(CoreObject *o, UserRequest *ur)
907 dbg("get_preferred_plmn is not supported!");
908 return TCORE_RETURN_SUCCESS;
911 static TReturn set_order(CoreObject *o, UserRequest *ur)
913 dbg("set_order is not supported!");
914 return TCORE_RETURN_SUCCESS;
917 static TReturn get_order(CoreObject *o, UserRequest *ur)
919 dbg("get_order is not supported!");
920 return TCORE_RETURN_SUCCESS;
923 static TReturn set_power_on_attach(CoreObject *o, UserRequest *ur)
925 dbg("set_power_on_attach is not supported!");
926 return TCORE_RETURN_SUCCESS;
929 static TReturn get_power_on_attach(CoreObject *o, UserRequest *ur)
931 dbg("get_power_on_attach is not supported!");
932 return TCORE_RETURN_SUCCESS;
935 static TReturn set_cancel_manual_search(CoreObject *o, UserRequest *ur)
937 dbg("set_cancel_manual_search is not supported!");
938 return TCORE_RETURN_SUCCESS;
941 static TReturn get_serving_network(CoreObject *o, UserRequest *ur)
943 /* AT command variable*/
944 struct ATReqMetaInfo metainfo;
948 return TCORE_RETURN_EINVAL;
951 ur = tcore_user_request_new(NULL, NULL);
953 __set_metainfo(ur, &metainfo, SINGLELINE,"+COPS:");
955 atcmd = g_strdup("AT+COPS?\r");
956 dbg("cmd : %s, prefix(if any) : %s, cmd_len : %d",atcmd, "N/A", strlen(atcmd));
958 __send_at_request(o, atcmd, ur, on_response_get_serving_network);
960 return TCORE_RETURN_SUCCESS;
965 static struct tcore_network_operations network_ops = {
966 .search = search_network,
967 .set_plmn_selection_mode = set_plmn_selection_mode,
968 .get_plmn_selection_mode = get_plmn_selection_mode,
969 .set_service_domain = set_service_domain,
970 .get_service_domain = get_service_domain,
971 .set_band = set_band,
972 .get_band = get_band,
973 .set_preferred_plmn = set_preferred_plmn,
974 .get_preferred_plmn = get_preferred_plmn,
975 .set_order = set_order,
976 .get_order = get_order,
977 .set_power_on_attach = set_power_on_attach,
978 .get_power_on_attach = get_power_on_attach,
979 .set_cancel_manual_search = set_cancel_manual_search,
980 .get_serving_network = get_serving_network,
983 gboolean s_network_init(TcorePlugin *plugin)
987 o = tcore_network_new(plugin, "umts_network", &network_ops);
991 tcore_object_add_callback(o, EVENT_NETWORK_REGISTRATION, on_event_network_regist, NULL);
992 tcore_object_add_callback(o, EVENT_NETWORK_ICON_INFO, on_event_network_icon_info, NULL);
994 tcore_server_add_notification_hook(tcore_plugin_ref_server(plugin), TNOTI_SIM_STATUS, on_hook_sim_init, o);
996 _insert_mcc_mnc_oper_list(plugin, o);
1001 void s_network_exit(TcorePlugin *plugin)
1005 o = tcore_plugin_ref_core_object(plugin, "umts_network");
1007 tcore_network_free(o);