[RFC] HFP support into oFono and BlueZ
by Gustavo F. Padovan
Hi,
These patches implement the new API for the Audio Gateway in BlueZ. It
follows the last version of the HandsfreeGateway and HandsfreeAgent
Intefaces API.
The first two patches is for BlueZ and the other for oFono. You can
test it with using enable-modem and test-voicecall scripts into the
test dir of oFono.
Feel free to test it and send me your comments. We have some bugs yet.
The audio part is not working yet. We are going to work on pulseaudio
this week to get this done soon.
Regards,
--
Gustavo F. Padovan
ProFUSION embedded systems - http://profusion.mobi
9 years, 10 months
CDMA SMS Handling
by Rajesh.Nagaiah@elektrobit.com
Hi,
There was a discussion about the CDMA SMS handling and CDMA PDUs in the
IRC channel couple of days before. I would like to highlight the
differences between CDMA and GSM PDU and how we should proceed with this
from my understanding. Let me know your opinion.
Even though oFono supports +CMT and +CMTI, if we feed the incoming CDMA
PDUs to the SMS core it wont get decoded correctly, as there is
substantial differences between the GSM and CDMA SMS PDUs as described
in 3GPP2 specification C.S0015-B Short Message Service (SMS) for
Wideband Spread Spectrum Systems
For eg, the incoming PDU example that was mentioned in the IRC
discussion
+CMT: , 40,
00000210020207028CE95DCC65800601FC08150003168D30010610241830608003061010
04044847
40 - Length of the PDU in bytes
00 - Message Type ( 00 - SMS Point-to-Point)
00 - TeleService Identifier Tag (SMS Parameter Indentifier)
02 - TeleService Identifier Length (SMS Parameter Length)
10 - TeleService Identifier Value - First 8 bits
02 - TeleService Identifier Value - Second 8 bits
TeleService Identifier - 0x1002 - CDMA Messaging Teleservice
(CMT-95)
02 - Originating Address Tag
07 - Originating Address Length
02 - Originating Address 1st 8 Bits
8C - Originating Address 2nd 8 Bits
E9 - Originating Address 3rd 8 Bits
5D - Originating Address 4th 8 Bits
CC - Originating Address 5th 8 Bits
65 - Originating Address 6th 8 Bits
80 - Originating Address 7th 8 Bits
Digit Mode - 1 Bit
Number Mode - 1 Bit
Number Type - 0 or 3 bits
Number Plan - 0 or 4 bits
Number Fields - 8 Bits
Number Field occurrence of CHARi
CHARi - 4 or 8 bits ( 4 - in case of DTMF encoding, 8 - incase
of ASCII encoding)
Reserved - 0-7 bits
Lets take the 1st and 2nd 8 bits
02 - 0000 0010 ( Digit Mode bit - 0, Number Mode bit - 0)
8C - 1000 1100
As Digit mode bit is set to 0, Number Plan and Number Type is void
(0 bits) in this case.
So the remaining 6 bits of 1st 8bits and the first 2 bits of 2nd
8bit is Number fields
Number fields - 00 0010 10 - 0000 1010 - 0x0A (10 digits)
As Digit mode bit is set to 0, each address digit here is
represented as 4bit DTMF digit
0x8C 0xE9 0x5D 0xCC 0x65 0X80
1000 1100 1110 1001 0101 1101 1100 1100 0110 0101 1000 0000
10 0011 0011 1010 0101 0111 0111 0011 0001 1001 0110 0000 00
3 3 0 5 7 7 3 1 9 6 Last 6 bits
are reserved bits
Originating Address - 3305773196
06 - Bearer Reply Option Tag
01 - Bearer Reply Option Length
FC - First 6 bits Reply Sequence number and last 2 bits reserved set to
0
1111 1100 - 111111 REPLY_SEQ
00 Reserved
08 - Bearer Data Tag
15 - Bearer Data Length
00 - Message Indentifier Tag ( Bearer Data Sub parameter )
03 - Message Indentifier Length
16 - Message Type 4 bits Message Id 4 Bits
8D - Message Id 8 Bits
30 - Message Id 4 Bits, UDH Header indicator 1 Bit, Reserved 3 Bits
How Message Identifier value 16 8D 30 was formed ?
Message type ( 4 bits ) - 1( 0001 - Deliver)
Message Identifier ( 16 bits ) - 26835( 0x68D3)
Header Indicator (1 bit) - 0 (UDH not present in User Data
Subparameter)
Reserved ( 3bits) - 0 (000)
01 - User Data Tag ( Bearer Data Sub parameter )
06 - User Data Length
10 - Message Encoding 5 bits ( 0001 0000 ( 00010 = 2 -> 7-bit ASCII )) &
Number Fields 3 bits ( 000)
24 - Number Fields 5 Bits + User char field 1's 3 bits ( 0010 0100 )
18 - User char field 1's remaining 5 bits + User char field 2's 3 bits
(0001 1000)
30 - User char field 2's remaining 5 bits + User char field 3's 3 bits
(0011 0000)
60 - User char field 3's remaining 5 bits + User char field 4's 3 bits
(0110 0000)
80 - User char field 4's remaining 5 bits + Reserved 3 Bits (1000 0000)
Number Fields: 000 00100 - 04 (4 Character fields)
User Char [1] - 100 00011 - 0x83
User Char [2] - 000 00110 - 0x06
User Char [3] - 000 01100 - 0x0C
User Char [4] - 000 10000 - 0x10
Hex 0x83 0x06 0x0C 0x10
Octets 1000 0011 0000 0110 0000 1100 0001 0000
Septets 1000 001 10000 01 100000 1 1000001
Character A(0x41) A(0x41) A(0x41) A(0x41)
Message content: AAAA
Message Encoding - 2 (00010 - 5 bits)
Number Fields - 4 (0000 0100 - 8 bits)
User characters - 0x83 0x06 0x0C 0x10 ( 8 bits each)
00010 0000 0100 1000 0011 0000 0110 0000 1100 0001 0000
0001 0000 - 0x10
0010 0100 - 0x24
0001 1000 - 0x18
0011 0000 - 0x30
0110 0000 - 0x60
1000 0000 - 0x80 (Last 3 bits set to 0's(reserved bit) to complete
the octets)
03 - Message Center Time Stamp Tag ( Bearer Data Sub parameter )
06 - Message Center Time Stamp Length
all date and time fields contain two 4-bit BCD numbers giving the
decimal value of the field.
10 - Year (2010)
10 - Month (10 - October)
04 - Day
04 - Hour
48 - Minutes
47 - Seconds
Time Stamp 04:48:47 04/10/2010
Decoded Information:
Message Type: Deliver (Incoming Message)
Teleservice: CMT-95
Message Identifier: 26835
Originating Address: 3305773196
Message content: AAAA
Message Center Time Stamp: 04:48:47 04/10/2010
As from the above decoding example we can see there is substantial
differences between the GSM and CDMA SMS specifications and so the SMS
atom needs many additions and needs to be heavily modified to support
also CDMA SMS handling. Currently the oFono sms file unit handles the
common and the GSM technology aspects of the SMS stack along with the
smsutils. The SMS atom has the GSM specific members, segmentation and
queuing logic. The smsutils mainly takes care of encoding/decoding of
the PDUs, which is GSM specific. As the segmentation and queuing logic
and the interface is common for both GSM and CDMA, we could reuse this
common code and add the CDMA handling into it and create a new
cdmasmsutils unit to support the CDMA SMS specifics, much like the
smsutils does already for GSM.
BR,
Rajesh
10 years
Enabling/disabling the GPS part of a Huawei EM770W
by Florian Mayer (Mayer Electronics)
Hello folks,
is it possible to enable / disable the GPS part of a Huawei EM770W 3G
modem through a DBUS command? It is done with the command AT^WPDGP and
AT^WPEND on the modem (tested it on PCUI port). Or is it possible to
send generic AT commands through DBUS?
Regards
Florian Mayer
11 years, 2 months
[PATCH] TODO: Add vCard export to SM/ME stores
by Jaakko Kiviluoto
---
TODO | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index bf2305b..9dcb43f 100644
--- a/TODO
+++ b/TODO
@@ -496,3 +496,14 @@ Miscellaneous
Priority: Low
Complexity: C4
+
+- Enable exporting contact information from vCard data to SM and ME stores.
+ Need to implement a robust vCard parser that can extract at least the
+ fields supported by the existing phonebook module. Functionality should
+ be analoguous to existing import functionality.
+
+ Implements feature request http://bugs.meego.com/show_bug.cgi?id=4476
+
+ Priority: Low
+ Complexity: C1
+ Owner: Jaakko Kiviluoto <jaakko.j.kiviluoto(a)intel.com>
--
1.7.0.4
---------------------------------------------------------------------
Intel Finland Oy
Registered Address: PL 281, 00181 Helsinki
Business Identity Code: 0357606 - 4
Domiciled in Helsinki
This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.
11 years, 4 months
[RFC] Refactoring ISI modem support
by Aki Niemi
Hi All,
I've been working on improving the ISI modem support in oFono, mostly
concentrating on the gisi library, but also on tweaking the drivers
and plugins. You can follow the progress of this 'gisi' branch here:
git://gitorious.org/~akiniemi/meego-cellular/ofono-aki.git
http://meego.gitorious.org/~akiniemi/meego-cellular/ofono-aki/trees/gisi
This is now shaping up enough to call for a bit wider review. Gisi is
mostly where I think it should be, and seems to work. The new
(redesigned, really) version is fixing some of the long-standing
complaints. For instance, it is now using only a single PhoNet socket,
managing indication subscriptions and reachability queries a bit more
intelligently, and is caching modem reachability status and ISI
resource versions for as long as the modem plugin is registered.
Note that not all of the drivers or the n900 plugin have yet been
adapted, but those that are seem to work.
I would really appreciate any comments you might have. Especially
if you are working with gisi or isimodem, please take a look. The plan
is to adapt the rest of the drivers and the n900 plugin in the next
couple of weeks, test some more, rebase, and apply to the
master tree.
Cheers,
Aki
11 years, 6 months
[PATCH] voicecall: Add EmergencyCall property.
by John Mathew
---
doc/voicecall-api.txt | 4 ++++
src/voicecall.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletions(-)
diff --git a/doc/voicecall-api.txt b/doc/voicecall-api.txt
index f0ba316..60c692c 100644
--- a/doc/voicecall-api.txt
+++ b/doc/voicecall-api.txt
@@ -125,3 +125,7 @@ Properties string LineIdentification [readonly]
Icon identifier to be used instead of or together
with the text information.
+
+ boolean EmergencyCall [readonly]
+
+ Contains the indication if the voice call is emergency call or not.
diff --git a/src/voicecall.c b/src/voicecall.c
index bd64432..e39f4b7 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -315,6 +315,20 @@ static void tone_request_finish(struct ofono_voicecall *vc,
g_free(entry);
}
+static gboolean voicecall_isemergency(struct voicecall *v)
+{
+ struct ofono_call *call = v->call;
+ const char *lineid_str;
+
+ lineid_str = phone_number_to_string(&call->phone_number);
+
+ if (g_slist_find_custom(v->vc->en_list, lineid_str,
+ (GCompareFunc) strcmp))
+ return TRUE;
+ else
+ return FALSE;
+}
+
static void append_voicecall_properties(struct voicecall *v,
DBusMessageIter *dict)
{
@@ -322,7 +336,8 @@ static void append_voicecall_properties(struct voicecall *v,
const char *status;
const char *callerid;
const char *timestr;
- ofono_bool_t mpty;
+ ofono_bool_t mpt;
+ dbus_bool_t emergency_call;
status = call_status_to_string(call->status);
callerid = phone_number_to_string(&call->phone_number);
@@ -358,6 +373,14 @@ static void append_voicecall_properties(struct voicecall *v,
if (v->icon_id)
ofono_dbus_dict_append(dict, "Icon", DBUS_TYPE_BYTE,
&v->icon_id);
+
+ if (voicecall_isemergency(v))
+ emergency_call = TRUE;
+ else
+ emergency_call = FALSE;
+
+ ofono_dbus_dict_append(dict, "EmergencyCall", DBUS_TYPE_BOOLEAN,
+ &emergency_call);
}
static DBusMessage *voicecall_get_properties(DBusConnection *conn,
@@ -722,6 +745,15 @@ static void voicecall_set_call_lineid(struct voicecall *v,
OFONO_VOICECALL_INTERFACE,
"LineIdentification",
DBUS_TYPE_STRING, &lineid_str);
+
+ if (voicecall_isemergency(v)) {
+ dbus_bool_t emergency_call = TRUE;
+ ofono_dbus_signal_property_changed(conn, path,
+ OFONO_VOICECALL_INTERFACE,
+ "EmergencyCall",
+ DBUS_TYPE_BOOLEAN,
+ &emergency_call);
+ }
}
static gboolean voicecall_dbus_register(struct voicecall *v)
--
1.7.0.4
11 years, 6 months
[PATCH 0/5] Call Counters (2nd)
by Andras Domokos
Here a proposal for call counters implementation for keeping track
of the total incoming and outgoing call duration counters. Each
established call instance is contributing to either of the call
duration counters. The 2 counters are updated periodically when
there is an established call and the information is stored in
a file. The bookkeeping of the call duration counters are per IMSI
number.
The implementation makes use of the history framework which had to be
expanded with a function for marking the beginning of a voice call.
There is a D-Bus interface to call counters for reading and clearing
the counters.
Andras Domokos (5):
history: expand history API include file
history: expand history API
voicecall: take into use the new history function
plugins: add call counters
doc: call counters API doc
Makefile.am | 3 +
doc/callcounters-api.txt | 18 ++
include/history.h | 3 +
plugins/callcounters.c | 388 ++++++++++++++++++++++++++++++++++++++++++++++
src/history.c | 24 +++
src/ofono.h | 4 +
src/voicecall.c | 3 +
7 files changed, 443 insertions(+), 0 deletions(-)
create mode 100644 doc/callcounters-api.txt
create mode 100644 plugins/callcounters.c
11 years, 6 months
[PATCH 0/3] Persist TX SMS messages
by Kristen Carlson Accardi
This patch series implements a method of persisting pending
outgoing sms messages on disk. Once an sms message has
been submitted to the transmit queue, each pdu in the
message is stored on disk until the driver indicates that
it has been sent.
Each tx_queue_entry is given an id number that represents
it's order in the queue. A subdirectory per entry is
created as id-uuid, in order to preserve order when the
queue is loaded in the event of a crash. Within each
subdirectory, each pdu is saved in order by sequence
number.
When an sms driver is ready for operation, the disk will
be scanned for any saved pending tx sms messages. If there
are any found, they will be loaded from disk and placed
into the queue in order.
Kristen Carlson Accardi (3):
sms: store pending tx pdus on disk
sms: delete sent sms messages from backup
sms: restore pending tx messages from backup
src/ofono.h | 1 +
src/sms.c | 64 ++++++++++++++++++++
src/smsutil.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/smsutil.h | 13 ++++
4 files changed, 258 insertions(+), 0 deletions(-)
--
1.7.2.3
11 years, 6 months
[RESEND PATCHv2 1/2] stemodem: Create network interfaces statically
by Sjur Brændeland
From: Sjur Brændeland <sjur.brandeland(a)stericsson.com>
Changes:
o Restructure code so interfaces are created statically when probe is called,
instead of creating interfaces dynamically at activation.
o Changed debug messages.
o Removed some of the unnecessary initializations at declaration.
o No longer reporting "default gateway" for PtP IP Interface.
o Bugfix: Handle network initiated deactivation.
---
Resend after re-basing with latest commit:
"drivers: explicitly compare pointers to NULL".
drivers/stemodem/gprs-context.c | 149 +++++++++++++++++++++-----------------
1 files changed, 82 insertions(+), 67 deletions(-)
diff --git a/drivers/stemodem/gprs-context.c b/drivers/stemodem/gprs-context.c
index faa3124..7bdcdb8 100644
--- a/drivers/stemodem/gprs-context.c
+++ b/drivers/stemodem/gprs-context.c
@@ -28,6 +28,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
+#include <errno.h>
#include <glib.h>
@@ -65,10 +66,18 @@ struct gprs_context_data {
};
struct conn_info {
+ /*
+ * cid is allocated in oFono Core and is identifying
+ * the Account. cid = 0 indicates that it is currently unused.
+ */
unsigned int cid;
- unsigned int device;
+ /* Id used by CAIF and EPPSD to identify the CAIF channel*/
unsigned int channel_id;
- char interface[10];
+ /* Linux Interface Id */
+ unsigned int ifindex;
+ /* Linux Interface name */
+ char interface[IF_NAMESIZE];
+ gboolean created;
};
struct eppsd_response {
@@ -76,7 +85,6 @@ struct eppsd_response {
char ip_address[IP_ADDR_LEN];
char subnet_mask[IP_ADDR_LEN];
char mtu[IP_ADDR_LEN];
- char default_gateway[IP_ADDR_LEN];
char dns_server1[IP_ADDR_LEN];
char dns_server2[IP_ADDR_LEN];
char p_cscf_server[IP_ADDR_LEN];
@@ -96,8 +104,6 @@ static void start_element_handler(GMarkupParseContext *context,
rsp->current = rsp->subnet_mask;
else if (!strcmp(element_name, "mtu"))
rsp->current = rsp->mtu;
- else if (!strcmp(element_name, "default_gateway"))
- rsp->current = rsp->default_gateway;
else if (!strcmp(element_name, "dns_server") &&
rsp->dns_server1[0] == '\0')
rsp->current = rsp->dns_server1;
@@ -123,7 +129,7 @@ static void text_handler(GMarkupParseContext *context,
if (rsp->current) {
strncpy(rsp->current, text, IP_ADDR_LEN);
- rsp->current[IP_ADDR_LEN] = 0;
+ rsp->current[IP_ADDR_LEN] = '\0';
}
}
@@ -153,8 +159,7 @@ static gint conn_compare_by_cid(gconstpointer a, gconstpointer b)
return 0;
}
-static struct conn_info *conn_info_create(unsigned int device,
- unsigned int channel_id)
+static struct conn_info *conn_info_create(unsigned int channel_id)
{
struct conn_info *connection = g_try_new0(struct conn_info, 1);
@@ -162,7 +167,6 @@ static struct conn_info *conn_info_create(unsigned int device,
return NULL;
connection->cid = 0;
- connection->device = device;
connection->channel_id = channel_id;
return connection;
@@ -171,7 +175,7 @@ static struct conn_info *conn_info_create(unsigned int device,
/*
* Creates a new IP interface for CAIF.
*/
-static gboolean caif_if_create(const char *interface, unsigned int connid)
+static gboolean caif_if_create(struct conn_info *conn)
{
return FALSE;
}
@@ -179,9 +183,8 @@ static gboolean caif_if_create(const char *interface, unsigned int connid)
/*
* Removes IP interface for CAIF.
*/
-static gboolean caif_if_remove(const char *interface, unsigned int connid)
+static void caif_if_remove(struct conn_info *conn)
{
- return FALSE;
}
static void ste_eppsd_down_cb(gboolean ok, GAtResult *result,
@@ -210,21 +213,13 @@ static void ste_eppsd_down_cb(gboolean ok, GAtResult *result,
DBG("Did not find data (used caif device) for"
"connection with cid; %d",
gcd->active_context);
- goto error;
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+ return;
}
conn = l->data;
-
- if (!caif_if_remove(conn->interface, conn->channel_id)) {
- DBG("Failed to remove caif interface %s.",
- conn->interface);
- }
-
conn->cid = 0;
- return;
-
-error:
- CALLBACK_WITH_FAILURE(cb, cbd->data);
+ CALLBACK_WITH_SUCCESS(cb, cbd->data);
}
static void ste_eppsd_up_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -233,7 +228,7 @@ static void ste_eppsd_up_cb(gboolean ok, GAtResult *result, gpointer user_data)
ofono_gprs_context_up_cb_t cb = cbd->cb;
struct ofono_gprs_context *gc = cbd->user;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
- struct conn_info *conn = NULL;
+ struct conn_info *conn;
GAtResultIter iter;
GSList *l;
int i;
@@ -241,17 +236,15 @@ static void ste_eppsd_up_cb(gboolean ok, GAtResult *result, gpointer user_data)
const char *res_string;
const char *dns[MAX_DNS + 1];
struct eppsd_response rsp;
- GMarkupParseContext *context = NULL;
+ GMarkupParseContext *context;
l = g_slist_find_custom(g_caif_devices,
GUINT_TO_POINTER(gcd->active_context),
conn_compare_by_cid);
if (l == NULL) {
- DBG("Did not find data (device and channel id)"
- "for connection with cid; %d",
- gcd->active_context);
- goto error;
+ DBG("CAIF Device gone missing (cid:%d)", gcd->active_context);
+ goto error_no_device;
}
conn = l->data;
@@ -291,31 +284,21 @@ static void ste_eppsd_up_cb(gboolean ok, GAtResult *result, gpointer user_data)
dns[1] = rsp.dns_server2;
dns[2] = NULL;
- sprintf(conn->interface, "caif%u", conn->device);
-
- if (!caif_if_create(conn->interface, conn->channel_id)) {
- ofono_error("Failed to create caif interface %s.",
- conn->interface);
- CALLBACK_WITH_SUCCESS(cb, NULL, FALSE, rsp.ip_address,
- rsp.subnet_mask, rsp.default_gateway,
+ CALLBACK_WITH_SUCCESS(cb, conn->interface, TRUE, rsp.ip_address,
+ rsp.subnet_mask, NULL,
dns, cbd->data);
- } else {
- CALLBACK_WITH_SUCCESS(cb, conn->interface,
- FALSE, rsp.ip_address, rsp.subnet_mask,
- rsp.default_gateway, dns, cbd->data);
- }
-
return;
error:
- DBG("ste_eppsd_up_cb error");
-
if (context)
g_markup_parse_context_free(context);
if (conn)
conn->cid = 0;
+error_no_device:
+ DBG("ste_eppsd_up_cb error");
+ gcd->active_context = 0;
CALLBACK_WITH_FAILURE(cb, NULL, 0, NULL, NULL, NULL, NULL, cbd->data);
}
@@ -325,44 +308,45 @@ static void ste_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data)
ofono_gprs_context_up_cb_t cb = cbd->cb;
struct ofono_gprs_context *gc = cbd->user;
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
- struct cb_data *ncbd = NULL;
+ struct cb_data *ncbd;
char buf[128];
struct conn_info *conn;
GSList *l;
+ l = g_slist_find_custom(g_caif_devices,
+ GUINT_TO_POINTER(gcd->active_context),
+ conn_compare_by_cid);
+
+ if (!l) {
+ DBG("CAIF Device gone missing (cid:%d)", gcd->active_context);
+ goto error_no_device;
+ }
+
+ conn = l->data;
+
if (!ok) {
struct ofono_error error;
+ conn->cid = 0;
gcd->active_context = 0;
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, NULL, 0, NULL, NULL, NULL, NULL, cbd->data);
return;
}
- ncbd = g_memdup(cbd, sizeof(struct cb_data));
-
- l = g_slist_find_custom(g_caif_devices, GUINT_TO_POINTER(0),
- conn_compare_by_cid);
-
- if (l == NULL) {
- DBG("at_cgdcont_cb, no more available devices");
- goto error;
- }
-
- conn = l->data;
- conn->cid = gcd->active_context;
snprintf(buf, sizeof(buf), "AT*EPPSD=1,%u,%u",
conn->channel_id, conn->cid);
+ ncbd = g_memdup(cbd, sizeof(struct cb_data));
if (g_at_chat_send(gcd->chat, buf, NULL,
ste_eppsd_up_cb, ncbd, g_free) > 0)
return;
-error:
g_free(ncbd);
+ conn->cid = 0;
+error_no_device:
gcd->active_context = 0;
-
CALLBACK_WITH_FAILURE(cb, NULL, 0, NULL, NULL,
NULL, NULL, cbd->data);
}
@@ -375,13 +359,32 @@ static void ste_gprs_activate_primary(struct ofono_gprs_context *gc,
struct cb_data *cbd = cb_data_new(cb, data);
char buf[AUTH_BUF_LENGTH];
int len;
+ GSList *l;
+ struct conn_info *conn;
if (cbd == NULL)
- goto error;
+ goto error_no_device;
gcd->active_context = ctx->cid;
cbd->user = gc;
+ /* Find free connection with cid zero */
+ l = g_slist_find_custom(g_caif_devices, GUINT_TO_POINTER(0),
+ conn_compare_by_cid);
+
+ if (!l) {
+ DBG("No more available CAIF devices");
+ goto error_no_device;
+ }
+
+ conn = l->data;
+ conn->cid = ctx->cid;
+
+ if (!conn->created) {
+ DBG("CAIF interface not created (rtnl error?)");
+ goto error;
+ }
+
len = snprintf(buf, sizeof(buf), "AT+CGDCONT=%u,\"IP\"", ctx->cid);
if (ctx->apn)
@@ -405,6 +408,9 @@ static void ste_gprs_activate_primary(struct ofono_gprs_context *gc,
return;
error:
+ conn->cid = 0;
+
+error_no_device:
gcd->active_context = 0;
g_free(cbd);
@@ -431,8 +437,8 @@ static void ste_gprs_deactivate_primary(struct ofono_gprs_context *gc,
conn_compare_by_cid);
if (l == NULL) {
- DBG("at_gprs_deactivate_primary, did not find"
- "data (channel id) for connection with cid; %d", id);
+ DBG("did not find data (channel id) "
+ "for connection with cid; %d", id);
goto error;
}
@@ -446,7 +452,6 @@ static void ste_gprs_deactivate_primary(struct ofono_gprs_context *gc,
error:
g_free(cbd);
-
CALLBACK_WITH_FAILURE(cb, data);
}
@@ -457,6 +462,7 @@ static void ste_cgact_read_cb(gboolean ok, GAtResult *result,
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
gint cid, state;
GAtResultIter iter;
+ GSList *l;
if (!ok)
return;
@@ -480,7 +486,13 @@ static void ste_cgact_read_cb(gboolean ok, GAtResult *result,
ofono_gprs_context_deactivated(gc, gcd->active_context);
gcd->active_context = 0;
- break;
+ /* Mark interface as unused */
+ l = g_slist_find_custom(g_caif_devices, GUINT_TO_POINTER(cid),
+ conn_compare_by_cid);
+ if (l != NULL) {
+ struct conn_info *conn = l->data;
+ conn->cid = 0;
+ }
}
}
@@ -524,9 +536,11 @@ static int ste_gprs_context_probe(struct ofono_gprs_context *gc,
ofono_gprs_context_set_data(gc, gcd);
for (i = 0; i < MAX_CAIF_DEVICES; i++) {
- ci = conn_info_create(i, i+1);
- if (ci)
- g_caif_devices = g_slist_append(g_caif_devices, ci);
+ ci = conn_info_create(i+1);
+ if (!ci)
+ return -ENOMEM;
+ caif_if_create(ci);
+ g_caif_devices = g_slist_append(g_caif_devices, ci);
}
return 0;
@@ -536,6 +550,7 @@ static void ste_gprs_context_remove(struct ofono_gprs_context *gc)
{
struct gprs_context_data *gcd = ofono_gprs_context_get_data(gc);
+ g_slist_foreach(g_caif_devices, (GFunc) caif_if_remove, NULL);
g_slist_foreach(g_caif_devices, (GFunc) g_free, NULL);
g_slist_free(g_caif_devices);
g_caif_devices = NULL;
--
1.7.0.4
11 years, 6 months
[PATCH 1/2] huaweimodem: Add support for radio settings
by Lucas De Marchi
---
Makefile.am | 3 +-
drivers/huaweimodem/huaweimodem.c | 2 +
drivers/huaweimodem/huaweimodem.h | 3 +
drivers/huaweimodem/radio-settings.c | 212 ++++++++++++++++++++++++++++++++++
4 files changed, 219 insertions(+), 1 deletions(-)
create mode 100644 drivers/huaweimodem/radio-settings.c
diff --git a/Makefile.am b/Makefile.am
index a4c47e8..5d39c23 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -180,7 +180,8 @@ builtin_sources += drivers/atmodem/atutil.h \
drivers/huaweimodem/huaweimodem.c \
drivers/huaweimodem/voicecall.c \
drivers/huaweimodem/audio-settings.c \
- drivers/huaweimodem/gprs-context.c
+ drivers/huaweimodem/gprs-context.c \
+ drivers/huaweimodem/radio-settings.c
builtin_modules += calypsomodem
builtin_sources += drivers/atmodem/atutil.h \
diff --git a/drivers/huaweimodem/huaweimodem.c b/drivers/huaweimodem/huaweimodem.c
index c8b6522..8097a9c 100644
--- a/drivers/huaweimodem/huaweimodem.c
+++ b/drivers/huaweimodem/huaweimodem.c
@@ -36,6 +36,7 @@ static int huaweimodem_init(void)
{
huawei_voicecall_init();
huawei_audio_settings_init();
+ huawei_radio_settings_init();
huawei_gprs_context_init();
return 0;
@@ -44,6 +45,7 @@ static int huaweimodem_init(void)
static void huaweimodem_exit(void)
{
huawei_gprs_context_exit();
+ huawei_radio_settings_exit();
huawei_audio_settings_exit();
huawei_voicecall_exit();
}
diff --git a/drivers/huaweimodem/huaweimodem.h b/drivers/huaweimodem/huaweimodem.h
index 03d52ef..596aa08 100644
--- a/drivers/huaweimodem/huaweimodem.h
+++ b/drivers/huaweimodem/huaweimodem.h
@@ -27,5 +27,8 @@ extern void huawei_voicecall_exit();
extern void huawei_audio_settings_init();
extern void huawei_audio_settings_exit();
+extern void huawei_radio_settings_init();
+extern void huawei_radio_settings_exit();
+
extern void huawei_gprs_context_init();
extern void huawei_gprs_context_exit();
diff --git a/drivers/huaweimodem/radio-settings.c b/drivers/huaweimodem/radio-settings.c
new file mode 100644
index 0000000..7f0b223
--- /dev/null
+++ b/drivers/huaweimodem/radio-settings.c
@@ -0,0 +1,212 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/radio-settings.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "huaweimodem.h"
+
+static const char *none_prefix[] = { NULL };
+static const char *xrat_prefix[] = { "^SYSCFG:", NULL };
+
+struct radio_settings_data {
+ GAtChat *chat;
+};
+
+static void xrat_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct cb_data *cbd = user_data;
+ ofono_radio_settings_rat_mode_query_cb_t cb = cbd->cb;
+ enum ofono_radio_access_mode mode;
+ struct ofono_error error;
+ GAtResultIter iter;
+ int value;
+
+ decode_at_error(&error, g_at_result_final_response(result));
+
+ if (!ok) {
+ cb(&error, -1, cbd->data);
+ return;
+ }
+
+ g_at_result_iter_init(&iter, result);
+
+ if (g_at_result_iter_next(&iter, "^SYSCFG:") == FALSE)
+ goto error;
+
+ if (g_at_result_iter_next_number(&iter, &value) == FALSE)
+ goto error;
+
+ switch (value) {
+ case 2:
+ mode = OFONO_RADIO_ACCESS_MODE_ANY;
+ break;
+ case 13:
+ mode = OFONO_RADIO_ACCESS_MODE_GSM;
+ break;
+ case 14:
+ mode = OFONO_RADIO_ACCESS_MODE_UMTS;
+ break;
+ default:
+ CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+ return;
+ }
+
+ cb(&error, mode, cbd->data);
+
+ return;
+
+error:
+ CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
+
+static void huawei_query_rat_mode(struct ofono_radio_settings *rs,
+ ofono_radio_settings_rat_mode_query_cb_t cb,
+ void *data)
+{
+ struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+ struct cb_data *cbd = cb_data_new(cb, data);
+
+ if (g_at_chat_send(rsd->chat, "AT^SYSCFG?", xrat_prefix,
+ xrat_query_cb, cbd, g_free) == 0) {
+ CALLBACK_WITH_FAILURE(cb, -1, data);
+ g_free(cbd);
+ }
+}
+
+static void xrat_modify_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct cb_data *cbd = user_data;
+ ofono_radio_settings_rat_mode_set_cb_t cb = cbd->cb;
+ struct ofono_error error;
+
+ decode_at_error(&error, g_at_result_final_response(result));
+ cb(&error, cbd->data);
+}
+
+static void huawei_set_rat_mode(struct ofono_radio_settings *rs,
+ enum ofono_radio_access_mode mode,
+ ofono_radio_settings_rat_mode_set_cb_t cb,
+ void *data)
+{
+ struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+ struct cb_data *cbd = cb_data_new(cb, data);
+ char buf[40];
+ int value = 2;
+
+ switch (mode) {
+ case OFONO_RADIO_ACCESS_MODE_ANY:
+ value = 2;
+ break;
+ case OFONO_RADIO_ACCESS_MODE_GSM:
+ value = 13;
+ break;
+ case OFONO_RADIO_ACCESS_MODE_UMTS:
+ value = 14;
+ break;
+ case OFONO_RADIO_ACCESS_MODE_LTE:
+ goto error;
+ }
+
+ snprintf(buf, sizeof(buf), "AT^SYSCFG=%u,0,3FFFFFFF,2,4", value);
+
+ if (g_at_chat_send(rsd->chat, buf, none_prefix,
+ xrat_modify_cb, cbd, g_free) > 0)
+ return;
+
+error:
+ CALLBACK_WITH_FAILURE(cb, data);
+ g_free(cbd);
+}
+
+static void xrat_support_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct ofono_radio_settings *rs = user_data;
+
+ if (!ok)
+ return;
+
+ ofono_radio_settings_register(rs);
+}
+
+static int huawei_radio_settings_probe(struct ofono_radio_settings *rs,
+ unsigned int vendor, void *data)
+{
+ GAtChat *chat = data;
+ struct radio_settings_data *rsd;
+
+ rsd = g_try_new0(struct radio_settings_data, 1);
+ if (rsd == NULL)
+ return -ENOMEM;
+
+ rsd->chat = g_at_chat_clone(chat);
+
+ ofono_radio_settings_set_data(rs, rsd);
+
+ g_at_chat_send(rsd->chat, "AT^SYSCFG=?", xrat_prefix,
+ xrat_support_cb, rs, NULL);
+
+ return 0;
+}
+
+static void huawei_radio_settings_remove(struct ofono_radio_settings *rs)
+{
+ struct radio_settings_data *rsd = ofono_radio_settings_get_data(rs);
+
+ ofono_radio_settings_set_data(rs, NULL);
+
+ g_at_chat_unref(rsd->chat);
+ g_free(rsd);
+}
+
+static struct ofono_radio_settings_driver driver = {
+ .name = "huaweimodem",
+ .probe = huawei_radio_settings_probe,
+ .remove = huawei_radio_settings_remove,
+ .query_rat_mode = huawei_query_rat_mode,
+ .set_rat_mode = huawei_set_rat_mode
+};
+
+void huawei_radio_settings_init()
+{
+ ofono_radio_settings_driver_register(&driver);
+}
+
+void huawei_radio_settings_exit()
+{
+ ofono_radio_settings_driver_unregister(&driver);
+}
--
1.7.3.2
11 years, 6 months