Updated SIM interface
[gsmd2.git] / vendor / wavecom-900e.c
blob10ea46a3dcc40ae94980a928c1085f7ebb3930cb
1 /*
2 * wavecom-900e.c
4 * Copyright(C) 2007,2008 Ixonos Plc
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Boston, MA 02111.
22 * Written by
23 * Vesa Pikki
24 * Heikki Paajanen
27 #include <termios.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <stdlib.h>
32 #include <glib.h>
33 #include <glib/gstdio.h>
35 #include "../src/modem.h"
36 #include "../src/utils.h"
37 #include "../src/call_interface.h"
38 #include "../src/at_error.h"
39 #include "../src/sim.h"
41 enum {
42 ENABLE_WIND = VENDOR_COMMAND
44 enum {
45 SYMBOL_WIND = VENDOR_SYMBOL
49 static void wavecom_unsolicite_handler_init (ModemInterface* modem,
50 VendorInterface *vendor);
51 static AtCommandHandlerStatus wavecom_unsolicite_handler (ModemInterface* modem,
52 AtCommandContext *at,
53 GString *response);
55 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor);
57 static AtCommandHandlerStatus wavecom_call_initiate_handler(ModemInterface *modem,
58 AtCommandContext *at,
59 GString *response);
60 static const AtCommand
61 commands[] = {
62 //Vendor command
63 { ENABLE_WIND, "AT+WIND=50\r\n", 100, TRUE, 1,
64 NULL,NULL }
65 }, *command_p = commands;
67 static const SymbolTable
68 symbols[] = {
69 { "WIND", SYMBOL_WIND, },//vendor command
70 { NULL, 0, },
71 }, *symbol_p = symbols;
73 typedef struct _Vendor {
74 ModemInterface *modem;
75 void (*orig_sim_auth_status) (SIMIPCInterface *sim_ipc,
76 const char *status);
78 AtCommandHandlerStatus (*orig_call_initiate_handler) (ModemInterface *modem,
79 AtCommandContext *at,
80 GString *response);
81 } Vendor;
83 static Vendor *vendor_priv = NULL;
85 static
86 AtCommandHandlerStatus wavecom_handler_query_pin_status (ModemInterface *modem,
87 AtCommandContext *at,
88 GString *response);
90 /** vendor_handle_init should be called from modem.c when the lib loaded*/
91 gboolean vendor_handle_init (VendorInterface *vendor, ModemInterface* modem)
93 if ( vendor_priv ) {
94 g_warning("%s : Already initialized!", __func__);
95 return FALSE;
97 vendor_priv = g_new0(Vendor, 1);
98 g_debug("%s", __func__);
99 vendor->init_at = NULL;
100 vendor->init_at_sim_ready = vendor_at_init_sim_ready;
101 vendor->priv = (gpointer)vendor_priv;
102 wavecom_unsolicite_handler_init (modem, vendor);
103 vendor_priv->modem = modem;
105 AtCommand *call_initiate = gsmd_modem_get_command(modem, INITIATE_CALL);
106 vendor_priv->orig_call_initiate_handler = call_initiate->handler;
107 call_initiate->handler = &wavecom_call_initiate_handler;
109 AtCommand *query_pin = gsmd_modem_get_command(modem, PIN_QUERY);
110 query_pin->handler = &wavecom_handler_query_pin_status;
113 return TRUE;
115 /*************************************/
119 * @brief Handler to modems response from queryPinStatus command
121 * @param modem modem whose response to handle
122 * @return true if responses were recognized
124 static
125 AtCommandHandlerStatus wavecom_handler_query_pin_status (ModemInterface *modem,
126 AtCommandContext *at,
127 GString *response)
129 g_debug("%s",__func__);
130 GScanner* scanner = modem->scanner;
134 if (gsmd_utils_send_error_from_response(at,
135 scanner,
136 "ERROR READING PIN STATUS",
137 "TIMEOUT READING PIN STATUS"))
138 return AT_HANDLER_DONE_ERROR;
140 if (scanner->token != '+') {
141 return AT_HANDLER_DONT_UNDERSTAND;
144 g_scanner_get_next_token (scanner);
145 switch (scanner->token) {
147 case SYMBOL_CME:
148 g_scanner_get_next_token (scanner);
149 //g_scanner_get_next_token (scanner);
150 if (scanner->token == SYMBOL_ERROR) {
151 g_scanner_peek_next_token(scanner);
152 if (scanner->next_token == ':') {
153 g_scanner_get_next_token (scanner);
154 g_scanner_get_next_token(scanner);//arrive error value
155 if ( ERR_NO_SIM_CARD == scanner->value.v_int ) {
156 gsmd_sim_change_auth_status(modem,
157 at->ipc_data,
158 SIM_MISSING,
159 "SIM MISSING",
160 TRUE);
161 } else {
162 gsmd_sim_change_auth_status(modem,
163 at->ipc_data,
164 SIM_ERROR,
165 "SIM ERROR",
166 TRUE);
169 return AT_HANDLER_DONE;
170 } else {
171 g_scanner_unexp_token (scanner, ':', NULL, "symbol",
172 NULL, NULL, TRUE);
175 } else {
176 g_scanner_unexp_token (scanner, SYMBOL_ERROR, NULL, "symbol",
177 NULL, NULL, TRUE);
179 break;
180 case SYMBOL_CPIN:
181 g_scanner_get_next_token (scanner);//get ':'
182 g_scanner_get_next_token (scanner);
183 if (scanner->token == SYMBOL_READY) {
184 g_debug("%s: READY",__func__);
185 gsmd_sim_change_auth_status(modem,
186 at->ipc_data,
187 SIM_READY,
188 "READY",
189 TRUE);
192 return AT_HANDLER_DONE;
194 } else if (scanner->token == SYMBOL_SIM) {
196 g_scanner_get_next_token (scanner);
197 g_scanner_peek_next_token(scanner);
198 if (scanner->token == SYMBOL_PIN) {
199 gsmd_sim_change_auth_status(modem,
200 at->ipc_data,
201 SIM_NEED_PIN,
202 "SIM PIN",
203 TRUE);
204 } else if (scanner->token == SYMBOL_PUK) {
205 g_debug("%s: SIM PUK",__func__);
206 gsmd_sim_change_auth_status(modem,
207 at->ipc_data,
208 SIM_NEED_PUK,
209 "SIM PUK",
210 TRUE);
213 return AT_HANDLER_DONE;
214 } else {
215 g_scanner_unexp_token (scanner, SYMBOL_READY, NULL, "symbol",
216 NULL, NULL, TRUE);
218 break;
219 default:
220 g_warning("No match after getting + \n");
221 break;
228 return AT_HANDLER_DONT_UNDERSTAND;
232 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor)
234 ModemInterface *modem = vendor_priv->modem;
235 g_assert(modem);
236 g_debug("%s", __func__);
238 gsmd_modem_general_at_init_sim_ready (modem);
240 gsmd_modem_post_at_command_id(modem,
241 ENABLE_WIND,
242 NULL,NULL,NULL,NULL,
243 INTERFACE_GENERAL,
244 NULL);
246 return TRUE;
249 /********************************/
253 static void wavecom_unsolicite_handler_init(ModemInterface *modem,
254 VendorInterface *vendor)
256 g_debug("%s", __func__);
257 //add the symbol to the modem scanner
258 while (symbol_p->symbol_name) {
259 g_scanner_add_symbol (modem->scanner, symbol_p->symbol_name,
260 GINT_TO_POINTER(symbol_p->symbol_token));
261 symbol_p ++;
264 //add the command to the modem command table
265 while (command_p->command) {
266 gsmd_modem_register_command(modem, command_p);
267 command_p++;
269 vendor->unsolicite_handler = wavecom_unsolicite_handler;
273 static
274 AtCommandHandlerStatus wavecom_handle_wind(ModemInterface *modem,
275 AtCommandContext *at,
276 gint value,
277 gint callid)
279 g_debug("%s",__func__);
280 Call *call = NULL;
282 switch (value) {
283 case 2:
284 call = gsmd_utils_find_first_call_status(modem,CALL_CALLING);
285 if (call) {
286 call->status = CALL_WAITING;
289 } else {
290 gsmd_utils_print_calls(modem);
292 return AT_HANDLER_NEED_MORE;
293 break;
294 case 5:
295 g_debug("%s : Call created with id %d",__func__,callid);
296 g_debug("%s : Current calls: ",__func__);
298 gsmd_utils_print_calls(modem);
299 call = gsmd_utils_find_first_call_status(modem,CALL_IDLE);
300 if (call) {
301 call->vendor_id = callid;
302 call->status = CALL_CALLING;
303 if (modem->call_ipc->initiate_reply && at)
304 modem->call_ipc->initiate_reply(modem->call_ipc,
305 at->ipc_data,
306 call->id);
308 gsmd_utils_call_send_status(modem,
309 call,
310 "outgoing");
311 at->ipc_data = NULL;
313 return AT_HANDLER_NEED_MORE;
314 break;
315 case 6:
316 gsmd_utils_remove_calls(modem,TRUE);
317 return AT_HANDLER_NEED_MORE;
318 break;
321 return AT_HANDLER_DONT_UNDERSTAND;
325 AtCommandHandlerStatus wavecom_parse_wind(ModemInterface *modem,
326 AtCommandContext *at,
327 GString *response)
329 g_debug("%s",__func__);
330 AtCommandHandlerStatus result = AT_HANDLER_DONT_UNDERSTAND;
331 GError **error = NULL;
332 GRegex *regex = g_regex_new ("\\+WIND:\\s(?<value>\\d+),?(?<call>\\d+)?", 0, 0, error);
333 GMatchInfo *match_info;
334 gchar *match = NULL;
336 if (g_regex_match (regex, response->str, 0, &match_info)) {
337 if (gsmd_utils_match_exists(match_info,"value")) {
338 match = g_match_info_fetch_named(match_info,"value");
339 gint value = atoi(match);
340 g_free(match);
341 gint id = 0;
343 if (gsmd_utils_match_exists(match_info,"call")) {
344 match = g_match_info_fetch_named(match_info,"call");
345 id = atoi(match);
346 g_free(match);
349 result = wavecom_handle_wind(modem,at,value,id);
353 g_free(error);
354 g_match_info_free (match_info);
355 g_regex_unref (regex);
357 return result;
360 static
361 AtCommandHandlerStatus wavecom_call_initiate_handler(ModemInterface *modem,
362 AtCommandContext *at,
363 GString *response)
366 AtCommandHandlerStatus status = wavecom_parse_wind(modem,at,response);
367 GScanner* scanner = modem->scanner;
370 if (scanner->token == SYMBOL_OK) {
372 Call *call = gsmd_utils_find_first_call_status(modem,CALL_WAITING);
375 if (!call) {
376 call = gsmd_utils_find_first_call_status(modem,CALL_CALLING);
379 if (call) {
380 call->status = CALL_CONNECTED;
381 gsmd_utils_call_send_status(modem,
382 call,
383 "active");
385 } else {
386 g_warning("%s : OK reply to a call that doesn't existst. Current calls:",__func__);
387 gsmd_utils_print_calls(modem);
390 return AT_HANDLER_DONE;
391 } else if (scanner->token == SYMBOL_BUSY || scanner->token == SYMBOL_NO) {
392 Call *call = gsmd_utils_get_first_call(modem);
393 if (call) {
394 gsmd_utils_remove_call(modem,call->id, TRUE);
397 return AT_HANDLER_DONE;
401 if (status != AT_HANDLER_NEED_MORE)
402 return vendor_priv->orig_call_initiate_handler(modem,at,response);
403 else
404 return status;
408 AtCommandHandlerStatus wavecom_unsolicite_handler (ModemInterface *modem,
409 AtCommandContext *at,
410 GString *response)
412 g_debug("%s",__func__);
413 return wavecom_parse_wind(modem,at,response);