Random fixes and cleanups
[gsmd2.git] / vendor / wavecom-900e.c
blob7b113006cb52808dd60956a9414754dbfa37b697
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 _Wavecom900e {
74 ModemInterface *modem;
75 AtCommandHandlerStatus (*orig_call_initiate_handler) (ModemInterface *modem,
76 AtCommandContext *at,
77 GString *response);
78 } Wavecom900e;
80 static Wavecom900e *vendor_priv = NULL;
82 static
83 AtCommandHandlerStatus wavecom_handler_query_pin_status (ModemInterface *modem,
84 AtCommandContext *at,
85 GString *response);
87 /** vendor_handle_init should be called from modem.c when the lib loaded*/
88 gboolean vendor_handle_init (VendorInterface *vendor, ModemInterface* modem)
90 if ( vendor_priv ) {
91 g_warning("%s : Already initialized!", __func__);
92 return FALSE;
94 vendor_priv = g_new0(Wavecom900e, 1);
95 g_debug("%s", __func__);
96 vendor->init_at = NULL;
97 vendor->init_at_sim_ready = vendor_at_init_sim_ready;
98 vendor->priv = (gpointer)vendor_priv;
99 wavecom_unsolicite_handler_init (modem, vendor);
100 vendor_priv->modem = modem;
102 AtCommand *call_initiate = gsmd_modem_get_command(modem, INITIATE_CALL);
103 vendor_priv->orig_call_initiate_handler = call_initiate->handler;
104 call_initiate->handler = &wavecom_call_initiate_handler;
106 AtCommand *query_pin = gsmd_modem_get_command(modem, PIN_QUERY);
107 query_pin->handler = &wavecom_handler_query_pin_status;
110 return TRUE;
112 /*************************************/
116 * @brief Handler to modems response from queryPinStatus command
118 * @param modem modem whose response to handle
119 * @return true if responses were recognized
121 static
122 AtCommandHandlerStatus wavecom_handler_query_pin_status (ModemInterface *modem,
123 AtCommandContext *at,
124 GString *response)
126 g_debug("%s",__func__);
127 GScanner* scanner = modem->scanner;
131 if (gsmd_utils_send_error_from_response(at,
132 response,
133 "ERROR READING PIN STATUS",
134 "TIMEOUT READING PIN STATUS"))
135 return AT_HANDLER_DONE_ERROR;
137 if (scanner->token != '+') {
138 return AT_HANDLER_DONT_UNDERSTAND;
141 g_scanner_get_next_token (scanner);
142 switch (scanner->token) {
144 case SYMBOL_CME:
145 g_scanner_get_next_token (scanner);
146 //g_scanner_get_next_token (scanner);
147 if (scanner->token == SYMBOL_ERROR) {
148 g_scanner_peek_next_token(scanner);
149 if (scanner->next_token == ':') {
150 g_scanner_get_next_token (scanner);
151 g_scanner_get_next_token(scanner);//arrive error value
152 if ( ERR_NO_SIM_CARD == scanner->value.v_int ) {
153 gsmd_sim_change_auth_status(modem,
154 at->ipc_data,
155 SIM_MISSING,
156 "SIM MISSING",
157 TRUE);
158 } else {
159 gsmd_sim_change_auth_status(modem,
160 at->ipc_data,
161 SIM_ERROR,
162 "SIM ERROR",
163 TRUE);
166 return AT_HANDLER_DONE;
167 } else {
168 g_scanner_unexp_token (scanner, ':', NULL, "symbol",
169 NULL, NULL, TRUE);
172 } else {
173 g_scanner_unexp_token (scanner, SYMBOL_ERROR, NULL, "symbol",
174 NULL, NULL, TRUE);
176 break;
177 case SYMBOL_CPIN:
178 g_scanner_get_next_token (scanner);//get ':'
179 g_scanner_get_next_token (scanner);
180 if (scanner->token == SYMBOL_READY) {
181 g_debug("%s: READY",__func__);
182 gsmd_sim_change_auth_status(modem,
183 at->ipc_data,
184 SIM_READY,
185 "READY",
186 TRUE);
189 return AT_HANDLER_DONE;
191 } else if (scanner->token == SYMBOL_SIM) {
193 g_scanner_get_next_token (scanner);
194 g_scanner_peek_next_token(scanner);
195 if (scanner->token == SYMBOL_PIN) {
196 gsmd_sim_change_auth_status(modem,
197 at->ipc_data,
198 SIM_NEED_PIN,
199 "SIM PIN",
200 TRUE);
201 } else if (scanner->token == SYMBOL_PUK) {
202 g_debug("%s: SIM PUK",__func__);
203 gsmd_sim_change_auth_status(modem,
204 at->ipc_data,
205 SIM_NEED_PUK,
206 "SIM PUK",
207 TRUE);
210 return AT_HANDLER_DONE;
211 } else {
212 g_scanner_unexp_token (scanner, SYMBOL_READY, NULL, "symbol",
213 NULL, NULL, TRUE);
215 break;
216 default:
217 g_warning("No match after getting + \n");
218 break;
225 return AT_HANDLER_DONT_UNDERSTAND;
229 static gboolean vendor_at_init_sim_ready (VendorInterface* vendor)
231 ModemInterface *modem = vendor_priv->modem;
232 g_assert(modem);
233 g_debug("%s", __func__);
235 gsmd_modem_general_at_init_sim_ready (modem);
237 gsmd_modem_post_at_command_id(modem,
238 ENABLE_WIND,
239 NULL,NULL,NULL,NULL,
240 INTERFACE_GENERAL,
241 NULL);
243 return TRUE;
246 /********************************/
250 static void wavecom_unsolicite_handler_init(ModemInterface *modem,
251 VendorInterface *vendor)
253 g_debug("%s", __func__);
254 //add the symbol to the modem scanner
255 while (symbol_p->symbol_name) {
256 g_scanner_add_symbol (modem->scanner, symbol_p->symbol_name,
257 GINT_TO_POINTER(symbol_p->symbol_token));
258 symbol_p ++;
261 //add the command to the modem command table
262 while (command_p->command) {
263 gsmd_modem_register_command(modem, command_p);
264 command_p++;
266 vendor->unsolicite_handler = wavecom_unsolicite_handler;
270 static
271 AtCommandHandlerStatus wavecom_handle_wind(ModemInterface *modem,
272 AtCommandContext *at,
273 gint value,
274 gint callid)
276 g_debug("%s",__func__);
277 Call *call = NULL;
279 switch (value) {
280 case 2:
281 call = gsmd_utils_find_first_call_status(modem,CALL_CALLING);
282 if (call) {
283 call->status = CALL_WAITING;
286 } else {
287 gsmd_utils_print_calls(modem);
289 return AT_HANDLER_NEED_MORE;
290 break;
291 case 5:
292 g_debug("%s : Call created with id %d",__func__,callid);
293 g_debug("%s : Current calls: ",__func__);
295 gsmd_utils_print_calls(modem);
296 call = gsmd_utils_find_first_call_status(modem,CALL_IDLE);
297 if (call) {
298 call->vendor_id = callid;
299 call->status = CALL_CALLING;
300 if (modem->call_ipc->initiate_reply && at)
301 modem->call_ipc->initiate_reply(modem->call_ipc,
302 at->ipc_data,
303 call->id);
305 gsmd_utils_call_send_status(modem,
306 call,
307 "outgoing");
308 at->ipc_data = NULL;
310 return AT_HANDLER_NEED_MORE;
311 break;
312 case 6:
313 gsmd_utils_remove_calls(modem,TRUE);
314 return AT_HANDLER_NEED_MORE;
315 break;
318 return AT_HANDLER_DONT_UNDERSTAND;
322 AtCommandHandlerStatus wavecom_parse_wind(ModemInterface *modem,
323 AtCommandContext *at,
324 GString *response)
326 g_debug("%s",__func__);
327 AtCommandHandlerStatus result = AT_HANDLER_DONT_UNDERSTAND;
328 GError **error = NULL;
329 GRegex *regex = g_regex_new ("\\+WIND:\\s(?<value>\\d+),?(?<call>\\d+)?", 0, 0, error);
330 GMatchInfo *match_info;
331 gchar *match = NULL;
333 if (g_regex_match (regex, response->str, 0, &match_info)) {
334 if (gsmd_utils_match_exists(match_info,"value")) {
335 match = g_match_info_fetch_named(match_info,"value");
336 gint value = atoi(match);
337 g_free(match);
338 gint id = 0;
340 if (gsmd_utils_match_exists(match_info,"call")) {
341 match = g_match_info_fetch_named(match_info,"call");
342 id = atoi(match);
343 g_free(match);
346 result = wavecom_handle_wind(modem,at,value,id);
350 g_free(error);
351 g_match_info_free (match_info);
352 g_regex_unref (regex);
354 return result;
357 static
358 AtCommandHandlerStatus wavecom_call_initiate_handler(ModemInterface *modem,
359 AtCommandContext *at,
360 GString *response)
363 AtCommandHandlerStatus status = wavecom_parse_wind(modem,at,response);
364 GScanner* scanner = modem->scanner;
367 if (scanner->token == SYMBOL_OK) {
369 Call *call = gsmd_utils_find_first_call_status(modem,CALL_WAITING);
372 if (!call) {
373 call = gsmd_utils_find_first_call_status(modem,CALL_CALLING);
376 if (call) {
377 call->status = CALL_CONNECTED;
378 gsmd_utils_call_send_status(modem,
379 call,
380 "active");
382 } else {
383 g_warning("%s : OK reply to a call that doesn't existst. Current calls:",__func__);
384 gsmd_utils_print_calls(modem);
387 return AT_HANDLER_DONE;
388 } else if (scanner->token == SYMBOL_BUSY || scanner->token == SYMBOL_NO) {
389 Call *call = gsmd_utils_get_first_call(modem);
390 if (call) {
391 gsmd_utils_remove_call(modem,call->id, TRUE);
394 return AT_HANDLER_DONE;
398 if (status != AT_HANDLER_NEED_MORE)
399 return vendor_priv->orig_call_initiate_handler(modem,at,response);
400 else
401 return status;
405 AtCommandHandlerStatus wavecom_unsolicite_handler (ModemInterface *modem,
406 AtCommandContext *at,
407 GString *response)
409 g_debug("%s",__func__);
410 return wavecom_parse_wind(modem,at,response);