3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include <sys/ioctl.h>
37 #define OFONO_API_SUBJECT_TO_CHANGE
38 #include <ofono/plugin.h>
39 #include <ofono/modem.h>
40 #include <ofono/devinfo.h>
41 #include <ofono/netreg.h>
42 #include <ofono/phonebook.h>
43 #include <ofono/voicecall.h>
44 #include <ofono/call-barring.h>
45 #include <ofono/call-forwarding.h>
46 #include <ofono/call-meter.h>
47 #include <ofono/call-settings.h>
48 #include <ofono/call-volume.h>
49 #include <ofono/message-waiting.h>
50 #include <ofono/sim.h>
51 #include <ofono/cbs.h>
52 #include <ofono/sms.h>
53 #include <ofono/ussd.h>
54 #include <ofono/gprs.h>
55 #include <ofono/gprs-context.h>
56 #include <ofono/radio-settings.h>
57 #include <ofono/audio-settings.h>
58 #include <ofono/stk.h>
59 #include <ofono/ctm.h>
60 #include <ofono/log.h>
62 #include <drivers/atmodem/atutil.h>
63 #include <drivers/atmodem/vendor.h>
74 static char *dlc_prefixes[NUM_DLC] = { "Voice: ", "Net: ", "GPRS1: ",
75 "GPRS2: ", "GPRS3: ", "Aux: " };
77 static const char *dlc_nodes[NUM_DLC] = { "/dev/ttyGSM1", "/dev/ttyGSM2",
78 "/dev/ttyGSM3", "/dev/ttyGSM4",
79 "/dev/ttyGSM5", "/dev/ttyGSM6" };
81 static const char *none_prefix[] = { NULL };
82 static const char *xdrv_prefix[] = { "+XDRV:", NULL };
83 static const char *xgendata_prefix[] = { "+XGENDATA:", NULL };
84 static const char *xsimstate_prefix[] = { "+XSIMSTATE:", NULL };
89 GAtChat *dlcs[NUM_DLC];
91 guint dlc_poll_source;
92 guint dlc_init_source;
93 guint mux_init_timeout;
100 const char *audio_setting;
102 struct ofono_sim *sim;
106 static void ifx_debug(const char *str, void *user_data)
108 const char *prefix = user_data;
110 ofono_info("%s%s", prefix, str);
113 static int ifx_probe(struct ofono_modem *modem)
115 struct ifx_data *data;
119 data = g_try_new0(struct ifx_data, 1);
123 data->mux_ldisc = -1;
124 data->saved_ldisc = -1;
126 ofono_modem_set_data(modem, data);
131 static void ifx_remove(struct ofono_modem *modem)
133 struct ifx_data *data = ofono_modem_get_data(modem);
137 ofono_modem_set_data(modem, NULL);
142 static void ifx_set_sim_state(struct ofono_modem *modem, int state)
144 struct ifx_data *data = ofono_modem_get_data(modem);
146 DBG("state %d", state);
149 case 0: /* SIM not present */
150 case 9: /* SIM Removed */
151 if (data->have_sim == TRUE) {
152 ofono_sim_inserted_notify(data->sim, FALSE);
153 data->have_sim = FALSE;
156 case 1: /* PIN verification needed */
157 case 2: /* PIN verification not needed – Ready */
158 case 3: /* PIN verified – Ready */
159 case 4: /* PUK verification needed */
160 case 5: /* SIM permanently blocked */
161 case 6: /* SIM Error */
162 case 7: /* ready for attach (+COPS) */
163 case 8: /* SIM Technical Problem */
164 if (data->have_sim == FALSE) {
165 ofono_sim_inserted_notify(data->sim, TRUE);
166 data->have_sim = TRUE;
170 ofono_warn("Unknown SIM state %d received", state);
175 static void xsim_notify(GAtResult *result, gpointer user_data)
177 struct ofono_modem *modem = user_data;
178 struct ifx_data *data = ofono_modem_get_data(modem);
183 if (data->sim == NULL)
186 g_at_result_iter_init(&iter, result);
188 if (!g_at_result_iter_next(&iter, "+XSIM:"))
191 if (!g_at_result_iter_next_number(&iter, &state))
194 ifx_set_sim_state(modem, state);
197 static void xsimstate_query(gboolean ok, GAtResult *result, gpointer user_data)
199 struct ofono_modem *modem = user_data;
200 struct ifx_data *data = ofono_modem_get_data(modem);
210 g_at_result_iter_init(&iter, result);
212 if (!g_at_result_iter_next(&iter, "+XSIMSTATE:"))
215 if (!g_at_result_iter_next_number(&iter, &mode))
218 if (!g_at_result_iter_next_number(&iter, &state))
221 ifx_set_sim_state(modem, state);
224 static void shutdown_device(struct ifx_data *data)
230 if (data->dlc_init_source > 0) {
231 g_source_remove(data->dlc_init_source);
232 data->dlc_init_source = 0;
235 for (i = 0; i < NUM_DLC; i++) {
236 if (data->dlcs[i] == NULL)
239 g_at_chat_unref(data->dlcs[i]);
240 data->dlcs[i] = NULL;
244 g_at_mux_shutdown(data->mux);
245 g_at_mux_unref(data->mux);
250 fd = g_io_channel_unix_get_fd(data->device);
252 if (ioctl(fd, TIOCSETD, &data->saved_ldisc) < 0)
253 ofono_warn("Failed to restore line discipline");
256 g_io_channel_unref(data->device);
260 static void dlc_disconnect(gpointer user_data)
262 struct ofono_modem *modem = user_data;
263 struct ifx_data *data = ofono_modem_get_data(modem);
267 ofono_warn("Disconnect of modem channel");
269 shutdown_device(data);
272 static GAtChat *create_chat(GIOChannel *channel, struct ofono_modem *modem,
281 syntax = g_at_syntax_new_gsmv1();
282 chat = g_at_chat_new(channel, syntax);
283 g_at_syntax_unref(syntax);
284 g_io_channel_unref(channel);
289 if (getenv("OFONO_AT_DEBUG"))
290 g_at_chat_set_debug(chat, ifx_debug, debug);
292 g_at_chat_set_disconnect_function(chat, dlc_disconnect, modem);
297 static void xgendata_query(gboolean ok, GAtResult *result, gpointer user_data)
299 struct ofono_modem *modem = user_data;
300 struct ifx_data *data = ofono_modem_get_data(modem);
309 g_at_result_iter_init(&iter, result);
311 if (!g_at_result_iter_next(&iter, "+XGENDATA:"))
314 if (!g_at_result_iter_next_string(&iter, &gendata))
317 DBG("\n%s", gendata);
319 if (g_str_has_prefix(gendata, " XMM6260") == TRUE) {
320 ofono_info("Detected XMM6260 modem");
321 data->audio_source = 4;
322 data->audio_dest = 3;
323 data->audio_context = 0;
326 /* disable UART for power saving */
327 g_at_chat_send(data->dlcs[AUX_DLC], "AT+XPOW=0,0,0", none_prefix,
330 if (data->audio_setting && data->audio_source && data->audio_dest) {
333 /* configure source */
334 snprintf(buf, sizeof(buf), "AT+XDRV=40,4,%d,%d,%s",
337 data->audio_setting);
338 g_at_chat_send(data->dlcs[AUX_DLC], buf, xdrv_prefix,
341 /* configure destination */
342 snprintf(buf, sizeof(buf), "AT+XDRV=40,5,%d,%d,%s",
345 data->audio_setting);
346 g_at_chat_send(data->dlcs[AUX_DLC], buf, xdrv_prefix,
349 if (data->audio_loopback) {
350 /* set destination for source */
351 snprintf(buf, sizeof(buf), "AT+XDRV=40,6,%d,%d",
352 data->audio_source, data->audio_dest);
353 g_at_chat_send(data->dlcs[AUX_DLC], buf, xdrv_prefix,
357 snprintf(buf, sizeof(buf), "AT+XDRV=40,2,%d",
359 g_at_chat_send(data->dlcs[AUX_DLC], buf, xdrv_prefix,
364 data->have_sim = FALSE;
366 /* notify that the modem is ready so that pre_sim gets called */
367 ofono_modem_set_powered(modem, TRUE);
369 g_at_chat_register(data->dlcs[AUX_DLC], "+XSIM:", xsim_notify,
372 /* enable XSIM and XLOCK notifications */
373 g_at_chat_send(data->dlcs[AUX_DLC], "AT+XSIMSTATE=1", none_prefix,
376 g_at_chat_send(data->dlcs[AUX_DLC], "AT+XSIMSTATE?", xsimstate_prefix,
377 xsimstate_query, modem, NULL);
382 shutdown_device(data);
383 ofono_modem_set_powered(modem, FALSE);
386 static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
388 struct ofono_modem *modem = user_data;
389 struct ifx_data *data = ofono_modem_get_data(modem);
394 shutdown_device(data);
395 ofono_modem_set_powered(modem, FALSE);
399 g_at_chat_send(data->dlcs[AUX_DLC], "AT+XGENDATA", xgendata_prefix,
400 xgendata_query, modem, NULL);
403 static gboolean dlc_setup(gpointer user_data)
405 struct ofono_modem *modem = user_data;
406 struct ifx_data *data = ofono_modem_get_data(modem);
411 for (i = 0; i < NUM_DLC; i++)
412 g_at_chat_send(data->dlcs[i], "ATE0 +CMEE=1", NULL,
415 g_at_chat_set_slave(data->dlcs[GPRS1_DLC], data->dlcs[NETREG_DLC]);
416 g_at_chat_set_slave(data->dlcs[GPRS2_DLC], data->dlcs[NETREG_DLC]);
417 g_at_chat_set_slave(data->dlcs[GPRS3_DLC], data->dlcs[NETREG_DLC]);
419 g_at_chat_send(data->dlcs[AUX_DLC], "AT+CFUN=4", NULL,
420 cfun_enable, modem, NULL);
422 data->dlc_init_source = 0;
427 static gboolean dlc_ready_check(gpointer user_data)
429 struct ofono_modem *modem = user_data;
430 struct ifx_data *data = ofono_modem_get_data(modem);
436 data->dlc_poll_count++;
438 if (stat(dlc_nodes[AUX_DLC], &st) < 0) {
439 /* only possible error is ENOENT */
440 if (data->dlc_poll_count > 6)
446 for (i = 0; i < NUM_DLC; i++) {
447 GIOChannel *channel = g_at_tty_open(dlc_nodes[i], NULL);
449 data->dlcs[i] = create_chat(channel, modem, dlc_prefixes[i]);
450 if (data->dlcs[i] == NULL) {
451 ofono_error("Failed to open %s", dlc_nodes[i]);
456 data->dlc_poll_source = 0;
458 /* iterate through mainloop */
459 data->dlc_init_source = g_timeout_add_seconds(0, dlc_setup, modem);
464 data->dlc_poll_source = 0;
466 shutdown_device(data);
467 ofono_modem_set_powered(modem, FALSE);
472 static void setup_internal_mux(struct ofono_modem *modem)
474 struct ifx_data *data = ofono_modem_get_data(modem);
479 data->mux = g_at_mux_new_gsm0710_basic(data->device, data->frame_size);
480 if (data->mux == NULL)
483 if (getenv("OFONO_MUX_DEBUG"))
484 g_at_mux_set_debug(data->mux, ifx_debug, "MUX: ");
486 g_at_mux_start(data->mux);
488 for (i = 0; i < NUM_DLC; i++) {
489 GIOChannel *channel = g_at_mux_create_channel(data->mux);
491 data->dlcs[i] = create_chat(channel, modem, dlc_prefixes[i]);
492 if (data->dlcs[i] == NULL) {
493 ofono_error("Failed to create channel");
498 /* wait for DLC creation to settle */
499 data->dlc_init_source = g_timeout_add(10, dlc_setup, modem);
504 shutdown_device(data);
505 ofono_modem_set_powered(modem, FALSE);
508 static void mux_setup_cb(gboolean ok, GAtResult *result, gpointer user_data)
510 struct ofono_modem *modem = user_data;
511 struct ifx_data *data = ofono_modem_get_data(modem);
516 if (data->mux_init_timeout > 0) {
517 g_source_remove(data->mux_init_timeout);
518 data->mux_init_timeout = 0;
521 g_at_chat_unref(data->dlcs[AUX_DLC]);
522 data->dlcs[AUX_DLC] = NULL;
527 if (data->mux_ldisc < 0) {
528 ofono_info("Using internal multiplexer");
529 setup_internal_mux(modem);
533 fd = g_io_channel_unix_get_fd(data->device);
535 if (ioctl(fd, TIOCGETD, &data->saved_ldisc) < 0) {
536 ofono_error("Failed to get current line discipline");
540 if (ioctl(fd, TIOCSETD, &data->mux_ldisc) < 0) {
541 ofono_error("Failed to set multiplexer line discipline");
545 data->dlc_poll_count = 0;
546 data->dlc_poll_source = g_timeout_add_seconds(1, dlc_ready_check,
552 data->saved_ldisc = -1;
554 g_io_channel_unref(data->device);
557 ofono_modem_set_powered(modem, FALSE);
560 static gboolean mux_timeout_cb(gpointer user_data)
562 struct ofono_modem *modem = user_data;
563 struct ifx_data *data = ofono_modem_get_data(modem);
565 ofono_error("Timeout with multiplexer setup");
567 data->mux_init_timeout = 0;
569 g_at_chat_unref(data->dlcs[AUX_DLC]);
570 data->dlcs[AUX_DLC] = NULL;
572 g_io_channel_unref(data->device);
575 ofono_modem_set_powered(modem, FALSE);
580 static int ifx_enable(struct ofono_modem *modem)
582 struct ifx_data *data = ofono_modem_get_data(modem);
583 const char *device, *ldisc, *audio, *loopback;
589 device = ofono_modem_get_string(modem, "Device");
595 audio = ofono_modem_get_string(modem, "AudioSetting");
596 if (g_strcmp0(audio, "FULL_DUPLEX") == 0)
597 data->audio_setting = "0,0,0,0,0,0,0,0,0";
598 else if (g_strcmp0(audio, "BURSTMODE_48KHZ") == 0)
599 data->audio_setting = "0,0,8,0,2,0,0,0,0";
600 else if (g_strcmp0(audio, "BURSTMODE_96KHZ") == 0)
601 data->audio_setting = "0,0,9,0,2,0,0,0,0";
603 loopback = ofono_modem_get_string(modem, "AudioLoopback");
604 if (loopback != NULL)
605 data->audio_loopback = atoi(loopback);
607 ldisc = ofono_modem_get_string(modem, "LineDiscipline");
609 data->mux_ldisc = atoi(ldisc);
610 ofono_info("Using multiplexer line discipline %d",
614 data->device = g_at_tty_open(device, NULL);
615 if (data->device == NULL)
618 syntax = g_at_syntax_new_gsmv1();
619 chat = g_at_chat_new(data->device, syntax);
620 g_at_syntax_unref(syntax);
623 g_io_channel_unref(data->device);
627 if (getenv("OFONO_AT_DEBUG"))
628 g_at_chat_set_debug(chat, ifx_debug, "Master: ");
630 g_at_chat_send(chat, "ATE0 +CMEE=1", NULL,
633 /* Enable multiplexer */
634 data->frame_size = 1509;
636 g_at_chat_send(chat, "AT+CMUX=0,0,,1509,10,3,30,,", NULL,
637 mux_setup_cb, modem, NULL);
639 data->mux_init_timeout = g_timeout_add_seconds(5, mux_timeout_cb,
642 data->dlcs[AUX_DLC] = chat;
647 static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
649 struct ofono_modem *modem = user_data;
650 struct ifx_data *data = ofono_modem_get_data(modem);
654 if (data->dlc_poll_source > 0) {
655 g_source_remove(data->dlc_poll_source);
656 data->dlc_poll_source = 0;
659 shutdown_device(data);
662 ofono_modem_set_powered(modem, FALSE);
665 static int ifx_disable(struct ofono_modem *modem)
667 struct ifx_data *data = ofono_modem_get_data(modem);
672 for (i = 0; i < NUM_DLC; i++) {
673 g_at_chat_cancel_all(data->dlcs[i]);
674 g_at_chat_unregister_all(data->dlcs[i]);
677 g_at_chat_send(data->dlcs[AUX_DLC], "AT+CFUN=4", NULL,
678 cfun_disable, modem, NULL);
683 static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
685 struct cb_data *cbd = user_data;
686 ofono_modem_online_cb_t cb = cbd->cb;
687 struct ofono_error error;
689 decode_at_error(&error, g_at_result_final_response(result));
690 cb(&error, cbd->data);
693 static void ifx_set_online(struct ofono_modem *modem, ofono_bool_t online,
694 ofono_modem_online_cb_t cb, void *user_data)
696 struct ifx_data *data = ofono_modem_get_data(modem);
697 struct cb_data *cbd = cb_data_new(cb, user_data);
698 char const *command = online ? "AT+CFUN=1" : "AT+CFUN=4";
700 DBG("%p %s", modem, online ? "online" : "offline");
702 if (g_at_chat_send(data->dlcs[AUX_DLC], command, none_prefix,
703 set_online_cb, cbd, g_free) > 0)
706 CALLBACK_WITH_FAILURE(cb, cbd->data);
711 static void ifx_pre_sim(struct ofono_modem *modem)
713 struct ifx_data *data = ofono_modem_get_data(modem);
717 ofono_devinfo_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
718 data->sim = ofono_sim_create(modem, OFONO_VENDOR_IFX,
719 "atmodem", data->dlcs[AUX_DLC]);
720 ofono_voicecall_create(modem, 0, "ifxmodem", data->dlcs[VOICE_DLC]);
721 ofono_audio_settings_create(modem, 0,
722 "ifxmodem", data->dlcs[VOICE_DLC]);
723 ofono_ctm_create(modem, 0, "ifxmodem", data->dlcs[AUX_DLC]);
726 static void ifx_post_sim(struct ofono_modem *modem)
728 struct ifx_data *data = ofono_modem_get_data(modem);
732 ofono_stk_create(modem, 0, "ifxmodem", data->dlcs[AUX_DLC]);
733 ofono_phonebook_create(modem, OFONO_VENDOR_IFX,
734 "atmodem", data->dlcs[AUX_DLC]);
735 ofono_call_forwarding_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
736 ofono_radio_settings_create(modem, 0, "ifxmodem", data->dlcs[AUX_DLC]);
738 ofono_sms_create(modem, OFONO_VENDOR_IFX,
739 "atmodem", data->dlcs[AUX_DLC]);
742 static void ifx_post_online(struct ofono_modem *modem)
744 struct ifx_data *data = ofono_modem_get_data(modem);
745 struct ofono_message_waiting *mw;
746 struct ofono_gprs *gprs;
747 struct ofono_gprs_context *gc;
751 ofono_netreg_create(modem, OFONO_VENDOR_IFX,
752 "atmodem", data->dlcs[NETREG_DLC]);
754 ofono_cbs_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
755 ofono_ussd_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
757 ofono_call_settings_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
758 ofono_call_meter_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
759 ofono_call_barring_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
760 ofono_call_volume_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
762 mw = ofono_message_waiting_create(modem);
764 ofono_message_waiting_register(mw);
766 gprs = ofono_gprs_create(modem, OFONO_VENDOR_IFX,
767 "atmodem", data->dlcs[NETREG_DLC]);
771 if (data->mux_ldisc < 0) {
772 gc = ofono_gprs_context_create(modem, 0,
773 "ifxmodem", data->dlcs[GPRS1_DLC]);
775 ofono_gprs_add_context(gprs, gc);
777 gc = ofono_gprs_context_create(modem, 0,
778 "ifxmodem", data->dlcs[GPRS2_DLC]);
780 ofono_gprs_add_context(gprs, gc);
782 gc = ofono_gprs_context_create(modem, 0,
783 "ifxmodem", data->dlcs[GPRS3_DLC]);
785 ofono_gprs_add_context(gprs, gc);
789 static struct ofono_modem_driver ifx_driver = {
792 .remove = ifx_remove,
793 .enable = ifx_enable,
794 .disable = ifx_disable,
795 .set_online = ifx_set_online,
796 .pre_sim = ifx_pre_sim,
797 .post_sim = ifx_post_sim,
798 .post_online = ifx_post_online,
801 static int ifx_init(void)
803 return ofono_modem_driver_register(&ifx_driver);
806 static void ifx_exit(void)
808 ofono_modem_driver_unregister(&ifx_driver);
811 OFONO_PLUGIN_DEFINE(ifx, "Infineon modem driver", VERSION,
812 OFONO_PLUGIN_PRIORITY_DEFAULT, ifx_init, ifx_exit)