Initial commit
[platform/core/telephony/tel-plugin-atdongle.git] / src / desc-atdongle.c
1 /*
2  * tel-plugin-atdongle
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <glib.h>
26
27 #include <tcore.h>
28 #include <server.h>
29 #include <plugin.h>
30 #include <core_object.h>
31 #include <hal.h>
32 #include <at.h>
33
34 #include "atd_modem.h"
35 #include "atd_sim.h"
36 #include "atd_network.h"
37 #include "atd_ps.h"
38
39 #define STATUS_INFO_RESP                "CPAS"
40
41 static void __initialize_device_retry(TcorePlugin *plugin);
42
43 static TReturn __send_at_request_immediately(CoreObject *co,
44         const char *at_cmd,
45         const char *at_cmd_prefix,
46         enum tcore_at_command_type at_cmd_type,
47         UserRequest *ur,
48         TcorePendingResponseCallback resp_cb,
49         void *resp_cb_data,
50         TcorePendingSendCallback send_cb,
51         void *send_cb_data,
52         unsigned int timeout,
53         TcorePendingTimeoutCallback timeout_cb,
54         void *timeout_cb_data)
55 {
56         TcorePending *pending = NULL;
57         TcoreATRequest *req = NULL;
58         TcoreHal *hal = NULL;
59         TReturn ret = TCORE_RETURN_FAILURE;
60
61         hal = tcore_object_get_hal(co);
62         if (!hal) {
63                 dbg("HAL is NULL");
64                 return ret;
65         }
66         dbg("hal: [0x%x]", hal);
67
68         /* Create Pending Request */
69         pending = tcore_pending_new(co, 0);
70         if (!pending) {
71                 dbg("Pending is NULL");
72                 return ret;
73         }
74
75         /* Create AT-Command Request */
76         req = tcore_at_request_new(at_cmd, at_cmd_prefix, at_cmd_type);
77         if (req == NULL) {
78                 dbg("Request is NULL");
79                 tcore_pending_free(pending);
80                 return ret;
81         }
82         dbg("AT Command: [%s], Prefix(if any): [%s], AT-Command length: [%d]",
83                         req->cmd, req->prefix, strlen(req->cmd));
84
85         tcore_pending_set_request_data(pending, 0, req);
86         tcore_pending_set_response_callback(pending, resp_cb, resp_cb_data);
87         tcore_pending_set_send_callback(pending, send_cb, send_cb_data);
88         tcore_pending_set_priority(pending, TCORE_PENDING_PRIORITY_HIGH);
89         tcore_pending_set_timeout(pending, timeout);
90         tcore_pending_set_timeout_callback(pending, timeout_cb, timeout_cb_data);
91         tcore_pending_link_user_request(pending, ur);
92
93         ret = tcore_hal_send_request(hal, pending);
94         dbg("ret: [0x%x]", ret);
95         return ret;
96 }
97
98 static void on_response_sync_for_resp(TcorePending *p,
99         int data_len, const void *data, void *user_data)
100 {
101         const TcoreATResponse *at_resp = data;
102         gboolean ret = FALSE;
103
104         if (at_resp && at_resp->success) {
105                 dbg("Received - [Success]");
106                 /* tty device works successfully. proceed */
107                 /* Modem Power on */
108                 ret = modem_power_on(user_data);
109                 dbg("Modem Power ON: [%s]", (ret == TRUE ? "SUCCESS" : "FAIL"));
110         } else
111                 err("Received - [Fail]");
112 }
113
114 static void __sync_for_resp(TcorePlugin *plugin)
115 {
116         CoreObject *co_modem;
117         TReturn ret;
118
119         if (plugin == NULL) {
120                 err("Invalid plugin !");
121                 return;
122         }
123
124         /* Modem Core object */
125         co_modem = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
126
127         /* Some Dongle returns late response
128          * due to its late initialize.
129          *
130          * Send 'meaningless' command
131          * and sync sequence AT response for unexpected response */
132         ret = __send_at_request_immediately(co_modem,
133                 "\n", NULL,
134                 TCORE_AT_NO_RESULT,
135                 NULL,
136                 on_response_sync_for_resp, plugin,
137                 NULL, NULL,
138                 0, NULL, NULL);
139
140         dbg("ret: [0x%x]", ret);
141 }
142
143 static void on_timeout_initialize_device(TcorePending *p, void *user_data)
144 {
145         dbg("Timeout! pending:[%p]", p);
146         dbg(" Try another command to tty device again..");
147
148         /* When AT device doesn't responded with 'AT+CPAS' command,
149          * need to send 'AT' command and check its response..
150          */
151         __initialize_device_retry(user_data);
152 }
153
154 static void on_response_initialize_device(TcorePending *p,
155         int data_len, const void *data, void *user_data)
156 {
157         const TcoreATResponse *at_resp = data;
158         gboolean ret = FALSE;
159
160         if (at_resp && at_resp->success) {
161                 GSList *lines;
162                 const char *line;
163                 gboolean expected = FALSE;
164
165                 dbg("Initialize for AT device - [Success] / Lines: %d",
166                         g_slist_length(at_resp->lines));
167
168                 lines = at_resp->lines;
169                 while (lines) {
170                         line = (const char *)lines->data;
171
172                         /* Check if response contains 'CPAS' - valid response */
173                         if (g_strrstr(line, STATUS_INFO_RESP)) {
174                                 expected = TRUE;
175                                 break;
176                         }
177
178                         /* Move to next line */
179                         lines = lines->next;
180                 }
181
182                 /* Send empty command and wait for valid response */
183                 if (expected == FALSE) {
184                         TcorePlugin *plugin = tcore_pending_ref_plugin(p);
185                         dbg("Response contains unexpected lines.");
186                         dbg("Sync AT response");
187                         __sync_for_resp(plugin);
188                 } else {
189                         /* tty device works successfully. proceed */
190                         /* Modem Power on */
191                         ret = modem_power_on(user_data);
192                         dbg("Modem Power ON: [%s]", (ret == TRUE ? "SUCCESS" : "FAIL"));
193                 }
194         } else {
195                 dbg("Initialize for AT device - [Failed]");
196         }
197 }
198
199 static void on_response_initialize_device_retry(TcorePending *p,
200         int data_len, const void *data, void *user_data)
201 {
202         const TcoreATResponse *at_resp = data;
203         gboolean ret = FALSE;
204
205         if (at_resp && at_resp->success) {
206                 GSList *lines;
207                 const char *line;
208                 gboolean unexpected = FALSE;
209
210                 dbg("Initialize for AT device - [Success] / Lines: %d",
211                         g_slist_length(at_resp->lines));
212
213                 lines = at_resp->lines;
214                 while (lines) {
215                         line = (const char *)lines->data;
216
217                         /* Check if response contains 'CPAS' - invalid response */
218                         if (g_strrstr(line, STATUS_INFO_RESP)) {
219                                 unexpected = TRUE;
220                                 break;
221                         }
222
223                         /* Move to next line */
224                         lines = lines->next;
225                 }
226
227                 /* Send empty command and wait for valid response */
228                 if (unexpected) {
229                         TcorePlugin *plugin = tcore_pending_ref_plugin(p);
230                         dbg("Response contains unexpected lines.");
231                         dbg("Sync AT response");
232                         __sync_for_resp(plugin);
233                 } else {
234                         /* tty device works successfully. proceed */
235                         /* Modem Power on */
236                         ret = modem_power_on(user_data);
237                         dbg("Modem Power ON: [%s]", (ret == TRUE ? "SUCCESS" : "FAIL"));
238                 }
239         } else {
240                 dbg("Initialize for AT device - [Failed]");
241         }
242 }
243
244 static void __initialize_device(TcorePlugin *plugin)
245 {
246         CoreObject *co_modem;
247         TReturn ret;
248
249         if (plugin == NULL) {
250                 err("Invalid plugin !");
251                 return;
252         }
253
254         /* Modem Core object */
255         co_modem = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
256
257         /* Send command and set timeout to 5 sec */
258         ret = tcore_prepare_and_send_at_request(co_modem,
259                 "AT+CPAS", NULL,
260                 TCORE_AT_MULTILINE,
261                 NULL,
262                 on_response_initialize_device, plugin,
263                 NULL, NULL,
264                 5, on_timeout_initialize_device, plugin);
265
266         dbg("ret: [0x%x]", ret);
267 }
268
269 static void __initialize_device_retry(TcorePlugin *plugin)
270 {
271         CoreObject *co_modem;
272         TReturn ret;
273
274         if (plugin == NULL) {
275                 err("Invalid plugin !");
276                 return;
277         }
278
279         /* Modem Core object */
280         co_modem = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
281
282         /* Send 'AT' command and set timeout to 5 sec */
283         ret = tcore_prepare_and_send_at_request(co_modem,
284                 "AT", NULL,
285                 TCORE_AT_MULTILINE,
286                 NULL,
287                 on_response_initialize_device_retry, plugin,
288                 NULL, NULL,
289                 5, on_timeout_initialize_device, plugin);
290
291         dbg("ret: [0x%x]", ret);
292 }
293
294 /**< Initializer Table */
295 struct object_initializer init_table = {
296         .modem_init = atd_modem_init,
297         .sim_init = atd_sim_init,
298         .network_init = atd_network_init,
299         .ps_init = atd_ps_init,
300         .sat_init = NULL,
301         .sap_init = NULL,
302         .call_init = NULL,
303         .ss_init = NULL,
304         .sms_init = NULL,
305         .phonebook_init = NULL,
306         .gps_init = NULL,
307 };
308
309 /**< Deinitializer Table */
310 struct object_deinitializer deinit_table = {
311         .modem_deinit = atd_modem_exit,
312         .sim_deinit = atd_sim_exit,
313         .ps_deinit = atd_ps_exit,
314         .network_deinit = atd_network_exit,
315         .sat_deinit = NULL,
316         .sap_deinit = NULL,
317         .call_deinit = NULL,
318         .ss_deinit = NULL,
319         .sms_deinit = NULL,
320         .phonebook_deinit = NULL,
321         .gps_deinit = NULL,
322 };
323
324 static gboolean on_load()
325 {
326         dbg("Load!!!");
327
328         return TRUE;
329 }
330
331 static gboolean on_init(TcorePlugin *p)
332 {
333         dbg("Init!!!");
334
335         if (p == NULL) {
336                 err("invalid plugin!!");
337                 return FALSE;
338         }
339
340         /* Initialize Modules (Core Objects) */
341         if (tcore_object_init_objects(p, &init_table)
342                         != TCORE_RETURN_SUCCESS) {
343                 err("Failed to initialize Core Objects");
344                 return FALSE;
345         }
346
347         /* Initialize tty device */
348         __initialize_device(p);
349
350         dbg("Init - Complete!");
351
352         return TRUE;
353 }
354
355 static void on_unload(TcorePlugin *p)
356 {
357         dbg("Unload!!!");
358
359         /* Deinitialize Modules (Core Objects) */
360         tcore_object_deinit_objects(p, &deinit_table);
361 }
362
363 /* AT Dongle - Modem Plug-in Descriptor */
364 struct tcore_plugin_define_desc plugin_define_desc = {
365         .name = "ATDONGLE",
366         .priority = TCORE_PLUGIN_PRIORITY_MID,
367         .version = 1,
368         .load = on_load,
369         .init = on_init,
370         .unload = on_unload
371 };