summaryrefslogtreecommitdiffstats
path: root/plugins/sim900.c
diff options
context:
space:
mode:
authorRenat Zaripov <r.r.zaripov@gmail.com>2013-03-12 18:37:58 +0400
committerDenis Kenzior <denkenz@gmail.com>2013-03-26 10:29:08 -0500
commit2d09257855e186b50f7f0083059df5cd07804ea5 (patch)
tree46c6f250cea1ec59bf291131bbdc465ac81ca1d0 /plugins/sim900.c
parentd8a9bf776b83309b8c934d7cee5480c26181feaf (diff)
downloadofono-2d09257855e186b50f7f0083059df5cd07804ea5.tar.bz2
sim900: Add multiplexer support
Also add gprs and call-volume support.
Diffstat (limited to 'plugins/sim900.c')
-rw-r--r--plugins/sim900.c201
1 files changed, 171 insertions, 30 deletions
diff --git a/plugins/sim900.c b/plugins/sim900.c
index b55991b9..de2a6f7a 100644
--- a/plugins/sim900.c
+++ b/plugins/sim900.c
@@ -25,10 +25,10 @@
#include <errno.h>
#include <stdlib.h>
-
#include <glib.h>
#include <gatchat.h>
#include <gattty.h>
+#include <gatmux.h>
#define OFONO_API_SUBJECT_TO_CHANGE
#include <ofono/plugin.h>
@@ -44,13 +44,27 @@
#include <ofono/history.h>
#include <ofono/log.h>
#include <ofono/voicecall.h>
-
+#include <ofono/call-volume.h>
#include <drivers/atmodem/vendor.h>
+#define NUM_DLC 5
+
+#define SETUP_DLC 0
+#define VOICE_DLC 1
+#define NETREG_DLC 2
+#define SMS_DLC 3
+#define GPRS_DLC 4
+
+static char *dlc_prefixes[NUM_DLC] = { "Voice: ", "Net: ", "SMS: ",
+ "GPRS: " , "Setup: "};
+
static const char *none_prefix[] = { NULL };
struct sim900_data {
- GAtChat *modem;
+ GIOChannel *device;
+ GAtMux *mux;
+ GAtChat * dlcs[NUM_DLC];
+ guint frame_size;
};
static int sim900_probe(struct ofono_modem *modem)
@@ -76,8 +90,6 @@ static void sim900_remove(struct ofono_modem *modem)
ofono_modem_set_data(modem, NULL);
- g_at_chat_unref(data->modem);
-
g_free(data);
}
@@ -89,8 +101,9 @@ static void sim900_debug(const char *str, void *user_data)
}
static GAtChat *open_device(struct ofono_modem *modem,
- const char *key, char *debug)
+ const char *key, char *debug)
{
+ struct sim900_data *data = ofono_modem_get_data(modem);
const char *device;
GAtSyntax *syntax;
GIOChannel *channel;
@@ -121,10 +134,32 @@ static GAtChat *open_device(struct ofono_modem *modem,
if (channel == NULL)
return NULL;
+ data->device = channel;
syntax = g_at_syntax_new_gsm_permissive();
chat = g_at_chat_new(channel, syntax);
g_at_syntax_unref(syntax);
+ if (chat == NULL)
+ return NULL;
+
+ if (getenv("OFONO_AT_DEBUG"))
+ g_at_chat_set_debug(chat, sim900_debug, debug);
+
+ return chat;
+}
+
+static GAtChat *create_chat(GIOChannel *channel, struct ofono_modem *modem,
+ char *debug)
+{
+ GAtSyntax *syntax;
+ GAtChat *chat;
+
+ if (channel == NULL)
+ return NULL;
+
+ syntax = g_at_syntax_new_gsmv1();
+ chat = g_at_chat_new(channel, syntax);
+ g_at_syntax_unref(syntax);
g_io_channel_unref(channel);
if (chat == NULL)
@@ -136,6 +171,96 @@ static GAtChat *open_device(struct ofono_modem *modem,
return chat;
}
+static void shutdown_device(struct sim900_data *data)
+{
+ int i, fd;
+
+ DBG("");
+
+ for (i = 0; i < NUM_DLC; i++) {
+ if (data->dlcs[i] == NULL)
+ continue;
+
+ g_at_chat_unref(data->dlcs[i]);
+ data->dlcs[i] = NULL;
+ }
+
+ if (data->mux) {
+ g_at_mux_shutdown(data->mux);
+ g_at_mux_unref(data->mux);
+ data->mux = NULL;
+ goto done;
+ }
+
+done:
+ g_io_channel_unref(data->device);
+ data->device = NULL;
+}
+
+static void setup_internal_mux(struct ofono_modem *modem)
+{
+ struct sim900_data *data = ofono_modem_get_data(modem);
+ int i;
+
+ DBG("");
+
+ data->frame_size = 128;
+
+ data->mux = g_at_mux_new_gsm0710_basic(data->device,
+ data->frame_size);
+ if (data->mux == NULL)
+ goto error;
+
+ if (getenv("OFONO_MUX_DEBUG"))
+ g_at_mux_set_debug(data->mux, sim900_debug, "MUX: ");
+
+ if (!g_at_mux_start(data->mux)) {
+ g_at_mux_shutdown(data->mux);
+ g_at_mux_unref(data->mux);
+ goto error;
+ }
+
+ for (i = 0; i < NUM_DLC; i++) {
+ GIOChannel *channel = g_at_mux_create_channel(data->mux);
+
+ data->dlcs[i] = create_chat(channel, modem, dlc_prefixes[i]);
+ if (data->dlcs[i] == NULL) {
+ ofono_error("Failed to create channel");
+ goto error;
+ }
+ }
+
+ ofono_modem_set_powered(modem, TRUE);
+
+ return;
+
+error:
+ shutdown_device(data);
+ ofono_modem_set_powered(modem, FALSE);
+}
+
+static void mux_setup_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct sim900_data *data = ofono_modem_get_data(modem);
+
+ DBG("");
+
+ g_at_chat_unref(data->dlcs[SETUP_DLC]);
+ data->dlcs[SETUP_DLC] = NULL;
+
+ if (!ok)
+ goto error;
+
+ setup_internal_mux(modem);
+
+ return;
+
+error:
+ shutdown_device(data);
+ ofono_modem_set_powered(modem, FALSE);
+}
+
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
@@ -144,11 +269,15 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
DBG("");
if (!ok) {
- g_at_chat_unref(data->modem);
- data->modem = NULL;
+ g_at_chat_unref(data->dlcs[SETUP_DLC]);
+ data->dlcs[SETUP_DLC] = NULL;
+ ofono_modem_set_powered(modem, FALSE);
+ return;
}
- ofono_modem_set_powered(modem, ok);
+ g_at_chat_send(data->dlcs[SETUP_DLC],
+ "AT+CMUX=0,0,5,128,10,3,30,10,2", NULL,
+ mux_setup_cb, modem, NULL);
}
static int sim900_enable(struct ofono_modem *modem)
@@ -157,25 +286,22 @@ static int sim900_enable(struct ofono_modem *modem)
DBG("%p", modem);
- data->modem = open_device(modem, "Device", "Device: ");
- if (data->modem == NULL) {
- DBG("return -EINVAL");
+ data->dlcs[SETUP_DLC] = open_device(modem, "Device", "Setup: ");
+ if (data->dlcs[SETUP_DLC] == NULL)
return -EINVAL;
- }
- g_at_chat_send(data->modem, "ATE0", NULL, NULL, NULL, NULL);
+ g_at_chat_send(data->dlcs[SETUP_DLC], "ATE0", NULL, NULL, NULL, NULL);
/* For obtain correct sms service number */
- g_at_chat_send(data->modem, "AT+CSCS=\"GSM\"", NULL,
+ g_at_chat_send(data->dlcs[SETUP_DLC], "AT+CSCS=\"GSM\"", NULL,
NULL, NULL, NULL);
- g_at_chat_send(data->modem, "AT+CFUN=1", none_prefix,
+ g_at_chat_send(data->dlcs[SETUP_DLC], "AT+CFUN=1", none_prefix,
cfun_enable, modem, NULL);
return -EINPROGRESS;
}
-
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
@@ -183,8 +309,11 @@ static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
DBG("");
- g_at_chat_unref(data->modem);
- data->modem = NULL;
+ g_at_mux_shutdown(data->mux);
+ g_at_mux_unref(data->mux);
+
+ g_at_chat_unref(data->dlcs[SETUP_DLC]);
+ data->dlcs[SETUP_DLC] = NULL;
if (ok)
ofono_modem_set_powered(modem, FALSE);
@@ -196,12 +325,11 @@ static int sim900_disable(struct ofono_modem *modem)
DBG("%p", modem);
- g_at_chat_cancel_all(data->modem);
- g_at_chat_unregister_all(data->modem);
-
- g_at_chat_send(data->modem, "AT+CFUN=4", none_prefix,
+ g_at_chat_send(data->dlcs[SETUP_DLC], "AT+CFUN=4", none_prefix,
cfun_disable, modem, NULL);
+ shutdown_device(data);
+
return -EINPROGRESS;
}
@@ -212,9 +340,9 @@ static void sim900_pre_sim(struct ofono_modem *modem)
DBG("%p", modem);
- ofono_devinfo_create(modem, 0, "atmodem", data->modem);
+ ofono_devinfo_create(modem, 0, "atmodem", data->dlcs[VOICE_DLC]);
sim = ofono_sim_create(modem, OFONO_VENDOR_SIMCOM, "atmodem",
- data->modem);
+ data->dlcs[VOICE_DLC]);
if (sim)
ofono_sim_inserted_notify(sim, TRUE);
@@ -223,12 +351,23 @@ static void sim900_pre_sim(struct ofono_modem *modem)
static void sim900_post_sim(struct ofono_modem *modem)
{
struct sim900_data *data = ofono_modem_get_data(modem);
+ struct ofono_gprs *gprs;
+ struct ofono_gprs_context *gc;
DBG("%p", modem);
- ofono_phonebook_create(modem, 0, "atmodem", data->modem);
+ ofono_phonebook_create(modem, 0, "atmodem", data->dlcs[VOICE_DLC]);
ofono_sms_create(modem, OFONO_VENDOR_SIMCOM, "atmodem",
- data->modem);
+ data->dlcs[SMS_DLC]);
+
+ gprs = ofono_gprs_create(modem, 0, "atmodem", data->dlcs[GPRS_DLC]);
+ if (gprs == NULL)
+ return;
+
+ gc = ofono_gprs_context_create(modem, OFONO_VENDOR_SIMCOM,
+ "atmodem", data->dlcs[GPRS_DLC]);
+ if (gc)
+ ofono_gprs_add_context(gprs, gc);
}
static void sim900_post_online(struct ofono_modem *modem)
@@ -237,9 +376,11 @@ static void sim900_post_online(struct ofono_modem *modem)
DBG("%p", modem);
- ofono_netreg_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->modem);
- ofono_ussd_create(modem, 0, "atmodem", data->modem);
- ofono_voicecall_create(modem, 0, "atmodem", data->modem);
+ ofono_netreg_create(modem, OFONO_VENDOR_SIMCOM,
+ "atmodem", data->dlcs[NETREG_DLC]);
+ ofono_ussd_create(modem, 0, "atmodem", data->dlcs[VOICE_DLC]);
+ ofono_voicecall_create(modem, 0, "atmodem", data->dlcs[VOICE_DLC]);
+ ofono_call_volume_create(modem, 0, "atmodem", data->dlcs[VOICE_DLC]);
}
static struct ofono_modem_driver sim900_driver = {