2 * tel-plugin-at_standard
4 * Copyright (c) 2012 Intel Corporation. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #include <core_object.h>
35 #include <co_context.h>
39 enum pdp_context_state {
44 static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
45 enum pdp_context_state state);
47 static void on_confirmation_ps_message_send(TcorePending *p, gboolean result,
50 dbg("msg out from queue");
52 dbg("Sending %s", (result == TRUE) ? "OK" : "FAIL");
55 static void notify_context_deactivated(CoreObject *co_ps,
56 CoreObject *ps_context)
58 struct tnoti_ps_call_status data_resp = {0};
59 unsigned int cid = tcore_context_get_id(ps_context);
64 data_resp.context_id = cid;
65 data_resp.state = TELEPHONY_GPRS_DATA_STATUS_NOCARRIER;
68 server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
70 tcore_server_send_notification(server, co_ps, TNOTI_PS_CALL_STATUS,
71 sizeof(struct tnoti_ps_call_status),
77 static void on_setup_netif(CoreObject *co_ps, const char *netif_name,
80 CoreObject *ps_context = user_data;
81 struct tnoti_ps_call_status data_status = {0};
86 dbg("devname = [%s]", netif_name);
88 if (tcore_util_netif_up(netif_name) != TCORE_RETURN_SUCCESS) {
89 err("util_netif_up() failed.");
90 set_pdp_context(co_ps, ps_context, DEACTIVATE);
94 tcore_context_set_ipv4_devname(ps_context, netif_name);
96 server = tcore_plugin_ref_server(tcore_object_ref_plugin(co_ps));
98 data_status.context_id = tcore_context_get_id(ps_context);
99 data_status.state = TELEPHONY_GPRS_DATA_STATUS_CONNECTED;
100 data_status.result = 0;
102 tcore_server_send_notification(server, co_ps,
103 TNOTI_PS_CALL_STATUS,
104 sizeof(struct tnoti_ps_call_status),
110 static void on_response_get_pdp_address(TcorePending *p, int data_len,
111 const void *data, void *user_data)
113 CoreObject *co_ps = tcore_pending_ref_core_object(p);
114 CoreObject *ps_context = user_data;
115 TcoreHal *h = tcore_object_get_hal(co_ps);
116 GSList *tokens = NULL;
117 const TcoreATResponse *resp = data;
120 char *real_pdp_address;
121 int cid = tcore_context_get_id(ps_context);
125 if (NULL == resp->final_response) {
132 if (NULL == resp->lines) {
133 err("Invalid response line");
137 line = (const char *)resp->lines->data;
138 tokens = tcore_at_tok_new(line);
139 if (g_slist_length(tokens) < 2) {
140 err("Invalid message");
144 dbg("Line: %s", line);
146 /* Skip CID & read directly IP address */
147 pdp_address = g_slist_nth_data(tokens, 1);
148 real_pdp_address = tcore_at_tok_extract(pdp_address);
150 tcore_context_set_ipv4_addr(ps_context, real_pdp_address);
152 dbg("PDP address: %s", real_pdp_address);
154 g_free(real_pdp_address);
156 dbg("Adding default DNS");
158 tcore_context_set_ipv4_dns(ps_context, "8.8.8.8", "8.8.4.4");
160 if (tcore_hal_setup_netif(h, co_ps, on_setup_netif, ps_context, cid)
161 == TCORE_RETURN_SUCCESS)
165 err("Failed to get PDP address deactivating context...");
166 set_pdp_context(co_ps, ps_context, DEACTIVATE);
170 tcore_at_tok_free(tokens);
175 static void get_pdp_address(CoreObject *co_ps, CoreObject *ps_context)
177 char *cmd_str = NULL;
178 unsigned int cid = tcore_context_get_id(ps_context);
182 cmd_str = g_strdup_printf("AT+CGPADDR=%d", cid);
184 if (tcore_prepare_and_send_at_request(co_ps, cmd_str, NULL,
185 TCORE_AT_NO_RESULT, NULL,
186 on_response_get_pdp_address,
188 on_confirmation_ps_message_send, NULL)
189 != TCORE_RETURN_SUCCESS) {
190 err("Failed to prepare and send AT request");
191 set_pdp_context(co_ps, ps_context, DEACTIVATE);
199 static void on_response_set_pdp_context_activate(TcorePending *p, int data_len,
203 CoreObject *co_ps = tcore_pending_ref_core_object(p);
204 const TcoreATResponse *resp = data;
205 CoreObject *ps_context = user_data;
211 get_pdp_address(co_ps, ps_context);
213 /* TODO: Manage CME errors */
215 notify_context_deactivated(co_ps, ps_context);
221 static TReturn set_pdp_context(CoreObject *co_ps, CoreObject *ps_context,
222 enum pdp_context_state state)
224 char *cmd_str = NULL;
225 unsigned int cid = tcore_context_get_id(ps_context);
226 int ret = TCORE_RETURN_SUCCESS;
227 TcorePendingResponseCallback cb = NULL;
228 gboolean activate = (state == ACTIVATE);
232 dbg("CID %d %s", cid, activate ? "activation" : "deactivation");
234 if (activate == TRUE)
235 cb = on_response_set_pdp_context_activate;
237 return TCORE_RETURN_ENOSYS;
239 cmd_str = g_strdup_printf("AT+CGACT=%d,%d", activate ? 1 : 0, cid);
241 if (tcore_prepare_and_send_at_request(co_ps, cmd_str, NULL,
242 TCORE_AT_NO_RESULT, NULL,
244 on_confirmation_ps_message_send, NULL)
245 != TCORE_RETURN_SUCCESS) {
246 err("Failed to prepare and send AT request");
247 notify_context_deactivated(co_ps, ps_context);
248 ret = TCORE_RETURN_FAILURE;
258 static void on_response_define_pdp_context(TcorePending *p, int data_len,
262 const TcoreATResponse *resp = data;
263 CoreObject *ps_context = user_data;
264 CoreObject *co_ps = tcore_pending_ref_core_object(p);
270 set_pdp_context(co_ps, ps_context, ACTIVATE);
273 notify_context_deactivated(co_ps, ps_context);
279 static TReturn define_pdp_context(CoreObject *co_ps, CoreObject *ps_context)
282 char *cmd_str = NULL;
283 char *pdp_type_str = NULL;
285 enum co_context_type pdp_type;
286 enum co_context_d_comp d_comp;
287 enum co_context_h_comp h_comp;
288 int ret = TCORE_RETURN_FAILURE;
292 pdp_type = tcore_context_get_type(ps_context);
293 cid = tcore_context_get_id(ps_context);
296 case CONTEXT_TYPE_X25:
297 dbg("CONTEXT_TYPE_X25");
298 pdp_type_str = g_strdup("X.25");
301 case CONTEXT_TYPE_IP:
302 dbg("CONTEXT_TYPE_IP");
303 pdp_type_str = g_strdup("IP");
306 case CONTEXT_TYPE_PPP:
307 dbg("CONTEXT_TYPE_PPP");
308 pdp_type_str = g_strdup("PPP");
311 case CONTEXT_TYPE_IPV6:
312 dbg("CONTEXT_TYPE_IPV6");
313 pdp_type_str = g_strdup("IPV6");
317 /* PDP Type not supported supported */
318 err("Unsupported PDP type %d ", pdp_type);
323 d_comp = tcore_context_get_data_compression(ps_context);
324 h_comp = tcore_context_get_header_compression(ps_context);
325 apn = tcore_context_get_apn(ps_context);
327 cmd_str = g_strdup_printf("AT+CGDCONT=%d,\"%s\",\"%s\",,%d,%d", cid,
328 pdp_type_str, apn, d_comp, h_comp);
330 ret = tcore_prepare_and_send_at_request(co_ps, cmd_str, NULL,
331 TCORE_AT_NO_RESULT, NULL,
332 on_response_define_pdp_context,
334 on_confirmation_ps_message_send, NULL);
336 g_free(pdp_type_str);
340 if (ret == TCORE_RETURN_SUCCESS)
343 err("Failed to prepare and send AT request");
346 notify_context_deactivated(co_ps, ps_context);
355 static TReturn activate_ps_context(CoreObject *co_ps, CoreObject *ps_context,
358 return define_pdp_context(co_ps, ps_context);
361 static TReturn deactivate_ps_context(CoreObject *co_ps, CoreObject *ps_context,
364 return TCORE_RETURN_ENOSYS;
367 static struct tcore_ps_operations ps_ops = {
368 .activate_context = activate_ps_context,
369 .deactivate_context = deactivate_ps_context
372 gboolean at_ps_init(TcorePlugin *p)
376 co_ps = tcore_ps_new(p, "umts_ps", &ps_ops, NULL);
383 void at_ps_exit(TcorePlugin *p)
387 co_ps = tcore_plugin_ref_core_object(p, "umts_ps");
391 tcore_ps_free(co_ps);